4 #include "Fit/Fitter.h"
13 #include "TLorentzVector.h"
19 #include <unordered_map>
22 #include "StFwdTrackMaker/include/Tracker/FwdHit.h"
23 #include "StFwdTrackMaker/include/Tracker/FwdDataSource.h"
24 #include "StFwdTrackMaker/include/Tracker/TrackFitter.h"
26 #include "Criteria/Criteria.h"
27 #include "Criteria/ICriterion.h"
28 #include "KiTrack/Automaton.h"
29 #include "KiTrack/SegmentBuilder.h"
30 #include "KiTrack/SubsetHopfieldNN.h"
32 #include "StFwdTrackMaker/include/Tracker/CriteriaKeeper.h"
34 #include "GenFit/FitStatus.h"
35 #include "GenFit/GFRaveVertexFactory.h"
37 #include "StFwdTrackMaker/FwdTrackerConfig.h"
38 #include "StFwdTrackMaker/Common.h"
43 static int dominantContribution(
Seed_t hits,
double &qa) {
46 std::unordered_map<int,int> truth;
47 for (
auto hit : hits ) {
49 truth[ fhit->_tid ]++;
52 if ( truth.size() == 0 ){
57 using P = decltype(truth)::value_type;
58 auto dom = max_element(begin(truth), end(truth), [](P a, P b){
return a.second < b.second; });
62 if ( hits.size() > 0 )
63 qa =
double(dom->second) / double(hits.size()) ;
73 TString classname()
const {
return "EventStats"; }
87 mAttemptedPrimaryFits = 0;
89 mFailedPrimaryFits = 0;
91 mStep1Duration.clear();
92 mStep2Duration.clear();
93 mStep3Duration.clear();
94 mStep4Duration.clear();
98 int mAttemptedFits = 0;
101 int mGoodCardinals = 0;
103 int mAttemptedReFits = 0;
104 int mFailedReFits = 0;
106 int mPossibleReFit = 0;
108 int mNumFwdVertices = 0;
109 int mAttemptedPrimaryFits = 0;
110 int mGoodPrimaryFits = 0;
111 int mFailedPrimaryFits = 0;
112 vector<float> mStep1Duration;
113 vector<float> mSeedFindingDuration;
114 vector<float> mStep2Duration;
115 vector<float> mStep3Duration;
116 vector<float> mStep4Duration;
117 vector<float> mFitDuration;
134 void set(
Seed_t &seeds, std::shared_ptr<genfit::Track> track ){
138 void setSeed(
Seed_t &seed ){
140 mIdTruth = MCTruthUtils::dominantContribution( seed, mQaTruth );
141 LOG_INFO <<
"GenFitTrackResult::mIdTruth = " << mIdTruth <<
", QaTruth = " << mQaTruth << endm;
143 void setTrack( std::shared_ptr<genfit::Track> track ){
147 mTrack ->setMcTrackId(mIdTruth);
148 mStatus = mTrack->getFitStatus();
149 mTrackRep = mTrack->getCardinalRep();
151 mIsFitConverged = mStatus->isFitConverged();
152 mIsFitConvergedFully = mStatus->isFitConvergedFully();
153 mIsFitConvergedPartially = mStatus->isFitConvergedPartially();
154 mNFailedPoints = mStatus->getNFailedPoints();
155 mCharge = mStatus->getCharge();
156 mChi2 = mStatus->getChi2();
158 if ( mIsFitConverged ){
159 LOG_INFO <<
"GTR Setting momentum from track" << endm;
160 mMomentum = mTrackRep->getMom( mTrack->getFittedState(0, mTrackRep) );
162 LOG_DEBUG <<
"GenfitTrackResult::set Track successful" << endm;
163 }
catch ( genfit::Exception &e ) {
164 LOG_ERROR <<
"Unable to set track -> GenfitException: " << e.what() << endm;
165 this->mTrack =
nullptr;
166 this->mTrackRep =
nullptr;
168 this->mIsFitConverged =
false;
169 this->mIsFitConvergedFully =
false;
170 this->mIsFitConvergedPartially =
false;
171 this->mNFailedPoints = 99;
184 auto dcaState = mTrack->getFittedState( 0 );
185 this->mTrackRep->extrapolateToPoint( dcaState, mPV );
186 this->mDCA = dcaState.getPos();
187 }
catch ( genfit::Exception &e ) {
188 LOG_ERROR <<
"CANNOT GET DCA : GenfitException: " << e.what() << endm;
189 this->mDCA = TVector3(99,99,99);
194 size_t numFtt()
const {
196 for (
auto hit : mSeed ){
197 if ( dynamic_cast<FwdHit*>(
hit)->_detid == kFttId ){
203 size_t numFst()
const {
205 for (
auto hit : mSeed ){
206 if ( dynamic_cast<FwdHit*>(
hit)->_detid == kFstId ){
212 size_t numPV()
const {
214 for (
auto hit : mSeed ){
215 if ( dynamic_cast<FwdHit*>(
hit)->isPV() ){
224 for (
auto hit : other.mSeed ){
225 if ( std::find( mSeed.begin(), mSeed.end(),
hit ) == mSeed.end() ){
226 mSeed.push_back(
hit );
231 bool isPrimary =
false;
237 genfit::FitStatus *mStatus =
nullptr;
238 genfit::AbsTrackRep *mTrackRep =
nullptr;
239 std::shared_ptr<genfit::Track> mTrack =
nullptr;
240 bool mIsFitConverged =
false;
241 bool mIsFitConvergedFully =
false;
242 bool mIsFitConvergedPartially =
false;
243 size_t mNFailedPoints = 0;
251 ForwardTrackMaker() : mConfigFile(
"config.xml"), mEventVertex(-999, -999, -999) {
255 const std::vector<GenfitTrackResult> &getTrackResults()
const {
return mTrackResults; }
256 const std::vector<Seed_t> &getTrackSeeds()
const {
return mTrackSeeds; }
257 const EventStats &getEventStats()
const {
return mEventStats; }
260 for (
auto gtr : mTrackResults ){
263 mTrackResults.clear();
281 mSaveCriteriaValues = save;
287 void setData(std::shared_ptr<FwdDataSource>
data) { mDataSource = data; }
295 virtual void initialize( TString geoCache,
bool genHistograms) {
296 mGeoCache = geoCache;
297 mDoTrackFitting = mConfig.get<
bool>(
"TrackFitter:active",
true);
299 if (!mConfig.exists(
"TrackFitter"))
300 mDoTrackFitting =
false;
311 std::vector<KiTrack::ICriterion *> crits;
312 auto paths = mConfig.childrenOf(path);
314 for (
string p : paths) {
315 string name = mConfig.get<
string>(p +
":name",
"");
316 bool active = mConfig.get<
bool>(p +
":active",
true);
318 if (
false == active) {
322 float vmin = mConfig.get<
float>(p +
":min", 0);
323 float vmax = mConfig.get<
float>(p +
":max", 1);
325 KiTrack::ICriterion * crit =
nullptr;
326 if ( name ==
"Crit2_BDT" ){
328 LOG_WARN <<
"BDT Criteria not implemented/out of date" << endm;
330 crit = KiTrack::Criteria::createCriterion(name, vmin, vmax);
333 crit->setSaveValues(mSaveCriteriaValues);
335 if (mSaveCriteriaValues)
338 crits.push_back(crit);
350 for (
size_t i = 0; i < crits.size(); i++ ){
366 std::vector<float> em;
367 if (mSaveCriteriaValues !=
true) {
371 for (
auto crit : mTwoHitCrit) {
372 if (crit_name == crit->getName()) {
374 return critKeeper->getValues();
378 for (
auto crit : mThreeHitCrit) {
379 if (crit_name == crit->getName()) {
381 return critKeeper->getValues();
395 std::vector<std::map < std::string , float >> em;
396 if (mSaveCriteriaValues !=
true) {
400 for (
auto crit : mTwoHitCrit) {
401 if (crit_name == crit->getName()) {
403 return critKeeper->getAllValues();
407 for (
auto crit : mThreeHitCrit) {
408 if (crit_name == crit->getName()) {
410 return critKeeper->getAllValues();
425 if (mSaveCriteriaValues !=
true) {
429 for (
auto crit : mTwoHitCrit) {
430 if (crit_name == crit->getName()) {
432 return critKeeper->getTrackIds();
436 for (
auto crit : mThreeHitCrit) {
437 if (crit_name == crit->getName()) {
439 return critKeeper->getTrackIds();
451 if (mSaveCriteriaValues !=
true) {
455 for (
auto crit : mTwoHitCrit) {
460 for (
auto crit : mThreeHitCrit) {
474 for (
auto kv : hitmap) {
475 n += kv.second.size();
486 void removeHits(FwdDataSource::HitMap_t &hitmap, std::vector<Seed_t> &tracks) {
488 for (
auto track : tracks) {
489 for (
auto hit : track) {
490 int sector =
hit->getSector();
492 auto hitit = std::find(hitmap[sector].begin(), hitmap[sector].end(),
hit);
494 if (hitit != hitmap[sector].end()) {
495 hitmap[sector].erase(hitit);
510 void mergeHitmaps( FwdDataSource::HitMap_t &hitmap1, FwdDataSource::HitMap_t &hitmap2 ){
511 static const int numFstSectors = 3;
512 for (
auto kv : hitmap2 ){
513 for (
auto hit : kv.second ){
514 dynamic_cast<FwdHit*
>(
hit )->setSector(
hit->getSector() + numFstSectors );
515 hitmap1[kv.first + numFstSectors].push_back(
hit );
528 mTrackResults.clear();
530 mTotalHitsRemoved = 0;
534 bool useMcTrackFinding(){
538 bool mcTrackFinding =
true;
539 if (mConfig.exists(
"TrackFinder")){
540 mcTrackFinding =
false;
542 if (mConfig.exists(
"TrackFinder") && mConfig.get<
bool>(
"TrackFinder:mc", false ) ==
false ){
543 mcTrackFinding =
false;
545 if (mConfig.exists(
"TrackFinder") && mConfig.get<
bool>(
"TrackFinder:active", true ) ==
false){
546 mcTrackFinding =
true;
548 return mcTrackFinding;
561 long long itStart = FwdTrackerUtils::nowNanoSecond();
562 FwdDataSource::HitMap_t &fttHitmap = mDataSource->getFttHits();
563 FwdDataSource::HitMap_t &fstHitmap = mDataSource->getFstHits();
568 string hitmapSource = mConfig.get<
string>(
"TrackFinder:source",
"ftt");
569 LOG_INFO <<
"Hitmap Source: " << hitmapSource << endm;
570 mSeedSource = kSeqSeed;
571 if (hitmapSource ==
"fst")
572 mSeedSource = kFstSeed;
573 else if (hitmapSource ==
"ftt")
574 mSeedSource = kFttSeed;
575 else if (hitmapSource ==
"seq")
576 mSeedSource = kSeqSeed;
577 else if (hitmapSource ==
"sim")
578 mSeedSource = kSimSeed;
579 LOG_INFO <<
"Performing Fwd Seed finding with mode: " << mConfig.get<
string>(
"TrackFinder:source",
"ftt") <<
" = " << mSeedSource << endm;
580 FwdDataSource::McTrackMap_t &mcTrackMap = mDataSource->getMcTracks();
582 long long duration = (FwdTrackerUtils::nowNanoSecond() - itStart) * 1e-6;
584 mEventStats.mStep1Duration.push_back( duration );
588 if (useMcTrackFinding()) {
589 doMcTrackFinding(mcTrackMap, mSeedSource);
590 mEventStats.mNumSeeds = mTrackSeeds.size();
591 long long duration2 = (FwdTrackerUtils::nowNanoSecond() - itStart) * 1e-6;
592 mEventStats.mSeedFindingDuration.push_back( duration2 );
595 LOG_DEBUG <<
"Performing Standard Track Finding" << endm;
601 size_t nIterations = mConfig.get<
size_t>(
"TrackFinder:nIterations", 0);
602 for (
size_t iIteration = 0; iIteration < nIterations; iIteration++) {
603 if ( mSeedSource == kSimSeed){
604 mergeHitmaps( fstHitmap, fttHitmap );
606 if ( mSeedSource == kFstSeed || mSeedSource == kSeqSeed ){
607 doSeedFindingIteration(iIteration, fstHitmap);
609 if ( mSeedSource == kFttSeed || mSeedSource == kSeqSeed){
610 doSeedFindingIteration(iIteration, fttHitmap);
615 mEventStats.mNumSeeds = mTrackSeeds.size();
616 long long duration2 = (FwdTrackerUtils::nowNanoSecond() - itStart) * 1e-6;
617 mEventStats.mSeedFindingDuration.push_back( duration2 );
621 std::vector< genfit::GFRaveVertex * > findFwdVertices(
const vector<GenfitTrackResult> &globalTracks ){
623 std::vector< genfit::GFRaveVertex * > raveVertices;
627 vector<genfit::Track*> tracks;
628 for (
auto gtr : globalTracks ){
630 tracks.push_back( gtr.mTrack.get() );
634 bool useBeamConstraint =
false;
635 if ( useBeamConstraint ){
638 const double bssXY = 2.0;
639 bscm(0, 0) = bssXY*bssXY;
640 bscm(1, 1) = bssXY*bssXY;
641 bscm(2, 2) = 50.5 * 50.5;
642 mGFRVertices.setBeamspot( TVector3( 0, 0, 0 ), bscm );
647 mGFRVertices.findVertices( &raveVertices, tracks, useBeamConstraint );
648 LOG_DEBUG <<
"raveVertices.size() = " << raveVertices.size() << endm;
649 for (
auto vert : raveVertices ){
650 LOG_DEBUG << TString::Format(
"GFRaveVertex vertex @(%f, %f, %f)\n\n", vert->getPos().X(), vert->getPos().Y(), vert->getPos().Z() ) << endm;
651 LOG_DEBUG <<
"GFRaveVertex\n";
654 LOG_DEBUG <<
"Ndf: " << vert->getNdf() <<
", Chi2: " << vert->getChi2() <<
", Id: " << vert->getId() <<
"\n";
655 LOG_DEBUG <<
"Number of tracks: " << vert->getNTracks() <<
"\n";
676 LOG_DEBUG <<
"FwdTracker::fitTrack->" << endm;
677 mEventStats.mAttemptedFits++;
681 LOG_DEBUG <<
"--Setting seed on GenfitTrackResult, seed has " << seed.size() <<
" hits" << endm;
686 if ( momentumSeedState ){
687 LOG_DEBUG <<
"--FitTrack with provided momentum seed state" << endm;
688 mTrackFitter->fitTrack( seed, momentumSeedState );
690 LOG_DEBUG <<
"--FitTrack without provided momentum seed state" << endm;
691 mTrackFitter->fitTrack( seed );
697 if (mTrackFitter->getTrack() != nullptr ){
698 LOG_DEBUG <<
"--FitTrack found, setting seed and track only" << endm;
699 gtr.set( seed, mTrackFitter->getTrack() );
701 if (gtr.mStatus && gtr.mStatus->isFitConvergedFully()) {
702 mEventStats.mGoodFits++;
704 mEventStats.mFailedFits++;
707 LOG_DEBUG <<
"--FitTrack failed, setting seed only" << endm;
708 mEventStats.mFailedFits++;
710 LOG_DEBUG <<
"<-FwdTracker::fitTrack complete" << endm;
729 LOG_DEBUG <<
">>doTrackFitting" << endm;
730 if (!mDoTrackFitting)
732 long long itStart = FwdTrackerUtils::nowNanoSecond();
734 std::vector<GenfitTrackResult> globalTracks;
735 std::vector<GenfitTrackResult> primaryTracks;
738 const bool doRefit = mConfig.get<
bool>(
"TrackFitter:refit",
false);
739 LOG_INFO <<
"TrackFitter:refit = " << doRefit << endm;
742 const bool useMcSeedMomentum = mConfig.get<
bool>(
"TrackFitter:mcSeed",
false);
743 LOG_INFO <<
"TrackFitter:mcSeed = " << useMcSeedMomentum << endm;
745 LOG_DEBUG <<
"Starting track fitting loop, mTrackResults.size() = " << mTrackResults.size() << endm;
746 LOG_DEBUG <<
"Starting Track fitting loop on " << trackSeeds.size() <<
" track seeds" << endm;
748 for (
auto t : trackSeeds) {
751 LOG_DEBUG <<
"\tTrack seed initial global fit #" << index << endm;
757 TVector3 momentumSeedStateMc;
758 TVector3 *pMomSeedState =
nullptr;
762 idt = MCTruthUtils::dominantContribution(t, qual);
763 LOG_INFO <<
"\t\tMc Match idTruth=" << idt <<
", quality = " << qual << endm;
764 if (
true == useMcSeedMomentum) {
769 auto mctm = mDataSource->getMcTracks();
771 if (mctm.count(idt)) {
772 auto mct = mctm[idt];
773 momentumSeedStateMc.SetPtEtaPhi(mct->mPt, mct->mEta, mct->mPhi);
776 LOG_WARN <<
"\tRequested MC momentum for fit seed, but couldnt find MC Track for id: " << idt <<
", qual: " << qual << endm;
783 gtrGlobal.
setDCA( mEventVertex );
785 LOG_DEBUG <<
"\tFit track seed with " << gtrGlobal.mSeed.size() <<
" hits" << endm;
786 LOG_DEBUG <<
"\t\t McTrack Id = " << gtrGlobal.mIdTruth <<
", QA = " << gtrGlobal.mQaTruth << endm;
792 if (gtrGlobal.mIsFitConvergedPartially ==
false) {
793 LOG_WARN <<
"\tInitial fitting failed for seed " << index << endm;
794 LOG_DEBUG <<
"\tFitting failed for seed " << index << endm;
795 LOG_DEBUG <<
"\tSkipping the refit steps but saving the seed and failed fit" << endm;
796 globalTracks.push_back( gtrGlobal );
801 if (doRefit ==
false) {
802 LOG_INFO <<
"\tRefit is disabled, saving the seed and initial fit" << endm;
803 gtrGlobal.isPrimary =
false;
804 globalTracks.push_back( gtrGlobal );
816 if (useMcTrackFinding()) {
817 if (mSeedSource != kFttSeed) addFttHitsMc( gtrGlobal );
818 if (mSeedSource != kFstSeed) addFstHitsMc( gtrGlobal );
825 if (mSeedSource != kFttSeed){
826 for (
int i = 0; i < FwdSystem::sNFttLayers; i++ ){
827 addFttHits( gtrGlobal, i );
830 if (mSeedSource != kFstSeed ){
831 for (
int i = 0; i < FwdSystem::sNFstLayers; i++ ){
832 addFstHits( gtrGlobal, i );
842 gtrGlobalRefit = fitTrack( gtrGlobal.mSeed, >rGlobal.mMomentum );
843 gtrGlobalRefit.
setDCA( mEventVertex );
850 if ( gtrGlobalRefit.mIsFitConvergedPartially ){
851 activeTrack = >rGlobalRefit;
854 if ( !activeTrack->mIsFitConvergedPartially ){
856 LOG_WARN <<
"\tFWD global track fit failed (both initial + refit)" << endm;
863 activeTrack->isPrimary =
false;
864 globalTracks.push_back( *activeTrack );
869 long long duration1 = (FwdTrackerUtils::nowNanoSecond() - itStart) * 1e-6;
870 mEventStats.mFitDuration.push_back( duration1 );
871 float perGood = (float) mEventStats.mGoodFits / (
float) mEventStats.mAttemptedFits;
872 float perFailed = (float) mEventStats.mFailedFits / (
float) mEventStats.mAttemptedFits;
873 float perCardinals = (float) mEventStats.mGoodCardinals / (
float) mEventStats.mGoodFits;
874 LOG_DEBUG <<
"\tGlobal Track Fitting Results:" <<
876 "Attempts = %d, Good = %d (%f%%), Failed = %d (%f%%), GoodCardinals = %d (%f%%)",
877 mEventStats.mAttemptedFits,
878 mEventStats.mGoodFits,
880 mEventStats.mFailedFits,
882 mEventStats.mGoodCardinals,
883 perCardinals ) << endm;
885 const bool do_fwd_vertex_finding =
true;
886 if (do_fwd_vertex_finding){
889 LOG_DEBUG <<
"\tStarting Track Fitting Step 3 (FWD Vertex Finding)" << endm;
890 auto fwdVertices = findFwdVertices( globalTracks );
891 mEventStats.mNumFwdVertices = fwdVertices.size();
893 for (
auto vert : fwdVertices ){
894 LOG_DEBUG <<
"\tFound FWD Vertex @(" << vert->getPos().X() <<
", " << vert->getPos().Y() <<
", " << vert->getPos().Z() <<
")" << endm;
895 LOG_DEBUG <<
"\t\tvs mEventVertexHit: " << mEventVertexHit.getX() <<
", " << mEventVertexHit.getY() <<
", " << mEventVertexHit.getZ() << endm;
901 LOG_INFO <<
"Event configuration is skipping FWD vertex finding" << endm;
905 const bool do_fwd_primary_fitting =
true;
909 if (do_fwd_primary_fitting){
911 for (
auto >r : globalTracks) {
912 LOG_INFO <<
"Refitting Track " << index <<
", McId=" << gtr.mIdTruth <<
" with Primary Vertex, seed already has: " << gtr.mSeed.size() <<
" hits" << endm;
913 LOG_INFO <<
"mEventVertexHit: " << mEventVertexHit.getX() <<
", " << mEventVertexHit.getY() <<
", " << mEventVertexHit.getZ() << endm;
915 Seed_t seedWithPV = gtr.mSeed;
916 seedWithPV.push_back( &mEventVertexHit );
919 TVector3 momentumSeedStateMc;
920 TVector3 *pMomSeedState = >r.mMomentum;
936 if ( gtrPV.mIsFitConvergedFully ){
937 mEventStats.mGoodPrimaryFits++;
939 mEventStats.mFailedPrimaryFits++;
942 gtrPV.
setDCA( mEventVertex );
943 gtrPV.isPrimary =
true;
944 mEventStats.mAttemptedPrimaryFits ++;
945 primaryTracks.push_back( gtrPV );
951 LOG_INFO <<
"Event configuration is skipping primary track fitting" << endm;
954 float perGoodPrim = (float) mEventStats.mGoodPrimaryFits / (
float) mEventStats.mAttemptedPrimaryFits;
955 float perFailedPrim = (float) mEventStats.mFailedPrimaryFits / (
float) mEventStats.mAttemptedPrimaryFits;
956 LOG_DEBUG <<
"\tPrimary Track Fitting Results:" <<
958 "Attempts = %d, Good = %d (%f%%), Failed = %d (%f%%)",
959 mEventStats.mAttemptedPrimaryFits,
960 mEventStats.mGoodPrimaryFits,
962 mEventStats.mFailedPrimaryFits,
967 LOG_DEBUG <<
"Ending track fitting loop, mTrackResults.size() = " << mTrackResults.size() << endm;
968 mTrackResults.insert( mTrackResults.end(), globalTracks.begin(), globalTracks.end() );
969 LOG_DEBUG <<
"Copied globals, now mTrackResults.size() = " << mTrackResults.size() << endm;
970 mTrackResults.insert( mTrackResults.end(), primaryTracks.begin(), primaryTracks.end() );
972 long long duration2 = (FwdTrackerUtils::nowNanoSecond() - itStart) * 1e-6;
973 LOG_DEBUG <<
"Track fitting took " << duration2 <<
"ms" << endm;
974 LOG_DEBUG <<
"We fit " << globalTracks.size() <<
" global tracks and " << primaryTracks.size() <<
" primary tracks, total = " << mTrackResults.size() << endm;
984 LOG_INFO <<
"Running MC Seed Finding, mode: " << seedSource << endm;
987 if ( seedSource == kSeqSeed ){
988 doMcTrackFinding( mcTrackMap, kFstSeed );
989 doMcTrackFinding( mcTrackMap, kFttSeed );
993 mTrackSeedsThisIteration.clear();
995 for (
auto kv : mcTrackMap) {
997 auto mc_track = kv.second;
998 LOG_DEBUG <<
"McTrack[ " << kv.first <<
" ]: nFtt=" << mc_track->mFttHits.size() <<
", nFst=" << mc_track->mFstHits.size() << endm;
1000 if (seedSource == kFttSeed && mc_track->mFttHits.size() < 2){
1004 if (seedSource == kFstSeed && mc_track->mFstHits.size() < 2 ) {
1005 LOG_DEBUG <<
"Skipping McSeedFinding bc FST hits < 2" << endm;
1009 if ( seedSource == kSimSeed && mc_track->mFstHits.size() < 2 && mc_track->mFttHits.size() < 2 ){
1013 std::set<size_t> uvid;
1016 if ( seedSource != kFstSeed ){
1017 for (
auto h : mc_track->mFttHits) {
1019 uvid.insert(static_cast<FwdHit *>(h)->_vid);
1022 if (seedSource != kFttSeed ) {
1023 for (
auto h : mc_track->mFstHits) {
1025 uvid.insert(static_cast<FwdHit *>(h)->_vid);
1029 if (uvid.size() == track.size()) {
1030 mTrackSeedsThisIteration.push_back(track);
1033 idt = MCTruthUtils::dominantContribution(track, qual);
1039 LOG_DEBUG <<
"McTrackFinding Found: " << mTrackSeedsThisIteration.size() <<
" tracks" << endm;
1043 mTrackSeeds.insert( mTrackSeeds.end(), mTrackSeedsThisIteration.begin(), mTrackSeedsThisIteration.end() );
1056 size_t sliceHitMapInPhi( FwdDataSource::HitMap_t &inputMap, FwdDataSource::HitMap_t &outputMap,
float phi_min,
float phi_max ){
1057 size_t n_hits_kept = 0;
1060 for (
auto kv : inputMap ){
1061 for ( KiTrack::IHit*
hit : kv.second ){
1062 TVector3 vec(hit->getX(), hit->getY(), hit->getZ() );
1063 if ( vec.Phi() < phi_min || vec.Phi() > phi_max )
continue;
1066 outputMap[kv.first].push_back( hit );
1080 long long itStart = FwdTrackerUtils::nowNanoSecond();
1082 std::vector<Seed_t> acceptedTrackSeeds;
1088 KiTrack::SegmentBuilder builder(hitmap);
1092 std::string criteriaPath =
"TrackFinder.Iteration[" + std::to_string(iIteration) +
"].SegmentBuilder";
1094 if (
false == mConfig.exists(criteriaPath)) {
1097 criteriaPath =
"TrackFinder.SegmentBuilder";
1100 clearCriteria( mTwoHitCrit );
1101 mTwoHitCrit = loadCriteria(criteriaPath);
1102 builder.addCriteria(mTwoHitCrit);
1105 std::string connPath =
"TrackFinder.Iteration[" + std::to_string(iIteration) +
"].Connector";
1107 if (
false == mConfig.exists(connPath))
1108 connPath =
"TrackFinder.Connector";
1110 unsigned int distance = mConfig.get<
unsigned int>(connPath +
":distance", 1);
1111 if (mSeedSource == kFttSeed){
1116 builder.addSectorConnector(&connector);
1117 LOG_DEBUG <<
"Connector added: " << endm;
1120 KiTrack::Automaton automaton = builder.get1SegAutomaton();
1121 LOG_DEBUG << TString::Format(
"nSegments=%lu", automaton.getSegments().size() ).Data() << endm;
1122 LOG_DEBUG << TString::Format(
"nConnections=%u", automaton.getNumberOfConnections() ).Data() << endm;
1124 if (automaton.getNumberOfConnections() > 9000 ){
1125 LOG_ERROR <<
"Got too many connections, bailing out of tracking" << endm;
1126 return acceptedTrackSeeds;
1133 long long duration = (FwdTrackerUtils::nowNanoSecond() - itStart) * 1e-6;
1134 mEventStats.mStep2Duration.push_back(duration);
1135 itStart = FwdTrackerUtils::nowNanoSecond();
1141 automaton.clearCriteria();
1142 automaton.resetStates();
1143 criteriaPath =
"TrackFinder.Iteration[" + std::to_string(iIteration) +
"].ThreeHitSegments";
1145 if (
false == mConfig.exists(criteriaPath))
1146 criteriaPath =
"TrackFinder.ThreeHitSegments";
1148 clearCriteria( mThreeHitCrit );
1149 mThreeHitCrit = loadCriteria(criteriaPath);
1150 automaton.addCriteria(mThreeHitCrit);
1152 duration = (FwdTrackerUtils::nowNanoSecond() - itStart) * 1e-6;
1153 mEventStats.mStep3Duration.push_back( duration );
1154 if (duration > 2000 || automaton.getNumberOfConnections() > 9000){
1155 LOG_WARN <<
"The Three Hit Criteria took more than 200ms to process, duration: " << duration <<
" ms" << endm;
1156 LOG_WARN <<
"bailing out (skipping subset HNN)" << endm;
1158 std::string subsetPath =
"TrackFinder.Iteration[" + std::to_string(iIteration) +
"].SubsetNN";
1159 size_t minHitsOnTrack = mConfig.get<
size_t>(subsetPath +
":min-hits-on-track", FwdSystem::sNFttLayers);
1160 acceptedTrackSeeds = automaton.getTracks(minHitsOnTrack);
1161 return acceptedTrackSeeds;
1163 itStart = FwdTrackerUtils::nowNanoSecond();
1165 LOG_DEBUG << TString::Format(
"nSegments=%lu", automaton.getSegments().size() ).Data() << endm;
1166 LOG_DEBUG << TString::Format(
"nConnections=%u", automaton.getNumberOfConnections() ).Data() << endm;
1172 std::string subsetPath =
"TrackFinder.Iteration[" + std::to_string(iIteration) +
"].SubsetNN";
1174 if (
false == mConfig.exists(subsetPath))
1175 subsetPath =
"TrackFinder.SubsetNN";
1178 bool findSubsets = mConfig.get<
bool>(subsetPath +
":active",
true);
1181 size_t minHitsOnTrack = mConfig.get<
size_t>(subsetPath +
":min-hits-on-track", 7);
1183 std::vector<Seed_t> tracks = automaton.getTracks(minHitsOnTrack);
1185 float omega = mConfig.get<
float>(subsetPath +
".Omega", 0.75);
1186 float stableThreshold = mConfig.get<
float>(subsetPath +
".StableThreshold", 0.1);
1187 float Ti = mConfig.get<
float>(subsetPath +
".InitialTemp", 2.1);
1188 float Tf = mConfig.get<
float>(subsetPath +
".InfTemp", 0.1);
1190 KiTrack::SubsetHopfieldNN<Seed_t> subset;
1192 subset.setOmega(omega);
1193 subset.setLimitForStable(stableThreshold);
1194 subset.setTStart(Ti);
1200 subset.calculateBestSet(comparer, quality);
1202 acceptedTrackSeeds = subset.getAccepted();
1209 size_t minHitsOnTrack = mConfig.get<
size_t>(subsetPath +
":min-hits-on-track", FwdSystem::sNFttLayers);
1210 acceptedTrackSeeds = automaton.getTracks(minHitsOnTrack);
1213 duration = (FwdTrackerUtils::nowNanoSecond() - itStart) * 1e-6;
1214 mEventStats.mStep4Duration.push_back( duration );
1215 if (duration > 500){
1216 LOG_WARN <<
"The took more than 500ms to process, duration: " << duration <<
" ms" << endm;
1217 LOG_WARN <<
"We got " << acceptedTrackSeeds.size() <<
" tracks this round" << endm;
1219 LOG_DEBUG <<
"We got " << acceptedTrackSeeds.size() <<
" tracks this round" << endm;
1220 return acceptedTrackSeeds;
1232 mTrackSeedsThisIteration.clear();
1235 size_t nHitsThisIteration = nHitsInHitMap(hitmap);
1237 const int minHitsToConsider = 3;
1238 if (nHitsThisIteration < minHitsToConsider) {
1240 LOG_INFO <<
"No hits to consider in this iteration, skipping" << endm;
1244 std::string pslPath =
"TrackFinder.Iteration["+ std::to_string(iIteration) +
"]:nPhiSlices";
1245 if (
false == mConfig.exists( pslPath ) ) pslPath =
"TrackFinder:nPhiSlices";
1246 size_t phi_slice_count = mConfig.get<
size_t>( pslPath, 1 );
1248 if ( phi_slice_count <= 1 || phi_slice_count > 100 ) {
1249 LOG_DEBUG <<
"Tracking without phi slices" << endm;
1253 auto acceptedTracks = doSeedFindingOnHitmapSubset( iIteration, hitmap );
1254 mTrackSeedsThisIteration.insert( mTrackSeedsThisIteration.end(), acceptedTracks.begin(), acceptedTracks.end() );
1257 FwdDataSource::HitMap_t slicedHitMap;
1259 if ( phi_slice_count == 0 || phi_slice_count > 100 ){
1260 LOG_WARN <<
"Invalid phi_slice_count = " << phi_slice_count <<
", resetting to 1" << endm;
1263 float phi_slice = 2 * TMath::Pi() / (float) phi_slice_count;
1264 for (
size_t phi_slice_index = 0; phi_slice_index < phi_slice_count; phi_slice_index++ ){
1266 float phi_min = phi_slice_index * phi_slice - TMath::Pi();
1267 float phi_max = (phi_slice_index + 1) * phi_slice - TMath::Pi();
1268 LOG_INFO << TString::Format(
"phi slice = (%f, %f)", phi_min, phi_max ) << endm;
1275 size_t nHitsThisSlice = 0;
1276 if ( phi_slice_count > 1 ){
1277 nHitsThisSlice = sliceHitMapInPhi( hitmap, slicedHitMap, phi_min, phi_max );
1278 if ( nHitsThisSlice < minHitsToConsider ) {
1283 slicedHitMap = hitmap;
1289 auto acceptedTracks = doSeedFindingOnHitmapSubset( iIteration, slicedHitMap );
1290 mTrackSeedsThisIteration.insert( mTrackSeedsThisIteration.end(), acceptedTracks.begin(), acceptedTracks.end() );
1298 std::string hrmPath =
"TrackFinder.Iteration["+ std::to_string(iIteration) +
"].HitRemover";
1299 if (
false == mConfig.exists( hrmPath ) ) hrmPath =
"TrackFinder.HitRemover";
1301 if (
true == mConfig.get<
bool>( hrmPath +
":active",
true ) ){
1302 removeHits( hitmap, mTrackSeedsThisIteration );
1305 LOG_DEBUG <<
" Found " << mTrackSeedsThisIteration.size() <<
" seed tracks this iteration" << endm;
1307 mTrackSeeds.insert( mTrackSeeds.end(), mTrackSeedsThisIteration.begin(), mTrackSeedsThisIteration.end() );
1315 FwdDataSource::HitMap_t hitmap = mDataSource->getFstHits();
1316 if ( gtr.mStatus->isFitConverged() ==
false || gtr.mMomentum.Perp() < 1e-3) {
1317 LOG_DEBUG <<
"Skipping addFstHitsMc, fit failed" << endm;
1320 mEventStats.mPossibleReFit++;
1323 for (
size_t j = 0; j < 3; j++) {
1324 for (
auto h0 : hitmap[j]) {
1325 if (dynamic_cast<FwdHit *>(h0)->_tid == gtr.mIdTruth) {
1326 fstHitsThisTrack.push_back(h0);
1332 LOG_DEBUG <<
"Found " << gtr.mSeed.size() <<
" existing seed points" << endm;
1333 LOG_DEBUG <<
"Adding " << fstHitsThisTrack.size() <<
" new FST seed points" << endm;
1335 if (fstHitsThisTrack.size() >= 1) {
1336 mEventStats.mAttemptedReFits++;
1337 gtr.mSeed.insert( gtr.mSeed.end(), fstHitsThisTrack.begin(), fstHitsThisTrack.end() );
1349 FwdDataSource::HitMap_t hitmap = mDataSource->getFttHits();
1351 LOG_WARN <<
"Invalid FTT disk number: " << disk <<
", cannot add Ftt points to track" << endm;
1354 if (gtr.mIsFitConverged !=
true)
1356 mEventStats.mPossibleReFit++;
1360 auto msp = mTrackFitter->projectToFtt(disk, gtr.mTrack);
1363 hits_near_plane = findFttHitsNearProjectedState(hitmap[disk], msp);
1364 LOG_DEBUG <<
" Found #FTT hits on plane #" << disk << TString::Format(
" = [%ld]", hits_near_plane.size() ) << endm;
1365 }
catch (genfit::Exception &e) {
1367 LOG_WARN <<
"Unable to get Ftt projections: " << e.what() << endm;
1370 LOG_DEBUG <<
"Found " << gtr.mSeed.size() <<
" existing seed points" << endm;
1372 if ( hits_near_plane.size() > 0 ){
1373 mEventStats.mAttemptedReFits++;
1374 LOG_DEBUG <<
"Adding " << hits_near_plane.size() <<
" new FTT seed points" << endm;
1375 gtr.mSeed.insert( gtr.mSeed.end(), hits_near_plane.begin(), hits_near_plane.end() );
1385 LOG_DEBUG <<
"Looking for FTT hits on this track (MC lookup)" << endm;
1386 LOG_DEBUG <<
"Track TruthId = " << gtr.mIdTruth <<
" vs. " << gtr.mTrack->getMcTrackId() << endm;
1387 FwdDataSource::HitMap_t hitmap = mDataSource->getFttHits();
1388 if ( gtr.mStatus->isFitConverged() ==
false || gtr.mMomentum.Perp() < 1e-6) {
1389 LOG_DEBUG <<
"Skipping addFttHitsMc on this track, fit failed" << endm;
1393 mEventStats.mPossibleReFit++;
1394 Seed_t fttHitsForThisTrack;
1396 for (
size_t j = 0; j < 4; j++) {
1397 for (
auto h0 : hitmap[j]) {
1398 if (dynamic_cast<FwdHit *>(h0)->_tid == gtr.mIdTruth) {
1399 fttHitsForThisTrack.push_back( h0 );
1405 LOG_DEBUG <<
"Found " << fttHitsForThisTrack.size() <<
" FTT Hits on this track (MC lookup)" << endm;
1407 if (fttHitsForThisTrack.size() >= 1) {
1408 mEventStats.mAttemptedReFits++;
1409 gtr.mSeed.insert( gtr.mSeed.end(), fttHitsForThisTrack.begin(), fttHitsForThisTrack.end() );
1420 FwdDataSource::HitMap_t hitmap = mDataSource->getFstHits();
1421 if (gtr.mIsFitConverged ==
false) {
1426 LOG_ERROR <<
"Invalid FST disk number: " << disk << endm;
1429 mEventStats.mPossibleReFit++;
1434 auto msp = mTrackFitter->projectToFst(disk, gtr.mTrack);
1436 nearby_hits = findFstHitsNearProjectedState(hitmap[disk], msp);
1437 }
catch (genfit::Exception &e) {
1438 LOG_WARN <<
"Unable to get projections: " << e.what() << endm;
1440 LOG_DEBUG <<
"Track already has " << gtr.mSeed.size() <<
" existing seed points" << endm;
1442 if ( nearby_hits.size() > 0 ){
1443 mEventStats.mAttemptedReFits++;
1444 LOG_DEBUG <<
"Adding " << nearby_hits.size() <<
" new FST seed points from disk " << disk << endm;
1445 gtr.mSeed.insert( gtr.mSeed.end(), nearby_hits.begin(), nearby_hits.end() );
1460 double probe_phi = TMath::ATan2(msp.getPos().Y(), msp.getPos().X());
1461 double probe_r = sqrt(pow(msp.getPos().X(), 2) + pow(msp.getPos().Y(), 2));
1465 for (
auto h : available_hits) {
1466 double h_phi = TMath::ATan2(h->getY(), h->getX());
1467 double h_r = sqrt(pow(h->getX(), 2) + pow(h->getY(), 2));
1468 double mdphi = fabs(h_phi - probe_phi);
1469 if (mdphi > 2*3.1415926)
1470 mdphi = mdphi - 2*3.1415926;
1472 if ( mdphi < dphi && fabs( h_r - probe_r ) < dr) {
1473 found_hits.push_back(h);
1493 TLorentzVector lv1, lv2;
1494 lv1.SetPxPyPzE( msp.getPos().X(), msp.getPos().Y(), 0, 1 );
1500 KiTrack::IHit *closest =
nullptr;
1502 for (
auto h : available_hits) {
1504 lv2.SetPxPyPzE( h->getX(), h->getY(), 0, 1 );
1505 double sr = lv1.Pt() - lv2.Pt();
1506 double sp = lv1.DeltaPhi( lv2 );
1507 double sx = h->getX() - msp.getPos().X();
1508 double sy = h->getY() - msp.getPos().Y();
1510 if ( fabs(sr) < fabs(mindr) )
1512 if ( fabs(sp) < fabs(mindp) ){
1516 if ( fabs(sx) < fabs(mindx) )
1518 if ( fabs(sy) < fabs(mindy) )
1523 if ( fabs(mindp) < 0.04*5 && fabs(mindr) < 9 ) {
1524 found_hits.push_back(closest);
1530 bool getSaveCriteriaValues() {
return mSaveCriteriaValues; }
1531 std::vector<KiTrack::ICriterion *> getTwoHitCriteria() {
return mTwoHitCrit; }
1532 std::vector<KiTrack::ICriterion *> getThreeHitCriteria() {
return mThreeHitCrit; }
1534 TrackFitter *getTrackFitter() {
return mTrackFitter; }
1535 void setEventVertex( TVector3 v, TMatrixDSym cov ){
1538 mEventVertexHit.setXYZDetId( v.X(), v.Y(), v.Z(), kTpcId );
1539 for (
size_t i=0; i < 3; i++){
1540 for (
size_t j=0; j < 3; j++){
1541 mEventVertexHit._covmat(i,j) = cov(i,j);
1545 TVector3 getEventVertex() {
return mEventVertex; }
1548 unsigned long long int nEvents;
1550 bool mDoTrackFitting =
true;
1551 bool mSaveCriteriaValues =
false;
1552 enum SeedSource { kFstSeed = 0, kFttSeed, kSimSeed, kSeqSeed };
1553 int mSeedSource = 1;
1556 std::string mConfigFile;
1557 size_t mTotalHitsRemoved;
1559 std::vector<GenfitTrackResult> mTrackResults;
1561 std::vector<Seed_t> mTrackSeeds;
1562 std::vector<Seed_t> mTrackSeedsThisIteration;
1568 TVector3 mEventVertex;
1570 genfit::GFRaveVertexFactory mGFRVertices;
1572 std::shared_ptr<FwdDataSource> mDataSource;
1576 std::vector<KiTrack::ICriterion *> mTwoHitCrit;
1577 std::vector<KiTrack::ICriterion *> mThreeHitCrit;
size_t nHitsInHitMap(FwdDataSource::HitMap_t &hitmap)
Determine the total num of hits in the hitmap.
void clearCriteria(std::vector< KiTrack::ICriterion * > &crits)
Clear the loaded criteria.
std::vector< KiTrack::ICriterion * > loadCriteria(string path)
Loads Criteria from XML configuration. Utility function for loading criteria from XML config...
void doSeedFindingIteration(size_t iIteration, FwdDataSource::HitMap_t &hitmap)
Main tracking procedure.
void findTrackSeeds()
Perform the track finding Creates a list of track seeds from the hitmaps Retrieve them using getTrack...
void addFstHits(GenfitTrackResult >r, size_t disk)
Adds compatible FST hits to a track.
void doTrackFitting(const std::vector< Seed_t > &trackSeeds)
Loop on track seeds and fit each one.
void removeHits(FwdDataSource::HitMap_t &hitmap, std::vector< Seed_t > &tracks)
Remove used hits from the hit map.
void setSaveCriteriaValues(bool save)
Set the Save Criteria Values object.
GenfitTrackResult fitTrack(Seed_t &seed, TVector3 *momentumSeedState=nullptr)
Perform a single fit from seed points.
void cleanup()
cleanup the event-wise data structures
void addFttHitsMc(GenfitTrackResult >r)
Adds compatible FTT hits using MC info.
std::vector< float > getCriteriaValues(std::string crit_name)
Get the Criteria Values object.
void doMcTrackFinding(FwdDataSource::McTrackMap_t &mcTrackMap, int seedSource)
MC track finding builds track seeds from available hits using MC association.
std::vector< int > getCriteriaTrackIds(std::string crit_name)
Get the Criteria Track Ids object.
void setDCA(TVector3 pv)
Set the DCA and primary vertex for the event.
void clearSavedCriteriaValues()
Clear the saved values for two hit and three hit criteria.
virtual void initialize(TString geoCache, bool genHistograms)
Initialize FwdTracker.
Seed_t findFttHitsNearProjectedState(Seed_t &available_hits, genfit::MeasuredStateOnPlane &msp, double dx=1.5, double dy=1.5)
Finds FTT hits near projected state.
void mergeHitmaps(FwdDataSource::HitMap_t &hitmap1, FwdDataSource::HitMap_t &hitmap2)
merges the FST and FTT hitmaps into a single hitmap The FTT hits are shifted by the number of FST sec...
void addFstHitsMc(GenfitTrackResult >r)
Adds compatible FST hits to tracks seeded with FTT.
vector< Seed_t > doSeedFindingOnHitmapSubset(size_t iIteration, FwdDataSource::HitMap_t &hitmap)
Does track finding steps on a subset of hits (phi slice)
size_t sliceHitMapInPhi(FwdDataSource::HitMap_t &inputMap, FwdDataSource::HitMap_t &outputMap, float phi_min, float phi_max)
Slices a hitmap into a phi section.
void setConfigFile(std::string cf)
Set the Config File object.
std::vector< std::map< std::string, float > > getCriteriaAllValues(std::string crit_name)
Get the Criteria All Values object.
Seed_t findFstHitsNearProjectedState(Seed_t &available_hits, genfit::MeasuredStateOnPlane &msp, double dphi=0.004 *20.5, double dr=2.75 *2)
Finds FST hits near projected state.
void addFttHits(GenfitTrackResult >r, size_t disk)
Adds compatible FTT hits to tracks seeded with FST.