File indexing completed on 2025-12-17 09:20:59
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "PHActsTrkFitter.h"
0010
0011 #include "ActsPropagator.h"
0012 #include "MakeSourceLinks.h"
0013
0014 #include <tpc/TpcDistortionCorrectionContainer.h>
0015
0016
0017 #include <trackbase/Calibrator.h>
0018 #include <trackbase/ClusterErrorPara.h>
0019 #include <trackbase/InttDefs.h>
0020 #include <trackbase/MvtxDefs.h>
0021 #include <trackbase/TpcDefs.h>
0022 #include <trackbase/TrkrCluster.h>
0023 #include <trackbase/TrkrClusterContainer.h>
0024
0025 #include <trackbase_historic/ActsTransformations.h>
0026 #include <trackbase_historic/SvtxAlignmentStateMap_v1.h>
0027 #include <trackbase_historic/SvtxTrackMap_v2.h>
0028
0029 #include <trackbase_historic/SvtxTrackState_v3.h>
0030 #include <trackbase_historic/SvtxTrack_v4.h>
0031 #include <trackbase_historic/TrackSeed.h>
0032 #include <trackbase_historic/TrackSeedContainer.h>
0033 #include <trackbase_historic/TrackSeedHelper.h>
0034
0035 #include <g4detectors/PHG4TpcGeomContainer.h>
0036
0037 #include <micromegas/MicromegasDefs.h>
0038
0039 #include <ffamodules/CDBInterface.h>
0040
0041 #include <fun4all/Fun4AllReturnCodes.h>
0042
0043 #include <phool/PHCompositeNode.h>
0044 #include <phool/PHDataNode.h>
0045 #include <phool/PHNode.h>
0046 #include <phool/PHNodeIterator.h>
0047 #include <phool/PHObject.h>
0048 #include <phool/PHTimer.h>
0049 #include <phool/getClass.h>
0050 #include <phool/phool.h>
0051
0052 #include <Acts/EventData/MultiTrajectory.hpp>
0053 #include <Acts/EventData/MultiTrajectoryHelpers.hpp>
0054 #include <Acts/EventData/SourceLink.hpp>
0055 #include <Acts/EventData/TrackParameters.hpp>
0056 #include <Acts/Surfaces/PerigeeSurface.hpp>
0057 #include <Acts/Surfaces/Surface.hpp>
0058 #include <Acts/TrackFitting/GainMatrixSmoother.hpp>
0059 #include <Acts/TrackFitting/GainMatrixUpdater.hpp>
0060
0061 #include <cmath>
0062 #include <filesystem>
0063 #include <iostream>
0064 #include <vector>
0065
0066 namespace
0067 {
0068
0069 inline bool is_valid(const Acts::Vector3& vec)
0070 {
0071 return !(std::isnan(vec.x()) || std::isnan(vec.y()) || std::isnan(vec.z()));
0072 }
0073 template <class T>
0074 inline T square(const T& x)
0075 {
0076 return x * x;
0077 }
0078 }
0079
0080 #include <trackbase/alignmentTransformationContainer.h>
0081 #include <Eigen/Dense>
0082 #include <Eigen/Geometry>
0083
0084 PHActsTrkFitter::PHActsTrkFitter(const std::string& name)
0085 : SubsysReco(name)
0086 {
0087 }
0088
0089 int PHActsTrkFitter::InitRun(PHCompositeNode* topNode)
0090 {
0091 if (Verbosity() > 1)
0092 {
0093 std::cout << "Setup PHActsTrkFitter" << std::endl;
0094 }
0095
0096 if (createNodes(topNode) != Fun4AllReturnCodes::EVENT_OK)
0097 {
0098 return Fun4AllReturnCodes::ABORTEVENT;
0099 }
0100
0101 if (getNodes(topNode) != Fun4AllReturnCodes::EVENT_OK)
0102 {
0103 return Fun4AllReturnCodes::ABORTEVENT;
0104 }
0105
0106
0107 m_alignStates.loadNodes(topNode);
0108 m_alignStates.verbosity(Verbosity());
0109 m_alignStates.fieldMap(m_fieldMap);
0110
0111
0112 std::istringstream stringline(m_fieldMap);
0113 stringline >> fieldstrength;
0114 if (!stringline.fail())
0115 {
0116 m_ConstField = true;
0117 }
0118
0119 auto level = Acts::Logging::FATAL;
0120 if (Verbosity() > 5)
0121 {
0122 level = Acts::Logging::VERBOSE;
0123 }
0124
0125 m_fitCfg.fit = ActsTrackFittingAlgorithm::makeKalmanFitterFunction(
0126 m_tGeometry->geometry().tGeometry,
0127 m_tGeometry->geometry().magField,
0128 true, true, 0.0, Acts::FreeToBoundCorrection(), *Acts::getDefaultLogger("Kalman", level));
0129
0130 m_fitCfg.dFit = ActsTrackFittingAlgorithm::makeDirectedKalmanFitterFunction(
0131 m_tGeometry->geometry().tGeometry,
0132 m_tGeometry->geometry().magField);
0133
0134 MaterialSurfaceSelector selector;
0135 if (m_fitSiliconMMs || m_directNavigation)
0136 {
0137 m_tGeometry->geometry().tGeometry->visitSurfaces(selector,false);
0138
0139 m_materialSurfaces = selector.surfaces;
0140 }
0141
0142 m_outlierFinder.verbosity = Verbosity();
0143 std::map<long unsigned int, float> chi2Cuts;
0144 chi2Cuts.insert(std::make_pair(10, 4));
0145 chi2Cuts.insert(std::make_pair(12, 4));
0146 chi2Cuts.insert(std::make_pair(14, 9));
0147 chi2Cuts.insert(std::make_pair(16, 4));
0148 m_outlierFinder.chi2Cuts = chi2Cuts;
0149 if (m_useOutlierFinder)
0150 {
0151 m_outlierFinder.m_tGeometry = m_tGeometry;
0152 m_fitCfg.fit->outlierFinder(m_outlierFinder);
0153 }
0154
0155 if (m_timeAnalysis)
0156 {
0157 m_timeFile = new TFile(std::string(Name() + ".root").c_str(),
0158 "RECREATE");
0159 h_eventTime = new TH1F("h_eventTime", ";time [ms]",
0160 100000, 0, 10000);
0161 h_fitTime = new TH2F("h_fitTime", ";p_{T} [GeV];time [ms]",
0162 80, 0, 40, 100000, 0, 1000);
0163 h_updateTime = new TH1F("h_updateTime", ";time [ms]",
0164 100000, 0, 1000);
0165
0166 h_rotTime = new TH1F("h_rotTime", ";time [ms]",
0167 100000, 0, 1000);
0168 h_stateTime = new TH1F("h_stateTime", ";time [ms]",
0169 100000, 0, 1000);
0170 }
0171
0172 if (m_actsEvaluator)
0173 {
0174 m_evaluator = std::make_unique<ActsEvaluator>(m_evalname);
0175 m_evaluator->Init(topNode);
0176 if(m_actsEvaluator && !m_simActsEvaluator)
0177 {
0178 m_evaluator->isData();
0179 }
0180 m_evaluator->verbosity(Verbosity());
0181 }
0182
0183 _tpccellgeo = findNode::getClass<PHG4TpcGeomContainer>(topNode, "TPCGEOMCONTAINER");
0184 if (!_tpccellgeo)
0185 {
0186 std::cout << PHWHERE << " unable to find DST node TPCGEOMCONTAINER" << std::endl;
0187 return Fun4AllReturnCodes::ABORTRUN;
0188 }
0189
0190 if (Verbosity() > 1)
0191 {
0192 std::cout << "Finish PHActsTrkFitter Setup" << std::endl;
0193 }
0194
0195 return Fun4AllReturnCodes::EVENT_OK;
0196 }
0197
0198 int PHActsTrkFitter::process_event(PHCompositeNode* topNode)
0199 {
0200 PHTimer eventTimer("eventTimer");
0201 eventTimer.stop();
0202 eventTimer.restart();
0203 m_nBadFits = 0;
0204 m_event++;
0205
0206 auto logLevel = Acts::Logging::FATAL;
0207
0208 if (m_actsEvaluator)
0209 {
0210 m_evaluator->next_event(topNode);
0211 }
0212
0213 if (Verbosity() > 1)
0214 {
0215 std::cout << PHWHERE << "Events processed: " << m_event << std::endl;
0216 std::cout << "Start PHActsTrkFitter::process_event" << std::endl;
0217 if (Verbosity() > 4)
0218 {
0219 logLevel = Acts::Logging::VERBOSE;
0220 }
0221 }
0222
0223
0224 m_trackMap->Reset();
0225
0226 loopTracks(logLevel);
0227
0228 eventTimer.stop();
0229 auto eventTime = eventTimer.get_accumulated_time();
0230
0231 if (Verbosity() > 1)
0232 {
0233 std::cout << "PHActsTrkFitter total event time "
0234 << eventTime << std::endl;
0235 }
0236
0237 if (m_timeAnalysis)
0238 {
0239 h_eventTime->Fill(eventTime);
0240 }
0241
0242 if (Verbosity() > 1)
0243 {
0244 std::cout << "PHActsTrkFitter::process_event finished"
0245 << std::endl;
0246 }
0247
0248
0249 if (Verbosity() > 0)
0250 {
0251 std::cout << "The Acts track fitter had " << m_nBadFits
0252 << " fits return an error" << std::endl;
0253 std::cout << " seed map size " << m_seedMap->size() << std::endl;
0254
0255 std::cout << " SvtxTrackMap size is now " << m_trackMap->size()
0256 << std::endl;
0257 }
0258
0259 return Fun4AllReturnCodes::EVENT_OK;
0260 }
0261
0262 int PHActsTrkFitter::ResetEvent(PHCompositeNode* )
0263 {
0264 if (Verbosity() > 1)
0265 {
0266 std::cout << "Reset PHActsTrkFitter" << std::endl;
0267 }
0268
0269 return Fun4AllReturnCodes::EVENT_OK;
0270 }
0271
0272 int PHActsTrkFitter::End(PHCompositeNode* )
0273 {
0274 if (m_timeAnalysis)
0275 {
0276 m_timeFile->cd();
0277 h_fitTime->Write();
0278 h_eventTime->Write();
0279 h_rotTime->Write();
0280 h_stateTime->Write();
0281 h_updateTime->Write();
0282 m_timeFile->Write();
0283 m_timeFile->Close();
0284 }
0285
0286 if (m_actsEvaluator)
0287 {
0288 m_evaluator->End();
0289 }
0290 if(m_useOutlierFinder)
0291 {
0292 m_outlierFinder.Write();
0293 }
0294 if (Verbosity() > 0)
0295 {
0296 std::cout << "Finished PHActsTrkFitter" << std::endl;
0297 }
0298 return Fun4AllReturnCodes::EVENT_OK;
0299 }
0300
0301 void PHActsTrkFitter::loopTracks(Acts::Logging::Level logLevel)
0302 {
0303 auto logger = Acts::getDefaultLogger("PHActsTrkFitter", logLevel);
0304
0305 for (auto track : *m_seedMap)
0306 {
0307 if (!track)
0308 {
0309 continue;
0310 }
0311
0312 unsigned int tpcid = track->get_tpc_seed_index();
0313 unsigned int siid = track->get_silicon_seed_index();
0314
0315
0316
0317 short silicon_crossing = SHRT_MAX;
0318 auto siseed = m_siliconSeeds->get(siid);
0319 if(siseed)
0320 {
0321 silicon_crossing = siseed->get_crossing();
0322 }
0323 short crossing = silicon_crossing;
0324 short int crossing_estimate = crossing;
0325
0326 if(m_enable_crossing_estimate)
0327 {
0328 crossing_estimate = track->get_crossing_estimate();
0329 }
0330
0331
0332
0333
0334 if (m_fitSiliconMMs)
0335 {
0336 if( (siid == std::numeric_limits<unsigned int>::max()) || (silicon_crossing == SHRT_MAX))
0337 {
0338 continue;
0339 }
0340 }
0341
0342
0343 if(!siseed)
0344 {
0345 crossing = 0;
0346 }
0347
0348 if (Verbosity() > 1)
0349 {
0350 if(siseed)
0351 {
0352 std::cout << "tpc and si id " << tpcid << ", " << siid << " silicon_crossing " << silicon_crossing
0353 << " crossing " << crossing << " crossing estimate " << crossing_estimate << std::endl;
0354 }
0355 }
0356
0357 auto tpcseed = m_tpcSeeds->get(tpcid);
0358
0359
0360 if (!tpcseed)
0361 {
0362 std::cout << "no tpc seed" << std::endl;
0363 continue;
0364 }
0365
0366 if (Verbosity() > 0)
0367 {
0368 if (siseed)
0369 {
0370 const auto si_position = TrackSeedHelper::get_xyz(siseed);
0371 const auto tpc_position = TrackSeedHelper::get_xyz(tpcseed);
0372 std::cout << " silicon seed position is (x,y,z) = " << si_position.x() << " " << si_position.y() << " " << si_position.z() << std::endl;
0373 std::cout << " tpc seed position is (x,y,z) = " << tpc_position.x() << " " << tpc_position.y() << " " << tpc_position.z() << std::endl;
0374 }
0375 }
0376
0377 PHTimer trackTimer("TrackTimer");
0378 trackTimer.stop();
0379 trackTimer.restart();
0380
0381 if (Verbosity() > 1 && siseed)
0382 {
0383 std::cout << " m_pp_mode " << m_pp_mode << " m_enable_crossing_estimate " << m_enable_crossing_estimate
0384 << " INTT crossing " << crossing << " crossing_estimate " << crossing_estimate << std::endl;
0385 }
0386
0387 short int this_crossing = crossing;
0388 bool use_estimate = false;
0389 short int nvary = 0;
0390 std::vector<float> chisq_ndf;
0391 std::vector<SvtxTrack_v4> svtx_vec;
0392
0393 if(m_pp_mode)
0394 {
0395 if (m_enable_crossing_estimate && crossing == SHRT_MAX)
0396 {
0397
0398
0399 use_estimate = true;
0400 nvary = max_bunch_search;
0401 if (Verbosity() > 1)
0402 {
0403 std::cout << " No INTT crossing: use crossing_estimate " << crossing_estimate << " with nvary " << nvary << std::endl;
0404 }
0405 }
0406 else
0407 {
0408
0409 crossing_estimate = crossing;
0410 }
0411 }
0412 else
0413 {
0414
0415 if(siseed && silicon_crossing != 0)
0416 {
0417 crossing = 0;
0418
0419 }
0420 crossing_estimate = crossing;
0421 }
0422
0423
0424
0425
0426
0427 for (short int ivary = -nvary; ivary <= nvary; ++ivary)
0428 {
0429 this_crossing = crossing_estimate + ivary;
0430
0431 if (Verbosity() > 1)
0432 {
0433 std::cout << " nvary " << nvary << " trial fit with ivary " << ivary << " this_crossing = " << this_crossing << std::endl;
0434 }
0435
0436 ActsTrackFittingAlgorithm::MeasurementContainer measurements;
0437
0438 SourceLinkVec sourceLinks;
0439
0440 MakeSourceLinks makeSourceLinks;
0441 makeSourceLinks.initialize(_tpccellgeo);
0442 makeSourceLinks.setVerbosity(Verbosity());
0443 makeSourceLinks.set_pp_mode(m_pp_mode);
0444 for(const auto& layer : m_ignoreLayer)
0445 {
0446 makeSourceLinks.ignoreLayer(layer);
0447 }
0448
0449
0450 makeSourceLinks.resetTransientTransformMap(
0451 m_alignmentTransformationMapTransient,
0452 m_transient_id_set,
0453 m_tGeometry);
0454
0455 if (m_use_clustermover)
0456 {
0457
0458 if (siseed && !m_ignoreSilicon)
0459 {
0460
0461 sourceLinks = makeSourceLinks.getSourceLinksClusterMover(
0462 siseed,
0463 measurements,
0464 m_clusterContainer,
0465 m_tGeometry,
0466 m_globalPositionWrapper,
0467 this_crossing);
0468 }
0469
0470
0471 const auto tpcSourceLinks = makeSourceLinks.getSourceLinksClusterMover(
0472 tpcseed,
0473 measurements,
0474 m_clusterContainer,
0475 m_tGeometry,
0476 m_globalPositionWrapper,
0477 this_crossing);
0478
0479
0480 sourceLinks.insert(sourceLinks.end(), tpcSourceLinks.begin(), tpcSourceLinks.end());
0481
0482 } else {
0483
0484
0485 if(Verbosity() > 1)
0486 { std::cout << "Calling getSourceLinks for si seed, siid " << siid << " and tpcid " << tpcid << std::endl; }
0487
0488 if (siseed && !m_ignoreSilicon)
0489 {
0490
0491 sourceLinks = makeSourceLinks.getSourceLinks(
0492 siseed,
0493 measurements,
0494 m_clusterContainer,
0495 m_tGeometry,
0496 m_globalPositionWrapper,
0497 m_alignmentTransformationMapTransient,
0498 m_transient_id_set,
0499 this_crossing);
0500 }
0501
0502 if(Verbosity() > 1)
0503 { std::cout << "Calling getSourceLinks for tpc seed, siid " << siid << " and tpcid " << tpcid << std::endl; }
0504
0505
0506 const auto tpcSourceLinks = makeSourceLinks.getSourceLinks(
0507 tpcseed,
0508 measurements,
0509 m_clusterContainer,
0510 m_tGeometry,
0511 m_globalPositionWrapper,
0512 m_alignmentTransformationMapTransient,
0513 m_transient_id_set,
0514 this_crossing);
0515
0516
0517 sourceLinks.insert(sourceLinks.end(), tpcSourceLinks.begin(), tpcSourceLinks.end());
0518 }
0519
0520
0521 m_transient_geocontext = m_alignmentTransformationMapTransient;
0522
0523
0524 Acts::Vector3 position(0, 0, 0);
0525 if (siseed)
0526 {
0527 position = TrackSeedHelper::get_xyz(siseed)*Acts::UnitConstants::cm;
0528 }
0529 if(!siseed || !is_valid(position) || m_ignoreSilicon)
0530 {
0531 position = TrackSeedHelper::get_xyz(tpcseed)*Acts::UnitConstants::cm;
0532 }
0533 if (!is_valid(position))
0534 {
0535 if(Verbosity() > 4)
0536 {
0537 std::cout << "Invalid position of " << position.transpose() << std::endl;
0538 }
0539 continue;
0540 }
0541
0542 if (sourceLinks.empty())
0543 {
0544 continue;
0545 }
0546
0547
0548 SurfacePtrVec surfaces_tmp;
0549 SurfacePtrVec surfaces;
0550 if (m_fitSiliconMMs || m_directNavigation)
0551 {
0552 sourceLinks = getSurfaceVector(sourceLinks, surfaces_tmp);
0553
0554
0555 if (surfaces_tmp.empty())
0556 {
0557 continue;
0558 }
0559
0560 for (const auto& surface_apr : m_materialSurfaces)
0561 {
0562 if(m_forceSiOnlyFit)
0563 {
0564 if(surface_apr->geometryId().volume() >12)
0565 {
0566 continue;
0567 }
0568 }
0569 bool pop_flag = false;
0570 if(surface_apr->geometryId().approach() == 1)
0571 {
0572 surfaces.push_back(surface_apr);
0573 }
0574 else
0575 {
0576 pop_flag = true;
0577 for (const auto& surface_sns: surfaces_tmp)
0578 {
0579 if (surface_apr->geometryId().volume() == surface_sns->geometryId().volume())
0580 {
0581 if ( surface_apr->geometryId().layer()==surface_sns->geometryId().layer())
0582 {
0583 pop_flag = false;
0584 surfaces.push_back(surface_sns);
0585 }
0586 }
0587 }
0588 if (!pop_flag)
0589 {
0590 surfaces.push_back(surface_apr);
0591 }
0592 else
0593 {
0594 surfaces.pop_back();
0595 pop_flag = false;
0596 }
0597 if (surface_apr->geometryId().volume() == 12&& surface_apr->geometryId().layer()==8)
0598 {
0599 for (const auto& surface_sns: surfaces_tmp)
0600 {
0601 if (14 == surface_sns->geometryId().volume())
0602 {
0603 surfaces.push_back(surface_sns);
0604 }
0605 }
0606 }
0607 }
0608 }
0609 checkSurfaceVec(surfaces);
0610 if (Verbosity() > 1)
0611 {
0612 for (const auto& surf : surfaces)
0613 {
0614 std::cout << "Surface vector : " << surf->geometryId() << std::endl;
0615 }
0616 }
0617
0618 if (m_fitSiliconMMs)
0619 {
0620
0621 if (m_useMicromegas &&
0622 std::none_of(surfaces.begin(), surfaces.end(), [this](const auto& surface)
0623 { return m_tGeometry->maps().isMicromegasSurface(surface); }))
0624 {
0625 continue;
0626 }
0627 }
0628 }
0629
0630 float px = std::numeric_limits<float>::quiet_NaN();
0631 float py = std::numeric_limits<float>::quiet_NaN();
0632 float pz = std::numeric_limits<float>::quiet_NaN();
0633
0634
0635 float seedphi = 0;
0636 float seedtheta = 0;
0637 float seedeta = 0;
0638 if(siseed)
0639 {
0640 seedphi = siseed->get_phi();
0641 seedtheta = siseed->get_theta();
0642 seedeta = siseed->get_eta();
0643 }
0644 else
0645 {
0646 seedphi = tpcseed->get_phi();
0647 seedtheta = tpcseed->get_theta();
0648 seedeta = tpcseed->get_eta();
0649 }
0650
0651 float seedpt = tpcseed->get_pt();
0652
0653 if (m_ConstField)
0654 {
0655 float pt = fabs(1. / tpcseed->get_qOverR()) * (0.3 / 100) * fieldstrength;
0656 float phi = seedphi;
0657 float eta = seedeta;
0658 float theta = seedtheta;
0659 px = pt * std::cos(phi);
0660 py = pt * std::sin(phi);
0661 pz = pt * std::cosh(eta) * std::cos(theta);
0662 } else {
0663 px = seedpt * std::cos(seedphi);
0664 py = seedpt * std::sin(seedphi);
0665 pz = seedpt * std::cosh(seedeta) * std::cos(seedtheta);
0666 }
0667
0668 Acts::Vector3 momentum(px, py, pz);
0669 if (!is_valid(momentum))
0670 {
0671 if(Verbosity() > 4)
0672 {
0673 std::cout << "Invalid momentum of " << momentum.transpose() << std::endl;
0674 }
0675 continue;
0676 }
0677
0678 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>( position);
0679
0680 Acts::Vector4 actsFourPos(position(0), position(1), position(2), 10 * Acts::UnitConstants::ns);
0681 Acts::BoundSquareMatrix cov = setDefaultCovariance();
0682
0683 int charge = tpcseed->get_charge();
0684
0685
0686 auto seed = ActsTrackFittingAlgorithm::TrackParameters::create(
0687 pSurface,
0688 m_transient_geocontext,
0689 actsFourPos,
0690 momentum,
0691 charge / momentum.norm(),
0692 cov,
0693 Acts::ParticleHypothesis::pion())
0694 .value();
0695
0696 if (Verbosity() > 2)
0697 {
0698 printTrackSeed(seed);
0699 }
0700
0701
0702 Acts::PropagatorPlainOptions ppPlainOptions;
0703
0704 auto calibptr = std::make_unique<Calibrator>();
0705 CalibratorAdapter calibrator{*calibptr, measurements};
0706
0707 auto magcontext = m_tGeometry->geometry().magFieldContext;
0708 auto calibcontext = m_tGeometry->geometry().calibContext;
0709
0710 ActsTrackFittingAlgorithm::GeneralFitterOptions
0711 kfOptions{
0712 m_transient_geocontext,
0713 magcontext,
0714 calibcontext,
0715 pSurface.get(),
0716 ppPlainOptions};
0717
0718 PHTimer fitTimer("FitTimer");
0719 fitTimer.stop();
0720 fitTimer.restart();
0721
0722 auto trackContainer = std::make_shared<Acts::VectorTrackContainer>();
0723 auto trackStateContainer = std::make_shared<Acts::VectorMultiTrajectory>();
0724 ActsTrackFittingAlgorithm::TrackContainer tracks(trackContainer, trackStateContainer);
0725
0726 if(Verbosity() > 1)
0727 { std::cout << "Calling fitTrack for track with siid " << siid << " tpcid " << tpcid << " crossing " << crossing << std::endl; }
0728
0729 auto result = fitTrack(sourceLinks, seed, kfOptions, surfaces, calibrator, tracks);
0730 fitTimer.stop();
0731
0732 if (Verbosity() > 1)
0733 {
0734 const auto fitTime = fitTimer.get_accumulated_time();
0735 std::cout << "PHActsTrkFitter Acts fit time " << fitTime << std::endl;
0736 }
0737
0738
0739 if (result.ok())
0740 {
0741 if (use_estimate)
0742 {
0743
0744
0745
0746 SvtxTrack_v4 newTrack;
0747 newTrack.set_tpc_seed(tpcseed);
0748 newTrack.set_crossing(this_crossing);
0749 newTrack.set_silicon_seed(siseed);
0750
0751 if (getTrackFitResult(result, track, &newTrack, tracks, measurements))
0752 {
0753 float chi2ndf = newTrack.get_quality();
0754 chisq_ndf.push_back(chi2ndf);
0755 svtx_vec.push_back(newTrack);
0756 if (Verbosity() > 1)
0757 {
0758 std::cout << " tpcid " << tpcid << " siid " << siid << " ivary " << ivary << " this_crossing " << this_crossing << " chi2ndf " << chi2ndf << std::endl;
0759 }
0760 }
0761
0762 if (ivary != nvary)
0763 {
0764 if(Verbosity() > 3)
0765 {
0766 std::cout << "Skipping track fit for trial variation" << std::endl;
0767 }
0768 continue;
0769 }
0770
0771
0772 if (Verbosity() > 1)
0773 {
0774 std::cout << "Finished with trial fits, chisq_ndf size is " << chisq_ndf.size() << " chisq_ndf values are:" << std::endl;
0775 }
0776 float best_chisq = 1000.0;
0777 short int best_ivary = 0;
0778 for (unsigned int i = 0; i < chisq_ndf.size(); ++i)
0779 {
0780 if (chisq_ndf[i] < best_chisq)
0781 {
0782 best_chisq = chisq_ndf[i];
0783 best_ivary = i;
0784 }
0785 if (Verbosity() > 1)
0786 {
0787 std::cout << " trial " << i << " chisq_ndf " << chisq_ndf[i] << " best_chisq " << best_chisq << " best_ivary " << best_ivary << std::endl;
0788 }
0789 }
0790 unsigned int trid = m_trackMap->size();
0791 svtx_vec[best_ivary].set_id(trid);
0792
0793 m_trackMap->insertWithKey(&svtx_vec[best_ivary], trid);
0794 }
0795 else
0796 {
0797 SvtxTrack_v4 newTrack;
0798 newTrack.set_tpc_seed(tpcseed);
0799 newTrack.set_crossing(this_crossing);
0800 newTrack.set_silicon_seed(siseed);
0801
0802 if (m_fitSiliconMMs)
0803 {
0804 unsigned int trid = m_directedTrackMap->size();
0805 newTrack.set_id(trid);
0806
0807 if (getTrackFitResult(result, track, &newTrack, tracks, measurements))
0808 {
0809
0810
0811 m_directedTrackMap->insertWithKey(&newTrack, trid);
0812 }
0813
0814 }
0815 else
0816 {
0817 unsigned int trid = m_trackMap->size();
0818 newTrack.set_id(trid);
0819
0820 if (getTrackFitResult(result, track, &newTrack, tracks, measurements))
0821 {
0822 m_trackMap->insertWithKey(&newTrack, trid);
0823 }
0824 }
0825 }
0826
0827
0828
0829
0830 }
0831 else if (!m_fitSiliconMMs)
0832 {
0833
0834 m_nBadFits++;
0835 if (Verbosity() > 1)
0836 {
0837 std::cout << "Track fit failed for track " << m_seedMap->find(track)
0838 << " with Acts error message "
0839 << result.error() << ", " << result.error().message()
0840 << std::endl;
0841 }
0842 }
0843 }
0844
0845 trackTimer.stop();
0846 auto trackTime = trackTimer.get_accumulated_time();
0847
0848 if (Verbosity() > 1)
0849 {
0850 std::cout << "PHActsTrkFitter total single track time " << trackTime << std::endl;
0851 }
0852 }
0853
0854 return;
0855 }
0856
0857 bool PHActsTrkFitter::getTrackFitResult(
0858 const FitResult& fitOutput,
0859 TrackSeed* seed, SvtxTrack* track,
0860 const ActsTrackFittingAlgorithm::TrackContainer& tracks,
0861 const ActsTrackFittingAlgorithm::MeasurementContainer& measurements)
0862 {
0863
0864
0865 std::vector<Acts::MultiTrajectoryTraits::IndexType> trackTips;
0866 trackTips.reserve(1);
0867 const auto& outtrack = fitOutput.value();
0868 if (outtrack.hasReferenceSurface())
0869 {
0870 trackTips.emplace_back(outtrack.tipIndex());
0871 Trajectory::IndexedParameters indexedParams;
0872
0873
0874 Acts::BoundTrackParameters parameters = ActsExamples::TrackParameters(outtrack.referenceSurface().getSharedPtr(),
0875 outtrack.parameters(), outtrack.covariance(), outtrack.particleHypothesis());
0876
0877 indexedParams.emplace(
0878 outtrack.tipIndex(),
0879 ActsExamples::TrackParameters{outtrack.referenceSurface().getSharedPtr(),
0880 outtrack.parameters(), outtrack.covariance(), outtrack.particleHypothesis()});
0881
0882 if (Verbosity() > 2)
0883 {
0884 std::cout << "Fitted parameters for track" << std::endl;
0885 std::cout << " position : " << outtrack.referenceSurface().localToGlobal(m_transient_geocontext, Acts::Vector2(outtrack.loc0(), outtrack.loc1()), Acts::Vector3(1, 1, 1)).transpose()
0886
0887 << std::endl;
0888 int otcharge = outtrack.qOverP() > 0 ? 1 : -1;
0889 std::cout << "charge: " << otcharge << std::endl;
0890 std::cout << " momentum : " << outtrack.momentum().transpose()
0891 << std::endl;
0892 std::cout << "For trackTip == " << outtrack.tipIndex() << std::endl;
0893 }
0894
0895
0896
0897 PHTimer updateTrackTimer("UpdateTrackTimer");
0898 updateTrackTimer.stop();
0899 updateTrackTimer.restart();
0900 updateSvtxTrack(trackTips, indexedParams, tracks, track);
0901
0902 if (m_commissioning)
0903 {
0904 if (track->get_silicon_seed() && track->get_tpc_seed())
0905 {
0906 m_alignStates.fillAlignmentStateMap(tracks, trackTips,
0907 track, measurements);
0908 }
0909 }
0910
0911 updateTrackTimer.stop();
0912 auto updateTime = updateTrackTimer.get_accumulated_time();
0913
0914 if (Verbosity() > 1)
0915 {
0916 std::cout << "PHActsTrkFitter update SvtxTrack time "
0917 << updateTime << std::endl;
0918 }
0919
0920 if (m_timeAnalysis)
0921 {
0922 h_updateTime->Fill(updateTime);
0923 }
0924
0925 Trajectory trajectory(tracks.trackStateContainer(),
0926 trackTips, indexedParams);
0927
0928 if (m_actsEvaluator)
0929 {
0930 m_evaluator->evaluateTrackFit(tracks, trackTips, indexedParams, track,
0931 seed, measurements);
0932 }
0933
0934 return true;
0935 }
0936
0937 return false;
0938 }
0939
0940
0941 ActsTrackFittingAlgorithm::TrackFitterResult PHActsTrkFitter::fitTrack(
0942 const std::vector<Acts::SourceLink>& sourceLinks,
0943 const ActsTrackFittingAlgorithm::TrackParameters& seed,
0944 const ActsTrackFittingAlgorithm::GeneralFitterOptions& kfOptions,
0945 const SurfacePtrVec& surfSequence,
0946 const CalibratorAdapter& calibrator,
0947 ActsTrackFittingAlgorithm::TrackContainer& tracks)
0948 {
0949
0950 if (m_fitSiliconMMs || m_directNavigation)
0951 { return (*m_fitCfg.dFit)(sourceLinks, seed, kfOptions, surfSequence, calibrator, tracks); }
0952
0953
0954 return (*m_fitCfg.fit)(sourceLinks, seed, kfOptions, calibrator, tracks);
0955 }
0956
0957
0958 SourceLinkVec PHActsTrkFitter::getSurfaceVector(const SourceLinkVec& sourceLinks, SurfacePtrVec& surfaces) const
0959 {
0960 SourceLinkVec siliconMMSls;
0961
0962
0963
0964
0965 for (const auto& sl : sourceLinks)
0966 {
0967 const ActsSourceLink asl = sl.get<ActsSourceLink>();
0968 if (Verbosity() > 1)
0969 {
0970 std::cout << "SL available on : " << asl.geometryId() << std::endl;
0971 }
0972
0973 const auto* const surf = m_tGeometry->geometry().tGeometry->findSurface(asl.geometryId());
0974 if (m_fitSiliconMMs)
0975 {
0976
0977 if (m_tGeometry->maps().isTpcSurface(surf))
0978 {
0979 continue;
0980 }
0981
0982
0983 if (m_tGeometry->maps().isMicromegasSurface(surf) && !m_useMicromegas)
0984 {
0985 continue;
0986 }
0987 }
0988
0989 if(m_forceSiOnlyFit)
0990 {
0991 if(m_tGeometry->maps().isMicromegasSurface(surf)||m_tGeometry->maps().isTpcSurface(surf))
0992 {
0993 continue;
0994 }
0995 }
0996
0997
0998 siliconMMSls.push_back(sl);
0999 surfaces.push_back(surf);
1000 }
1001
1002 if (Verbosity() > 10)
1003 {
1004 for (const auto& surf : surfaces)
1005 {
1006 std::cout << "Surface vector : " << surf->geometryId() << std::endl;
1007 }
1008 }
1009
1010 return siliconMMSls;
1011 }
1012
1013 void PHActsTrkFitter::checkSurfaceVec(SurfacePtrVec& surfaces) const
1014 {
1015 for (unsigned int i = 0; i < surfaces.size() - 1; i++)
1016 {
1017 const auto& surface = surfaces.at(i);
1018 const auto thisVolume = surface->geometryId().volume();
1019 const auto thisLayer = surface->geometryId().layer();
1020
1021 const auto nextSurface = surfaces.at(i + 1);
1022 const auto nextVolume = nextSurface->geometryId().volume();
1023 const auto nextLayer = nextSurface->geometryId().layer();
1024
1025
1026 if (nextVolume == thisVolume)
1027 {
1028 if (nextLayer < thisLayer)
1029 {
1030 std::cout
1031 << "PHActsTrkFitter::checkSurfaceVec - "
1032 << "Surface not in order... removing surface"
1033 << surface->geometryId() << std::endl;
1034
1035 surfaces.erase(surfaces.begin() + i);
1036
1037
1038 --i;
1039 continue;
1040 }
1041 }
1042 else
1043 {
1044 if (nextVolume < thisVolume)
1045 {
1046 std::cout
1047 << "PHActsTrkFitter::checkSurfaceVec - "
1048 << "Volume not in order... removing surface"
1049 << surface->geometryId() << std::endl;
1050
1051 surfaces.erase(surfaces.begin() + i);
1052
1053
1054 --i;
1055 continue;
1056 }
1057 }
1058 }
1059 }
1060
1061 void PHActsTrkFitter::updateSvtxTrack(
1062 const std::vector<Acts::MultiTrajectoryTraits::IndexType>& tips,
1063 const Trajectory::IndexedParameters& paramsMap,
1064 const ActsTrackFittingAlgorithm::TrackContainer& tracks,
1065 SvtxTrack* track)
1066 {
1067 const auto& mj = tracks.trackStateContainer();
1068
1069
1070 const auto& trackTip = tips.front();
1071
1072 if (Verbosity() > 2)
1073 {
1074 std::cout << "Identify (proto) track before updating with acts results " << std::endl;
1075 track->identify();
1076 }
1077
1078 if (!m_fitSiliconMMs && !m_forceSiOnlyFit)
1079 {
1080 track->clear_states();
1081 }
1082
1083
1084
1085 float pathlength = 0.0;
1086
1087 SvtxTrackState_v3 out(pathlength);
1088 out.set_localX(0.0);
1089 out.set_localY(0.0);
1090 out.set_x(0.0);
1091 out.set_y(0.0);
1092 out.set_z(0.0);
1093 track->insert_state(&out);
1094
1095 auto trajState =
1096 Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip);
1097
1098 const auto& params = paramsMap.find(trackTip)->second;
1099
1100
1101 track->set_x(params.position(m_transient_geocontext)(0) / Acts::UnitConstants::cm);
1102 track->set_y(params.position(m_transient_geocontext)(1) / Acts::UnitConstants::cm);
1103 track->set_z(params.position(m_transient_geocontext)(2) / Acts::UnitConstants::cm);
1104
1105 track->set_px(params.momentum()(0));
1106 track->set_py(params.momentum()(1));
1107 track->set_pz(params.momentum()(2));
1108
1109 track->set_charge(params.charge());
1110 track->set_chisq(trajState.chi2Sum);
1111 track->set_ndf(trajState.NDF);
1112
1113 ActsTransformations transformer;
1114 transformer.setVerbosity(Verbosity());
1115
1116 if (params.covariance())
1117 {
1118 auto rotatedCov = transformer.rotateActsCovToSvtxTrack(params);
1119
1120 for (int i = 0; i < 6; i++)
1121 {
1122 for (int j = 0; j < 6; j++)
1123 {
1124 track->set_error(i, j, rotatedCov(i, j));
1125 }
1126 }
1127 }
1128
1129
1130
1131 PHTimer trackStateTimer("TrackStateTimer");
1132 trackStateTimer.stop();
1133 trackStateTimer.restart();
1134
1135 if (m_fillSvtxTrackStates)
1136 { transformer.fillSvtxTrackStates(mj, trackTip, track, m_transient_geocontext); }
1137
1138
1139
1140 auto* seed = track->get_tpc_seed();
1141 if( m_fitSiliconMMs && seed )
1142 {
1143
1144
1145 ActsPropagator propagator(m_tGeometry);
1146
1147
1148 for( auto key_iter = seed->begin_cluster_keys(); key_iter != seed->end_cluster_keys(); ++key_iter )
1149 {
1150 const auto& cluskey = *key_iter;
1151
1152
1153 const auto detId = TrkrDefs::getTrkrId(cluskey);
1154 if (detId != TrkrDefs::tpcId)
1155 { continue; }
1156
1157
1158 const auto layer = TrkrDefs::getLayer(cluskey);
1159 auto result = propagator.propagateTrack(params, layer);
1160 if( !result.ok() ) { continue; }
1161
1162
1163 auto& [pathLength, trackStateParams] = result.value();
1164 pathLength /= Acts::UnitConstants::cm;
1165
1166
1167 transformer.addTrackState(track, cluskey, pathLength, trackStateParams, m_transient_geocontext);
1168 }
1169 }
1170
1171 trackStateTimer.stop();
1172 auto stateTime = trackStateTimer.get_accumulated_time();
1173
1174 if (Verbosity() > 1)
1175 {
1176 std::cout << "PHActsTrkFitter update SvtxTrackStates time "
1177 << stateTime << std::endl;
1178 }
1179
1180 if (m_timeAnalysis)
1181 {
1182 h_stateTime->Fill(stateTime);
1183 }
1184
1185 if (Verbosity() > 2)
1186 {
1187 std::cout << " Identify fitted track after updating track states:"
1188 << std::endl;
1189 track->identify();
1190 }
1191
1192 return;
1193 }
1194
1195 Acts::BoundSquareMatrix PHActsTrkFitter::setDefaultCovariance() const
1196 {
1197 Acts::BoundSquareMatrix cov = Acts::BoundSquareMatrix::Zero();
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209 if (m_fitSiliconMMs)
1210 {
1211 cov << 1000 * Acts::UnitConstants::um, 0., 0., 0., 0., 0.,
1212 0., 1000 * Acts::UnitConstants::um, 0., 0., 0., 0.,
1213 0., 0., 0.1, 0., 0., 0.,
1214 0., 0., 0., 0.1, 0., 0.,
1215 0., 0., 0., 0., 0.005, 0.,
1216 0., 0., 0., 0., 0., 1.;
1217 }
1218 else
1219 {
1220
1221 double sigmaD0 = 50 * Acts::UnitConstants::um;
1222 double sigmaZ0 = 50 * Acts::UnitConstants::um;
1223
1224 double sigmaPhi = 1. * Acts::UnitConstants::degree;
1225 double sigmaTheta = 1. * Acts::UnitConstants::degree;
1226 double sigmaT = 1. * Acts::UnitConstants::ns;
1227
1228 cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = sigmaD0 * sigmaD0;
1229 cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = sigmaZ0 * sigmaZ0;
1230 cov(Acts::eBoundTime, Acts::eBoundTime) = sigmaT * sigmaT;
1231 cov(Acts::eBoundPhi, Acts::eBoundPhi) = sigmaPhi * sigmaPhi;
1232 cov(Acts::eBoundTheta, Acts::eBoundTheta) = sigmaTheta * sigmaTheta;
1233
1234
1235 cov(Acts::eBoundQOverP, Acts::eBoundQOverP) = 0.025;
1236 }
1237
1238 return cov;
1239 }
1240
1241 void PHActsTrkFitter::printTrackSeed(const ActsTrackFittingAlgorithm::TrackParameters& seed) const
1242 {
1243 std::cout
1244 << PHWHERE
1245 << " Processing proto track:"
1246 << std::endl;
1247
1248 std::cout
1249 << "position: " << seed.position(m_transient_geocontext).transpose()
1250 << std::endl
1251 << "momentum: " << seed.momentum().transpose()
1252 << std::endl;
1253
1254 std::cout << "charge : " << seed.charge() << std::endl;
1255 std::cout << "absolutemom : " << seed.absoluteMomentum() << std::endl;
1256 }
1257
1258 int PHActsTrkFitter::createNodes(PHCompositeNode* topNode)
1259 {
1260 PHNodeIterator iter(topNode);
1261
1262 PHCompositeNode* dstNode = dynamic_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "DST"));
1263
1264 if (!dstNode)
1265 {
1266 std::cerr << "DST node is missing, quitting" << std::endl;
1267 throw std::runtime_error("Failed to find DST node in PHActsTrkFitter::createNodes");
1268 }
1269
1270 PHNodeIterator dstIter(topNode);
1271 PHCompositeNode* svtxNode = dynamic_cast<PHCompositeNode*>(dstIter.findFirst("PHCompositeNode", "SVTX"));
1272
1273 if (!svtxNode)
1274 {
1275 svtxNode = new PHCompositeNode("SVTX");
1276 dstNode->addNode(svtxNode);
1277 }
1278
1279 if (m_fitSiliconMMs)
1280 {
1281 m_directedTrackMap = findNode::getClass<SvtxTrackMap>(topNode,
1282 "SvtxSiliconMMTrackMap");
1283 if (!m_directedTrackMap)
1284 {
1285
1286 m_directedTrackMap = new SvtxTrackMap_v2;
1287
1288 PHIODataNode<PHObject>* trackNode =
1289 new PHIODataNode<PHObject>(m_directedTrackMap, "SvtxSiliconMMTrackMap", "PHObject");
1290 svtxNode->addNode(trackNode);
1291 }
1292 }
1293
1294 m_trackMap = findNode::getClass<SvtxTrackMap>(topNode, _track_map_name);
1295
1296 if (!m_trackMap)
1297 {
1298 m_trackMap = new SvtxTrackMap_v2;
1299 PHIODataNode<PHObject>* node = new PHIODataNode<PHObject>(m_trackMap, _track_map_name, "PHObject");
1300 svtxNode->addNode(node);
1301 }
1302
1303 m_alignmentStateMap = findNode::getClass<SvtxAlignmentStateMap>(topNode, _svtx_alignment_state_map_name);
1304 if (!m_alignmentStateMap)
1305 {
1306 m_alignmentStateMap = new SvtxAlignmentStateMap_v1;
1307 auto node = new PHDataNode<SvtxAlignmentStateMap>(m_alignmentStateMap, _svtx_alignment_state_map_name, "PHObject");
1308 svtxNode->addNode(node);
1309 }
1310
1311 return Fun4AllReturnCodes::EVENT_OK;
1312 }
1313
1314 int PHActsTrkFitter::getNodes(PHCompositeNode* topNode)
1315 {
1316 m_alignmentTransformationMap = findNode::getClass<alignmentTransformationContainer>(topNode, "alignmentTransformationContainer");
1317 if (!m_alignmentTransformationMap)
1318 {
1319 std::cout << PHWHERE << "alignmentTransformationContainer not on node tree. Bailing"
1320 << std::endl;
1321 return Fun4AllReturnCodes::ABORTEVENT;
1322 }
1323
1324 m_alignmentTransformationMapTransient = findNode::getClass<alignmentTransformationContainer>(topNode, "alignmentTransformationContainerTransient");
1325 if (!m_alignmentTransformationMapTransient)
1326 {
1327 std::cout << PHWHERE << "alignmentTransformationContainerTransient not on node tree. Bailing"
1328 << std::endl;
1329 return Fun4AllReturnCodes::ABORTEVENT;
1330 }
1331
1332
1333 m_tpcSeeds = findNode::getClass<TrackSeedContainer>(topNode, "TpcTrackSeedContainer");
1334 if (!m_tpcSeeds)
1335 {
1336 std::cout << PHWHERE << "TpcTrackSeedContainer not on node tree. Bailing"
1337 << std::endl;
1338 return Fun4AllReturnCodes::ABORTEVENT;
1339 }
1340
1341
1342 m_siliconSeeds = findNode::getClass<TrackSeedContainer>(topNode, "SiliconTrackSeedContainer");
1343 if (!m_siliconSeeds)
1344 {
1345 std::cout << PHWHERE << "SiliconTrackSeedContainer not on node tree. Bailing"
1346 << std::endl;
1347 return Fun4AllReturnCodes::ABORTEVENT;
1348 }
1349
1350
1351 m_clusterContainer = findNode::getClass<TrkrClusterContainer>(topNode, m_clusterContainerName);
1352 if (!m_clusterContainer)
1353 {
1354 std::cout << PHWHERE
1355 << "No trkr cluster container, exiting." << std::endl;
1356 return Fun4AllReturnCodes::ABORTEVENT;
1357 }
1358
1359
1360 m_tGeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
1361 if (!m_tGeometry)
1362 {
1363 std::cout << "ActsGeometry not on node tree. Exiting."
1364 << std::endl;
1365
1366 return Fun4AllReturnCodes::ABORTEVENT;
1367 }
1368
1369
1370 m_seedMap = findNode::getClass<TrackSeedContainer>(topNode, _svtx_seed_map_name);
1371 if (!m_seedMap)
1372 {
1373 std::cout << "No Svtx seed map on node tree. Exiting."
1374 << std::endl;
1375 return Fun4AllReturnCodes::ABORTEVENT;
1376 }
1377
1378
1379 m_globalPositionWrapper.loadNodes(topNode);
1380 m_globalPositionWrapper.set_suppressCrossing(true);
1381
1382 return Fun4AllReturnCodes::EVENT_OK;
1383 }