diff --git a/Tracker/TrackerRecAlgs/TrackerSegmentFit/src/SegmentFitAlg.cxx b/Tracker/TrackerRecAlgs/TrackerSegmentFit/src/SegmentFitAlg.cxx index 392eb9edc43dd2f5bb4aead0087a9abe7e06143c..ff163e105d51b02267ce35e3fdfe43737c5a184c 100644 --- a/Tracker/TrackerRecAlgs/TrackerSegmentFit/src/SegmentFitAlg.cxx +++ b/Tracker/TrackerRecAlgs/TrackerSegmentFit/src/SegmentFitAlg.cxx @@ -20,6 +20,7 @@ #include "TrkRIO_OnTrack/RIO_OnTrack.h" #include "StoreGate/ReadHandle.h" +#include <list> namespace Tracker { @@ -52,7 +53,7 @@ StatusCode SegmentFitAlg::initialize() { } ATH_CHECK(m_clusterContainerKey.initialize()); -// ATH_CHECK(m_trackCollection.initialize()); + ATH_CHECK(m_trackCollection.initialize()); // Get the SCT ID helper ATH_CHECK(detStore()->retrieve(m_idHelper, "FaserSCT_ID")); @@ -67,7 +68,7 @@ StatusCode SegmentFitAlg::initialize() { } // Process one station -StatusCode SegmentFitAlg::reconstructStation(ClusterContainerHandle container, int index) const +StatusCode SegmentFitAlg::reconstructStation(ClusterContainerHandle container, int index, std::unique_ptr<TrackCollection>& tracks) const { int station = m_detMgr->numerology().stationId(index); ATH_MSG_VERBOSE("Processing station " << station); @@ -119,14 +120,16 @@ StatusCode SegmentFitAlg::reconstructStation(ClusterContainerHandle container, i // try adding clusters to the good seeds FitMap allFits = enumerateFits(goodSeeds, badSeeds); - ATH_MSG_VERBOSE("Found " << allFits.size() << " good Fits after enumeration from " << goodSeeds.size() << " seeds."); - for (auto f : allFits) + ATH_MSG_VERBOSE("Found " << allFits.size() << " fits after enumeration from " << goodSeeds.size() << " seeds."); + FitMap goodFits = checkFitQuality(allFits); + ATH_MSG_VERBOSE(goodFits.size() << " out of " << allFits.size() << " fits pass quality cut."); + for (auto f : goodFits) { auto fit = f.second; if (fit->candidates.size() > 4) { ATH_MSG_VERBOSE("Fit Parameters: (" << fit->fitParams(0) << ", " << fit->fitParams(1) << ", " << fit->fitParams(2) << ", " << fit->fitParams(3) << "); chi2 = " << fit->fitChi2 << "; DoF = " << fit->candidates.size() - 4 ); - for (size_t i = fit->clusterMask.find_first(); i != boost::dynamic_bitset<>::npos; i = fit->clusterMask.find_next(i)) + for (size_t i = fit->clusterMask.find_first(); i != ClusterSet::npos; i = fit->clusterMask.find_next(i)) { Amg::Vector3D seedPos = l[i]->cluster.globalPosition(); ATH_MSG_VERBOSE("Fit cluster [" << l[i]->layer << "|" << l[i]->eta << "|" << l[i]->phi << @@ -134,7 +137,20 @@ StatusCode SegmentFitAlg::reconstructStation(ClusterContainerHandle container, i } } } - + FitMap selectedFits = selectFits(goodFits); + ATH_MSG_VERBOSE("Selected " << selectedFits.size() << " fits for output."); + for (auto f : selectedFits) + { + auto fit = f.second; + ATH_MSG_VERBOSE("Fit Parameters: (" << fit->fitParams(0) << ", " << fit->fitParams(1) << ", " << fit->fitParams(2) << ", " << fit->fitParams(3) << "); chi2 = " << fit->fitChi2 << "; DoF = " << fit->candidates.size() - 4 ); + for (size_t i = fit->clusterMask.find_first(); i != ClusterSet::npos; i = fit->clusterMask.find_next(i)) + { + Amg::Vector3D seedPos = l[i]->cluster.globalPosition(); + ATH_MSG_VERBOSE("Fit cluster [" << l[i]->layer << "|" << l[i]->eta << "|" << l[i]->phi << + "|" << l[i]->side << "] at (" << seedPos.x() << ", " << seedPos.y() << ", " << seedPos.z() << ")"); + } + ATH_CHECK(AddTrack(tracks, fit)); + } return StatusCode::SUCCESS; } @@ -279,7 +295,7 @@ SegmentFitAlg::enumerateSeeds(const ClusterList& clusters) const } auto i_compat = clusters[i]->compatible; std::vector<size_t> i_vec {i}; - for (size_t j = i_compat.find_next(i); j != boost::dynamic_bitset<>::npos; j = i_compat.find_next(j)) + for (size_t j = i_compat.find_next(i); j != ClusterSet::npos; j = i_compat.find_next(j)) { size_t ij_views[2] {i_views[0], i_views[1]}; if (clusters[j]->view > 0) @@ -291,7 +307,7 @@ SegmentFitAlg::enumerateSeeds(const ClusterList& clusters) const ij_views[0]++; } auto ij_compat = clusters[j]->compatible & i_compat; - for (size_t k = ij_compat.find_next(j); k != boost::dynamic_bitset<>::npos; k = ij_compat.find_next(k)) + for (size_t k = ij_compat.find_next(j); k != ClusterSet::npos; k = ij_compat.find_next(k)) { size_t ijk_views[2] {ij_views[0], ij_views[1]}; if (clusters[k]->view > 0) @@ -304,7 +320,7 @@ SegmentFitAlg::enumerateSeeds(const ClusterList& clusters) const } if (ijk_views[0] == 0 || ijk_views[1] == 0) continue; // Need two hits in each view to fit auto ijk_compat = clusters[k]->compatible & ij_compat; - for (size_t l = ijk_compat.find_next(k); l != boost::dynamic_bitset<>::npos; l = ijk_compat.find_next(l)) + for (size_t l = ijk_compat.find_next(k); l != ClusterSet::npos; l = ijk_compat.find_next(l)) { size_t ijkl_views[2] {ijk_views[0], ijk_views[1]}; if (clusters[l]->view > 0) @@ -355,7 +371,7 @@ SegmentFitAlg::findGoodSeeds(FitList& allSeeds, FitMap& goodSeeds, MaskSet& badS void SegmentFitAlg::fitClusters(fitInfo& fit) const { - + m_numberOfFits++; Eigen::Matrix< double, 5, 5 > s; s << fit.sums[1] , fit.sums[2] , fit.sums[4] , fit.sums[5] , fit.sums[10] , fit.sums[2] , fit.sums[3] , fit.sums[5] , fit.sums[6] , fit.sums[11] , @@ -391,6 +407,7 @@ SegmentFitAlg::checkFit(const Tracker::SegmentFitAlg::fitInfo& seed) const ATH_MSG_VERBOSE("Rejected fit without covariance matrix."); return false; } + if (m_tanThetaCut > 0.0 && pow(seed.fitParams(2),2.0) + pow(seed.fitParams(3), 2.0) > m_tanThetaCut * m_tanThetaCut) return false; for (auto i : seed.candidates) { double z = seed.clusters[i]->cluster.globalPosition().z(); @@ -420,11 +437,11 @@ SegmentFitAlg::enumerateFits(const FitMap& seeds, const MaskSet& veto) const for (auto p : newSeeds) { auto seed = p.second; - for (size_t i = seed->compatibleMask.find_first(); i != boost::dynamic_bitset<>::npos; i = seed->compatibleMask.find_next(i)) + for (size_t i = seed->compatibleMask.find_first(); i != ClusterSet::npos; i = seed->compatibleMask.find_next(i)) { if (abs(seed->fitParams(1) + seed->fitParams(3) * (seed->clusters[i]->z - fitInfo::zCenter) - seed->clusters[i]->yCenter) > m_yResidualCut) continue; - boost::dynamic_bitset<> mask = seed->clusterMask; + ClusterSet mask { seed->clusterMask }; mask.set(i); if (allFits.find(mask) == allFits.end() && !vetoFit(allFailures, mask)) { @@ -450,13 +467,66 @@ SegmentFitAlg::enumerateFits(const FitMap& seeds, const MaskSet& veto) const return allFits; } -bool -SegmentFitAlg::vetoFit(const MaskSet& badSeeds, const boost::dynamic_bitset<>& hypothesis) const +SegmentFitAlg::FitMap +SegmentFitAlg::checkFitQuality(const FitMap& fits) const { - for (auto bad : badSeeds) + FitMap goodFits { }; + for (auto f : fits) { - if (bad == hypothesis) return true; + auto candidate = f.second; + size_t nDoF = candidate->clusterMask.count() - 4; + if (nDoF == 0 || candidate->fitChi2/nDoF <= m_reducedChi2Cut) goodFits[candidate->clusterMask] = candidate; } + m_numberOfGoodFits += goodFits.size(); + return goodFits; +} + +SegmentFitAlg::FitMap +SegmentFitAlg::selectFits(const FitMap& fits) const +{ + // Select the input fit with the most clusters (using lowest chi2 as tie-breaker) + // Discard any other input fits using those clusters + // Repeat until no input fits remain + FitMap selectedFits { }; + std::list<std::shared_ptr<fitInfo> > info {}; + for (auto fit : fits) + { + info.push_back(fit.second); + } + info.sort([](const std::shared_ptr<fitInfo>& left, const std::shared_ptr<fitInfo>& right) + { + if (left->clusterMask.count() > right->clusterMask.count()) return true; + if (left->clusterMask.count() < right->clusterMask.count()) return false; + if (left->fitChi2 < right->fitChi2) return true; + return false; + }); + + ATH_MSG_VERBOSE("Sorted input fits:"); + for (auto it = info.begin(); it != info.end(); ++it) + { + auto content = *it; + ATH_MSG_VERBOSE("clusters: " << content->clusterMask.count() << " / chi2: " << content->fitChi2) ; + } + ClusterSet usedClusters { clusterInfo::nClusters }; + + while (info.size() > 0) + { + auto selected = info.front(); + ATH_MSG_VERBOSE("Selected nclust = " << selected->clusterMask.count() << " with chi2 = " << selected->fitChi2); + selectedFits[selected->clusterMask] = selected; + usedClusters |= selected->clusterMask; + + info.remove_if([&](std::shared_ptr<fitInfo> p) {return (p->clusterMask & ~usedClusters) != p->clusterMask;}); + } + + m_numberOfSelectedFits += selectedFits.size(); + return selectedFits; +} + +bool +SegmentFitAlg::vetoFit(const MaskSet& badSeeds, const ClusterSet& hypothesis) const +{ + if (badSeeds.count(hypothesis) > 0) return true; return false; } @@ -468,8 +538,8 @@ SegmentFitAlg::execute(const EventContext& ctx) const ++m_numberOfEvents; // setFilterPassed(false, ctx); -// SG::WriteHandle trackContainer{m_trackCollection, ctx}; -// std::unique_ptr<TrackCollection> outputTracks = std::make_unique<TrackCollection>(); + SG::WriteHandle trackContainer{m_trackCollection, ctx}; + std::unique_ptr<TrackCollection> outputTracks = std::make_unique<TrackCollection>(); ClusterContainerHandle clusterContainer{m_clusterContainerKey, ctx}; ATH_CHECK(clusterContainer.isValid()); @@ -477,7 +547,7 @@ SegmentFitAlg::execute(const EventContext& ctx) const for (int stationIdx = 0; stationIdx < m_detMgr->numerology().numStations(); stationIdx++) { - ATH_CHECK(reconstructStation(clusterContainer, stationIdx)); + ATH_CHECK(reconstructStation(clusterContainer, stationIdx, outputTracks)); } // Loop over stations @@ -530,7 +600,7 @@ SegmentFitAlg::execute(const EventContext& ctx) const // ATH_MSG_DEBUG("No stations with clusters found."); // } -// ATH_CHECK(trackContainer.record(std::move(outputTracks))); + ATH_CHECK(trackContainer.record(std::move(outputTracks))); // // Clean up // for (auto entry : clusterMap) @@ -569,77 +639,79 @@ StatusCode SegmentFitAlg::finalize() ATH_MSG_INFO( m_numberOfSeeds << " seeds fit."); ATH_MSG_INFO( m_numberOfGoodSeeds << " good seed fits."); ATH_MSG_INFO( m_numberOfFits << " fits performed." ); + ATH_MSG_INFO( m_numberOfGoodFits << " fits passed quality cuts." ); + ATH_MSG_INFO( m_numberOfSelectedFits << " fits selected for output." ); return StatusCode::SUCCESS; } -// // Method to create and store Trk::Track from fit results -// StatusCode -// SegmentFitAlg::AddTrack(std::unique_ptr<TrackCollection>& tracks, -// const Eigen::Matrix< double, 4, 1 >& fitResult, -// const Eigen::Matrix< double, 4, 4 >& fitCovariance, -// std::vector<const clusterInfo*>& fitClusters, -// double chi2, int ndof) const -// { -// Trk::TrackInfo i { Trk::TrackInfo::TrackFitter::Unknown, Trk::ParticleHypothesis::muon }; -// Trk::FitQuality* q = new Trk::FitQuality {chi2, ndof}; -// DataVector<const Trk::TrackStateOnSurface>* s = new DataVector<const Trk::TrackStateOnSurface> {}; +// Method to create and store Trk::Track from fit results +StatusCode +SegmentFitAlg::AddTrack(std::unique_ptr<TrackCollection>& tracks, + const std::shared_ptr<fitInfo>& theFit) const +{ + Trk::TrackInfo i { Trk::TrackInfo::TrackFitter::Unknown, Trk::ParticleHypothesis::muon }; + Trk::FitQuality* q = new Trk::FitQuality {theFit->fitChi2, static_cast<double>(theFit->clusterMask.count() - 4)}; + DataVector<const Trk::TrackStateOnSurface>* s = new DataVector<const Trk::TrackStateOnSurface> {}; -// int station = m_idHelper->station(fitClusters[0]->cluster->detectorElement()->identify()); + // translate parameters to nominal fit point + s->push_back( GetState(theFit->fitParams, theFit->fitCovariance, nullptr) ); -// // translate parameters to nominal fit point -// s->push_back( GetState(fitResult, fitCovariance, nullptr, station) ); + for (int clusterIndex : theFit->candidates) + { + s->push_back( GetState( theFit->fitParams, theFit->fitCovariance, &theFit->clusters[clusterIndex]->cluster) ); + } -// for (const clusterInfo* cInfo : fitClusters) -// { -// s->push_back( GetState(fitResult, fitCovariance, cInfo->cluster, station) ); -// } + // for (const clusterInfo* cInfo : fitClusters) + // { + // s->push_back( GetState(fitResult, fitCovariance, cInfo->cluster, station) ); + // } -// // Create and store track -// std::unique_ptr<DataVector<const Trk::TrackStateOnSurface>> sink(s); -// tracks->push_back(new Trk::Track(i, std::move(*sink) , q)); -// return StatusCode::SUCCESS; -// } + // Create and store track + std::unique_ptr<DataVector<const Trk::TrackStateOnSurface>> sink(s); + tracks->push_back(new Trk::Track(i, std::move(*sink) , q)); + return StatusCode::SUCCESS; +} -// Trk::TrackStateOnSurface* -// SegmentFitAlg::GetState( const Eigen::Matrix< double, 4, 1 >& fitResult, -// const Eigen::Matrix< double, 4, 4 >& fitCovariance, -// const FaserSCT_Cluster* fitCluster, int station ) const -// { -// // position of fit point: -// // int station = m_idHelper->station(fitCluster->detectorElement()->identify()); -// double zFit = m_zCenter[station]; -// if (fitCluster != nullptr) zFit = fitCluster->globalPosition()[2]; -// Amg::Vector3D pos { fitResult[0] + fitResult[2] * (zFit - m_zCenter[station]), fitResult[1] + fitResult[3] * (zFit - m_zCenter[station]), zFit }; -// double phi = atan2( fitResult[3], fitResult[2] ); -// double theta = atan( sqrt(fitResult[2]*fitResult[2] + fitResult[3]*fitResult[3]) ); -// double qoverp = 1.0/100000.0; - -// Eigen::Matrix< double, 4, 4 > jacobian = Eigen::Matrix< double, 4, 4 >::Zero(); -// jacobian << 1, 0, zFit - m_zCenter[station], 0, -// 0, 1, 0, zFit - m_zCenter[station], -// 0, 0, fitResult[3]/(fitResult[2]*fitResult[2]+fitResult[3]*fitResult[3]), -// fitResult[2]/(fitResult[2]*fitResult[2]+fitResult[3]*fitResult[3]), -// 0, 0, fitResult[2]/(sqrt(fitResult[2]*fitResult[2]+fitResult[3]*fitResult[3])*(1+fitResult[2]*fitResult[2]+fitResult[3]*fitResult[3])), -// fitResult[3]/(sqrt(fitResult[2]*fitResult[2]+fitResult[3]*fitResult[3])*(1+fitResult[2]*fitResult[2]+fitResult[3]*fitResult[3])); -// Eigen::Matrix< double, 4, 4 > covPar {jacobian * fitCovariance * jacobian.transpose()}; -// std::unique_ptr<AmgSymMatrix(5)> covPar5 { new AmgSymMatrix(5){ AmgSymMatrix(5)::Zero() } }; -// covPar5->block<4,4>(0,0) = covPar; -// covPar5->block<1,1>(4,4) = Eigen::Matrix< double, 1, 1 > { (50000.0)*qoverp*qoverp }; - -// FaserSCT_ClusterOnTrack* rot = nullptr; -// if (fitCluster != nullptr) -// { -// rot = new FaserSCT_ClusterOnTrack{ fitCluster, -// Trk::LocalParameters { Trk::DefinedParameter { fitCluster->localPosition()[0], Trk::loc1 }, -// Trk::DefinedParameter { fitCluster->localPosition()[1], Trk::loc2 } }, -// fitCluster->localCovariance(), -// m_idHelper->wafer_hash(fitCluster->detectorElement()->identify())}; -// } -// std::unique_ptr<Trk::TrackParameters> p { new Trk::CurvilinearParameters { pos, phi, theta, qoverp, *(covPar5.release()) } }; -// return new Trk::TrackStateOnSurface { rot, p.release() }; -// } +Trk::TrackStateOnSurface* +SegmentFitAlg::GetState( const Eigen::Matrix< double, 4, 1 >& fitResult, + const Eigen::Matrix< double, 4, 4 >& fitCovariance, + const FaserSCT_Cluster* fitCluster) const +{ + // position of fit point: + // int station = m_idHelper->station(fitCluster->detectorElement()->identify()); + double zFit = fitInfo::zCenter; + if (fitCluster != nullptr) zFit = fitCluster->globalPosition()[2]; + Amg::Vector3D pos { fitResult[0] + fitResult[2] * (zFit - fitInfo::zCenter), fitResult[1] + fitResult[3] * (zFit - fitInfo::zCenter), zFit }; + double phi = atan2( fitResult[3], fitResult[2] ); + double theta = atan( sqrt(fitResult[2]*fitResult[2] + fitResult[3]*fitResult[3]) ); + double qoverp = 1.0/100000.0; + + Eigen::Matrix< double, 4, 4 > jacobian = Eigen::Matrix< double, 4, 4 >::Zero(); + jacobian << 1, 0, zFit - fitInfo::zCenter, 0, + 0, 1, 0, zFit - fitInfo::zCenter, + 0, 0, fitResult[3]/(fitResult[2]*fitResult[2]+fitResult[3]*fitResult[3]), + fitResult[2]/(fitResult[2]*fitResult[2]+fitResult[3]*fitResult[3]), + 0, 0, fitResult[2]/(sqrt(fitResult[2]*fitResult[2]+fitResult[3]*fitResult[3])*(1+fitResult[2]*fitResult[2]+fitResult[3]*fitResult[3])), + fitResult[3]/(sqrt(fitResult[2]*fitResult[2]+fitResult[3]*fitResult[3])*(1+fitResult[2]*fitResult[2]+fitResult[3]*fitResult[3])); + Eigen::Matrix< double, 4, 4 > covPar {jacobian * fitCovariance * jacobian.transpose()}; + std::unique_ptr<AmgSymMatrix(5)> covPar5 { new AmgSymMatrix(5){ AmgSymMatrix(5)::Zero() } }; + covPar5->block<4,4>(0,0) = covPar; + covPar5->block<1,1>(4,4) = Eigen::Matrix< double, 1, 1 > { (50000.0)*qoverp*qoverp }; + + FaserSCT_ClusterOnTrack* rot = nullptr; + if (fitCluster != nullptr) + { + rot = new FaserSCT_ClusterOnTrack{ fitCluster, + Trk::LocalParameters { Trk::DefinedParameter { fitCluster->localPosition()[0], Trk::loc1 }, + Trk::DefinedParameter { fitCluster->localPosition()[1], Trk::loc2 } }, + fitCluster->localCovariance(), + m_idHelper->wafer_hash(fitCluster->detectorElement()->identify())}; + } + std::unique_ptr<Trk::TrackParameters> p { new Trk::CurvilinearParameters { pos, phi, theta, qoverp, *(covPar5.release()) } }; + return new Trk::TrackStateOnSurface { rot, p.release() }; +} // void // SegmentFitAlg::Residuals(std::vector<const clusterInfo*>& fitClusters) const diff --git a/Tracker/TrackerRecAlgs/TrackerSegmentFit/src/SegmentFitAlg.h b/Tracker/TrackerRecAlgs/TrackerSegmentFit/src/SegmentFitAlg.h index 29f184a33d35f008d89e2c12849e1616f64cbcb5..eb41946cd0a9094a24919eaf6824705094afa234 100644 --- a/Tracker/TrackerRecAlgs/TrackerSegmentFit/src/SegmentFitAlg.h +++ b/Tracker/TrackerRecAlgs/TrackerSegmentFit/src/SegmentFitAlg.h @@ -47,6 +47,7 @@ namespace TrackerDD namespace Tracker { + typedef boost::dynamic_bitset<> ClusterSet; /** * @class SCT_Clusterization @@ -72,6 +73,7 @@ class SegmentFitAlg : public AthReentrantAlgorithm virtual bool isClonable() const override { return true; }; //@} + private: /** @name Disallow default instantiation, copy, assignment */ //@{ @@ -186,7 +188,7 @@ class SegmentFitAlg : public AthReentrantAlgorithm static size_t nClusters; uint index; const FaserSCT_Cluster& cluster; - boost::dynamic_bitset<> compatible; + ClusterSet compatible; double sinAlpha; double cosAlpha; double u; @@ -223,6 +225,21 @@ class SegmentFitAlg : public AthReentrantAlgorithm addCluster(index); } } + // fitInfo(const fitInfo& f) + // : clusters { f.clusters } + // , candidates { f.candidates } + // , clusterMask { f.clusterMask } + // , compatibleMask { f.compatibleMask } + // , fitParams { f.fitParams } + // , fitCovariance { f.fitCovariance } + // , fitChi2 { f.fitChi2 } + // , hasCovariance { f.hasCovariance } + // { + // for (size_t i = 0; i < 15; i++) + // { + // sums[i] = f.sums[i]; + // } + // } void addCluster(size_t n) { candidates.push_back(n); @@ -255,7 +272,7 @@ class SegmentFitAlg : public AthReentrantAlgorithm fitCovariance.setZero(); fitChi2 = 0; hasCovariance = false; - } + } } HepGeom::Point3D<double> extrapolateFit(double z) const { @@ -263,8 +280,8 @@ class SegmentFitAlg : public AthReentrantAlgorithm } const ClusterList& clusters; std::vector<size_t> candidates; - boost::dynamic_bitset<> clusterMask; - boost::dynamic_bitset<> compatibleMask; + ClusterSet clusterMask; + ClusterSet compatibleMask; double sums[15]; static double zCenter; Eigen::Matrix<double, 4, 1> fitParams; @@ -272,13 +289,14 @@ class SegmentFitAlg : public AthReentrantAlgorithm double fitChi2; bool hasCovariance; }; + typedef std::vector<std::shared_ptr<fitInfo> > FitList; - typedef std::unordered_map<boost::dynamic_bitset<>, std::shared_ptr<fitInfo> > FitMap; - typedef std::unordered_set<boost::dynamic_bitset<> > MaskSet; + typedef std::unordered_map<ClusterSet, std::shared_ptr<fitInfo> > FitMap; + typedef std::unordered_set<ClusterSet> MaskSet; typedef SG::ReadHandle<FaserSCT_ClusterContainer> ClusterContainerHandle; - StatusCode reconstructStation(ClusterContainerHandle clusters, int index) const; + StatusCode reconstructStation(ClusterContainerHandle clusters, int index, std::unique_ptr<TrackCollection>& tracks) const; size_t stationOccupancy(ClusterContainerHandle clusters, int station) const; double findCenter(int station) const; ClusterList tabulateClusters(ClusterContainerHandle clusters, int station) const; @@ -288,7 +306,9 @@ class SegmentFitAlg : public AthReentrantAlgorithm void fitClusters(fitInfo& fit) const; bool checkFit(const fitInfo& fit) const; FitMap enumerateFits(const FitMap& seeds, const MaskSet& veto) const; - bool vetoFit(const MaskSet& badSeeds, const boost::dynamic_bitset<>& hypothesis) const; + FitMap checkFitQuality(const FitMap& fits) const; + FitMap selectFits(const FitMap& fits) const; + bool vetoFit(const MaskSet& badSeeds, const ClusterSet& hypothesis) const; int getStation(const Tracker::FaserSCT_ClusterCollection* collection) const; // struct layerCombo @@ -369,16 +389,12 @@ class SegmentFitAlg : public AthReentrantAlgorithm // } // }; - // StatusCode AddTrack(std::unique_ptr<TrackCollection>& tracks, - // const Eigen::Matrix< double, 4, 1 >& fitResult, - // const Eigen::Matrix< double, 4, 4>& fitCovariance, - // std::vector<const clusterInfo*>& fitClusters, - // double chi2, int ndof) const; + StatusCode AddTrack(std::unique_ptr<TrackCollection>& tracks, + const std::shared_ptr<fitInfo>& theFit) const; - // Trk::TrackStateOnSurface* GetState( const Eigen::Matrix< double, 4, 1 >& fitResult, - // const Eigen::Matrix< double, 4, 4 >& fitCovariance, - // const FaserSCT_Cluster* fitCluster, - // int station ) const; + Trk::TrackStateOnSurface* GetState( const Eigen::Matrix< double, 4, 1 >& fitResult, + const Eigen::Matrix< double, 4, 4 >& fitCovariance, + const FaserSCT_Cluster* fitCluster ) const; // void // Residuals(std::vector<const clusterInfo*>& fitClusters) const; @@ -387,7 +403,7 @@ class SegmentFitAlg : public AthReentrantAlgorithm const TrackerDD::SCT_DetectorManager* m_detMgr {nullptr}; SG::ReadHandleKey<FaserSCT_ClusterContainer> m_clusterContainerKey { this, "ClustersName", "SCT_ClusterContainer", "FaserSCT cluster container" }; - // SG::WriteHandleKey<TrackCollection> m_trackCollection { this, "OutputCollection", "ClusterFit", "Output track collection name" }; + SG::WriteHandleKey<TrackCollection> m_trackCollection { this, "OutputCollection", "SegmentFit", "Output track collection name" }; UnsignedIntegerProperty m_minClustersPerStation { this, "MinClusters", 4, "Minimum number of clusters allowed in a station" }; UnsignedIntegerProperty m_maxClustersPerStation { this, "MaxClusters", 36, "Maximum number of clusters allowed in a station" }; @@ -396,6 +412,8 @@ class SegmentFitAlg : public AthReentrantAlgorithm IntegerProperty m_edgeStrips { this, "EdgeStrips", 32, "Number of strips from either edge of sensor considered for overlap" }; DoubleProperty m_waferTolerance { this, "WaferTolerance", 3 * Gaudi::Units::mm, "Wafer boundary tolerance for extrapolated fit." }; DoubleProperty m_yResidualCut { this, "ResidualCut", 3 * Gaudi::Units::mm, "Cluster y tolerance for compatibility with extrapolated fit." }; + DoubleProperty m_tanThetaCut { this, "TanThetaCut", 0.0, "Maximum accepted tangent of track angle from beam axis; 0 means no cut."}; + DoubleProperty m_reducedChi2Cut { this, "ReducedChi2Cut", 10.0, "Maximum accepted chi^2 per degree of freedom for final fits; 0 means no cut." }; mutable std::atomic<int> m_numberOfEvents{0}; mutable std::atomic<int> m_numberExcessOccupancy{0}; @@ -410,6 +428,8 @@ class SegmentFitAlg : public AthReentrantAlgorithm mutable std::atomic<int> m_numberOfSeeds{0}; mutable std::atomic<int> m_numberOfGoodSeeds{0}; mutable std::atomic<int> m_numberOfFits{0}; + mutable std::atomic<int> m_numberOfGoodFits{0}; + mutable std::atomic<int> m_numberOfSelectedFits{0}; }; inline int SegmentFitAlg::getStation(const Tracker::FaserSCT_ClusterCollection* collection) const diff --git a/Tracker/TrackerRecAlgs/TrackerSegmentFit/test/TestBeamSegmentFitDbg.py b/Tracker/TrackerRecAlgs/TrackerSegmentFit/test/TestBeamSegmentFitDbg.py index 450b6313f2bd6bebf115f5bda613e28cec15a153..c4fcd2a24f74dee7e00cf1d1317882f088bbbf20 100755 --- a/Tracker/TrackerRecAlgs/TrackerSegmentFit/test/TestBeamSegmentFitDbg.py +++ b/Tracker/TrackerRecAlgs/TrackerSegmentFit/test/TestBeamSegmentFitDbg.py @@ -14,7 +14,7 @@ from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg from AthenaPoolCnvSvc.PoolWriteConfig import PoolWriteCfg from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg #from Digitization.DigitizationParametersConfig import writeDigitizationMetadata -from ScintRecAlgs.ScintRecAlgsConfig import WaveformReconstructionCfg +from WaveRecAlgs.WaveRecAlgsConfig import WaveformReconstructionCfg from TrackerPrepRawDataFormation.TrackerPrepRawDataFormationConfig import FaserSCT_ClusterizationCfg from TrackerSegmentFit.TrackerSegmentFitConfig import SegmentFitAlgCfg from TrackerSpacePointFormation.TrackerSpacePointFormationConfig import TrackerSpacePointFinderCfg @@ -26,10 +26,10 @@ Configurable.configurableRun3Behavior = True # Configure ConfigFlags.Input.Files = [ - 'tb.raw', + 'tbMu.raw', ] -ConfigFlags.Output.ESDFileName = "tb.ESD.pool.root" -ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Always needed; must match FaserVersion +ConfigFlags.Output.ESDFileName = "tbMu.ESD.pool.root" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-TB00" # Always needed; must match FaserVersion ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" # Use MC conditions for now ConfigFlags.Input.ProjectName = "data21" # Needed to bypass autoconfig ConfigFlags.Input.isMC = False # Needed to bypass autoconfig @@ -38,7 +38,7 @@ ConfigFlags.Common.isOnline = False ConfigFlags.GeoModel.Align.Dynamic = False ConfigFlags.Beam.NumberOfCollisions = 0. -ConfigFlags.Detector.GeometryFaserSCT = True +# ConfigFlags.Detector.GeometryFaserSCT = True ConfigFlags.lock() @@ -53,34 +53,64 @@ from FaserByteStreamCnvSvc.FaserByteStreamCnvSvcConfig import FaserByteStreamCnv acc.merge(FaserByteStreamCnvSvcCfg(ConfigFlags)) acc.merge(WaveformReconstructionCfg(ConfigFlags)) acc.merge(FaserSCT_ClusterizationCfg(ConfigFlags, DataObjectName="SCT_EDGEMODE_RDOs")) -acc.merge(SegmentFitAlgCfg(ConfigFlags)) +acc.merge(SegmentFitAlgCfg(ConfigFlags, TanThetaCut = 0.0, MaxClusters = 25)) acc.merge(TrackerSpacePointFinderCfg(ConfigFlags)) acc.getEventAlgo("Tracker::SegmentFitAlg").OutputLevel = VERBOSE -from AthenaConfiguration.ComponentFactory import CompFactory -decoderTool = CompFactory.ScintWaveformDecoderTool(name = "ScintWaveformDecoderTool", - CaloChannels = [0, 1, 2, 3, 4, 5], - PreshowerChannels = [6, 7], - TriggerChannels = [8, 9], - VetoChannels=[]) -acc.addPublicTool(decoderTool) +# from AthenaConfiguration.ComponentFactory import CompFactory +# decoderTool = CompFactory.ScintWaveformDecoderTool(name = "ScintWaveformDecoderTool", +# CaloChannels = [0, 1, 2, 3, 4, 5], +# PreshowerChannels = [6, 7], +# TriggerChannels = [8, 9], +# VetoChannels=[]) +# acc.addPublicTool(decoderTool) -# explicitly save RDO information +# # explicitly save RDO information +# from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg +# itemList = [ "xAOD::EventInfo#*", +# "xAOD::EventAuxInfo#*", +# "FaserSCT_RDO_Container#*", +# "xAOD::FaserTriggerData#*", +# "xAOD::FaserTriggerDataAux#*", +# "ScintWaveformContainer#*", +# "TrackCollection#*", +# "xAOD::WaveformHitContainer#*", +# "xAOD::WaveformHitAuxContainer#*", +# "xAOD::WaveformClock#*", +# "xAOD::WaveformClockAuxInfo#*", +# ] +# acc.merge(OutputStreamCfg(ConfigFlags, "ESD", itemList)) +# acc.getEventAlgo("OutputStreamESD").AcceptAlgs = ["Tracker::SegmentFitAlg"] + +# +# Configure output from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg -itemList = [ "xAOD::EventInfo#*", - "xAOD::EventAuxInfo#*", - "FaserSCT_RDO_Container#*", - "xAOD::FaserTriggerData#*", - "xAOD::FaserTriggerDataAux#*", - "ScintWaveformContainer#*", - "TrackCollection#*", - "xAOD::WaveformHitContainer#*", - "xAOD::WaveformHitAuxContainer#*", - "xAOD::WaveformClock#*", - "xAOD::WaveformClockAuxInfo#*", - ] -acc.merge(OutputStreamCfg(ConfigFlags, "ESD", itemList)) -acc.getEventAlgo("OutputStreamESD").AcceptAlgs = ["Tracker::SegmentFitAlg"] +itemList = [ "xAOD::EventInfo#*" + , "xAOD::EventAuxInfo#*" + , "xAOD::FaserTriggerData#*" + , "xAOD::FaserTriggerDataAux#*" + , "FaserSCT_RDO_Container#*" + , "Tracker::FaserSCT_ClusterContainer#*" + #, "Tracker::SCT_SpacePointContainer#*" + #, "Tracker::SCT_SpacePointOverlapCollection#*" + , "TrackCollection#*" +] +acc.merge(OutputStreamCfg(ConfigFlags, "xAOD", itemList)) + +# Waveform reconstruction +from WaveRecAlgs.WaveRecAlgsConfig import WaveformReconstructionOutputCfg +acc.merge(WaveformReconstructionOutputCfg(ConfigFlags)) + + + +# Hack to avoid problem with our use of MC databases when isMC = False +replicaSvc = acc.getService("DBReplicaSvc") +replicaSvc.COOLSQLiteVetoPattern = "" +replicaSvc.UseCOOLSQLite = True +replicaSvc.UseCOOLFrontier = False +replicaSvc.UseGeomSQLite = True + + # Timing #acc.merge(MergeRecoTimingObjCfg(ConfigFlags))