22 [](
const auto& meas) { return xAOD::isNSW(meas->type()); })};
24 return segment.
nDoF();
28 unsigned int nMeas {0};
33 nMeas += meas->measuresEta();
39 const unsigned int nDoF {NDoF(segment)};
40 return nDoF > 0
ul ? segment.
chi2() / nDoF : segment.
chi2();
45 const unsigned int nDoFNew {NDoF(newSegment)};
46 const unsigned int nDoFOld {NDoF(oldSegment)};
47 if (nDoFNew == nDoFOld) {
48 return newSegment.
chi2() < oldSegment.
chi2();
50 return nDoFNew > nDoFOld;
65 static constexpr double minZVariance {Acts::square(0.1 * Gaudi::Units::mm)};
69using namespace Muon::MuonStationIndex;
71using namespace Acts::UnitLiterals;
95 fitCfg.calcAlongStrip =
false;
106 fitCfg.parsToUse = {ParamDefs::y0, ParamDefs::theta};
110 nswFitCfg.parsToUse = {ParamDefs::x0, ParamDefs::y0, ParamDefs::theta, ParamDefs::phi};
112 m_fitter = std::make_unique<LineFitter>(name(), std::move(fitCfg));
113 m_nswFitter = std::make_unique<LineFitter>(name(), std::move(nswFitCfg));
116 MdtSegmentSeeder::Config genCfg{};
118 genCfg.busyLayerLimit = 3;
119 genCfg.startWithPattern =
false;
120 m_mdtSeeder = std::make_unique<MdtSegmentSeeder>(std::move(genCfg),
141 return StatusCode::SUCCESS;
160 std::size_t patIdx{0};
161 ATH_MSG_DEBUG(__func__<<
"() Start fitting segments in " << inPatterns->
size() <<
" global patterns");
164 std::vector<SegmentSeedPair_t> seedSegPairs{
processPattern(ctx, *gctx, *pat)};
166 if (seedSegPairs.size() <= 1u) {
167 ATH_MSG_DEBUG(__func__<<
"() Not enough muon segments to construct a candidate - abort pattern"
168 << std::endl << *pat);
174 const bool hasPhi {std::ranges::any_of(seedSegPairs, [](
const SegmentSeedPair_t& seg) {
175 return std::ranges::any_of(seg.second->measurements(), [](
const auto& meas) {
176 return isGoodHit(*meas) && meas->measuresPhi(); });
178 const Segment* toAddPhi{
nullptr};
186 const Segment_t& seg = seedSegPair.second;
190 dec_patternLink(*segXAOD) = PatLink_t{*inPatterns, patIdx};
193 if (toAddPhi && toAddPhi == seg.get()) {
204 return StatusCode::SUCCESS;
207std::vector<MuonFastSegmentFittingAlg::SegmentSeedPair_t>
213 std::vector<StIndex> stations {pattern.getStations()};
219 return layerRank(l1) < layerRank(l2);
222 std::vector<SegmentSeedPair_t> muonSegments{};
223 muonSegments.reserve(3u);
224 for (
const StIndex st : stations) {
227 if (muonSegments.size() > 2 || (st == stations.back() && muonSegments.size() == 0.)) {
233 return toLayerIndex(seg.second->msSector()->chamberIndex()) == layer; })) {
234 ATH_MSG_VERBOSE(__func__<<
"() Already found a segment in layer " << layer
235 <<
" - skip station " << st);
239 const HitVec_t& hits {pattern.hitsInStation(st)};
240 const std::vector<Bucket_t>& buckets {pattern.bucketsInStation(st)};
243 std::unordered_map<const MuonGMR4::SpectrometerSector*, HitVec_t> hitsPerSector{};
244 std::ranges::for_each(hits, [&hitsPerSector](
Hit_t hit) {
245 hitsPerSector[
hit->msSector()].push_back(
hit);
249 std::vector<const MuonGMR4::SpectrometerSector*> sectorsInStation{};
250 sectorsInStation.reserve(hitsPerSector.size());
251 std::ranges::transform(hitsPerSector, std::back_inserter(sectorsInStation),
252 [](
const auto&
pair) {
return pair.first; });
253 assert(sectorsInStation.size() > 0 && sectorsInStation.size() <= 2u &&
254 (sectorsInStation.size() == 1u ||
isSmall(sectorsInStation[0]->chamberIndex()) !=
isSmall(sectorsInStation[1]->chamberIndex())));
256 if (sectorsInStation.size() == 2u && !
isSmall(sectorsInStation[0]->chamberIndex())) {
257 std::swap(sectorsInStation[0], sectorsInStation[1]);
260 std::vector<SegmentSeedPair_t> stSegments{};
261 stSegments.reserve(sectorsInStation.size());
265 ATH_MSG_VERBOSE(__func__<<
"() Start segment fitting in sector " << sector->identString()
266 <<
" station " << st <<
" with " << hitsPerSector[sector].size() <<
" hits.");
267 HitVec_t& sectorHits {hitsPerSector[sector]};
271 std::vector<Bucket_t> bucketsInSector {};
272 std::ranges::copy_if(buckets, std::back_inserter(bucketsInSector),
275 if (bucketsInSector.empty()) {
276 throw std::runtime_error(std::format(
"No parent bucket found for sector {} in station {}",
277 sector->identString(),
stName(st)));
279 if (bucketsInSector.size() > 1u) {
280 Bucket_t primaryBucket {*std::ranges::max_element(bucketsInSector,
281 std::ranges::less{}, [§orHits](
const Bucket_t& b) {
282 return std::ranges::count_if(sectorHits, [&b](
const Hit_t&
hit) {
283 return std::ranges::any_of(*b, [&
hit](
const auto&
h) {
284 return h.get() ==
hit; });
287 bucketsInSector.clear();
288 bucketsInSector.push_back(primaryBucket);
290 Bucket_t parentBucket {bucketsInSector.back()};
293 parentBucket, std::move(sectorHits))};
295 ATH_MSG_VERBOSE(__func__<<
"() Successfully fitted segment in station "<< st
298 <<
", chi2: "<< segment->second->chi2()<<
", nDoF: "<<NDoF(*segment->second)<<std::endl
299 <<
print(segment->second->measurements()));
300 stSegments.push_back(std::move(*segment));
302 const Segment_t& newSegment {stSegments.back().second};
309 ATH_MSG_VERBOSE(__func__<<
"() No segment could be fitted. Try next sector, if any.");
311 if (stSegments.empty()) {
312 ATH_MSG_DEBUG(
"No segment could be fitted in station " << st <<
" for " << pattern);
317 return betterSegment(*s2.second, *s1.second); })
318 : stSegments.back()};
320 <<
", dir: " <<
Amg::toString(bestSeg.second->direction()) <<
", chi2: " << bestSeg.second->chi2() <<
", nDoF: " << NDoF(*bestSeg.second));
322 muonSegments.push_back(std::move(bestSeg));
324 ATH_MSG_DEBUG(__func__<<
"() Found "<< muonSegments.size()<<
" muon segments to construct a candidate.");
331 std::vector<Hit_t>&& hits)
const {
333 std::set<unsigned> layers{};
334 std::ranges::for_each(hits, [
this, &layers](
Hit_t hit) {
340 ATH_MSG_VERBOSE(__func__<<
"() Not enough layers with hits to fit a segment, skipping!");
346 auto [ValidHits, initialPars] {
initializePars(localToGlobal, hits)};
347 if (ValidHits.empty()) {
348 ATH_MSG_VERBOSE(__func__<<
"() Failed to initialize initial parameters for segment fitting.");
351 ATH_MSG_VERBOSE(__func__<<
"() Start segment fitting with initial parameters: "
354 const auto [locPos, locDir] {
makeLine(initialPars)};
355 auto houghSeed {std::make_unique<SegmentSeed>(
houghTanBeta(locDir), locPos.y(),
357 ValidHits.size(), std::move(ValidHits), parentBucket)};
361 std::ranges::all_of(houghSeed->getHitsInMax(), [](
const Hit_t&
hit) {
362 return xAOD::isNSW(hit->type()); })) {
364 ATH_MSG_VERBOSE(__func__<<
"() Found NSW hits. Use the NSW fitter to fit the segment.");
367 houghSeed->getHitsInMax(), locPos, locDir, 0.)};
369 houghSeed.get(), initialPars, localToGlobal, std::move(calibHits))};
371 return std::make_pair(std::move(houghSeed), std::move(
res));
378 std::vector<Segment_t> segments{};
382 while (
auto seed =
m_mdtSeeder->nextSeed(cctx, seedState)) {
383 ATH_MSG_VERBOSE(__func__<<
"() Found a seed. Try to fit the segment...");
386 localToGlobal, std::move(seed->hits))};
388 segments.push_back(std::move(segment));
392 if (!segments.empty()) {
393 ATH_MSG_VERBOSE(__func__<<
"() In total "<<segments.size()<<
" segment were constructed. Keep the best one.");
394 if (
msgLvl(MSG::VERBOSE) && segments.size() > 1) {
397 <<
", dir: "<<
Amg::toString(seg->direction())<<
", chi2: "<<seg->chi2()
398 <<
", nDoF: "<<NDoF(*seg)<<std::endl<<
print(seg->measurements()));
402 return betterSegment(*s2, *s1);
404 return std::make_pair(std::move(houghSeed), std::move(bestSegment));
409std::pair<MuonFastSegmentFittingAlg::HitVec_t, Parameters>
417 return std::pair<HitVec_t, Parameters>{};
419 const Amg::Vector3D beamspotPos {localToGlobal.inverse().translation()};
420 const Beamspot beamspot{beamspotPos.x(), beamspotPos.z(),
428 phiPars = std::make_optional(
Line2D_t{0., 0.});
433 if (!
hit->measuresEta()) {
434 etaHits.push_back(
hit);
438 const auto [tanAlpha, x0] = *phiPars;
439 const auto [tanBeta , y0] = *etaPars;
440 pars[Acts::toUnderlying(ParamDefs::y0)] = y0;
441 pars[Acts::toUnderlying(ParamDefs::x0)] = x0;
442 const Amg::Vector3D dir {Acts::makeDirectionFromAxisTangents(tanAlpha, tanBeta)};
443 pars[Acts::toUnderlying(ParamDefs::theta)] = dir.theta();
444 pars[Acts::toUnderlying(ParamDefs::phi)] = dir.phi();
446 return std::make_pair(std::move(etaHits), pars);
451 const std::optional<Beamspot>& beamspot)
const {
455 <<
" with "<<hits.size()<<
" hits"<<(beamspot ?
" & beamspot." :
"."));
461 double S {0.}, Sy {0.}, Sz {0.}, Szz {0.}, Syz {0.};
463 auto accumulate = [&](
const double y,
const double z,
const double w) {
478 ?
hit->covariance()[CovIdx] + Acts::square(
hit->driftRadius())
479 :
hit->covariance()[CovIdx]};
481 validHits.push_back(
hit);
489 accumulate(beamspot->coord, beamspot->z, 1./beamspot->cov_coordCoord);
492 if (validHits.size() + beamspot.has_value() < 2u) {
493 ATH_MSG_VERBOSE(__func__<<
"() Not enough hits to do a linear regression in the "
494 <<Plane<<
". Valid hits: "<<
print(validHits));
495 return std::make_pair(std::move(validHits), std::nullopt);
499 const double det {S * Szz - Acts::square(Sz)};
500 if (S <= Acts::s_epsilon ||
501 (det / Acts::square(S)) < minZVariance) {
503 <<Plane<<
": total weight: "<<S<<
", variance in z: "
504 <<det/Acts::square(S)<<
" valid hits: "<<
print(validHits));
505 return std::make_pair(std::move(validHits), std::nullopt);
511 <<Plane<<
" -> "<<pars<<
", with "<<validHits.size()
512 <<
" valid hits"<<(beamspot ?
" and beamspot." :
"."));
513 return std::make_pair(std::move(validHits), std::move(pars));
523 return toLayerIndex(seg.second->msSector()->chamberIndex()) == layer; });
524 if (it != segs.end()) {
525 return it->second.get();
534 const Amg::Vector3D globalAxisDir {localToGlobal.rotation() * localAxisDir};
542 return os <<
"etaPlane";
544 return os <<
"phiPlane";
551 return os <<
"Intercept";
553 return os <<
"Slope";
559 return os <<
"Line [slope, intercept]: ["
564 return os <<
"Beamspot [z, coord, sigmaCoord]: ["
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
bool accumulate(AccumulateMap &map, std::vector< module_t > const &modules, FPGATrackSimMatrixAccumulator const &acc)
Accumulates an accumulator (e.g.
std::pair< std::vector< unsigned int >, bool > res
std::unique_ptr< const Acts::Logger > makeActsAthenaLogger(IMessageSvc *svc, const std::string &name, int level, std::optional< std::string > parent_name)
bool msgLvl(const MSG::Level lvl) const
size_type size() const noexcept
Returns the number of elements in the collection.
ElementLink implementation for ROOT usage.
A spectrometer sector forms the envelope of all chambers that are placed in the same MS sector & laye...
Muon::MuonStationIndex::ChIndex chamberIndex() const
Returns the chamber index scheme.
Data class to represent an eta maximum in hough space.
std::vector< CalibSpacePointPtr > CalibSpacePointVec
std::unique_ptr< LineFitter > m_fitter
Pointer to the actual segment fitter.
BooleanProperty m_fastPreFitter
The fast fitter is treated as a pre fitter.
SG::WriteHandleKey< xAOD::MuonSegmentContainer > m_outSegments
Write handle key for the output segments.
BooleanProperty m_useFastFitter
Use the fast Mdt fitter where possible.
Muon::MuonStationIndex::StIndex StIndex
Type alias for the station index.
SegmentFit::Parameters Parameters
Type alias for the segment fitting parameters.
std::vector< Hit_t > HitVec_t
virtual StatusCode initialize() override
const SpacePointBucket * Bucket_t
Type alias for the bucket type.
const Segment * findSegmentToAddPhi(std::vector< SegmentSeedPair_t > &segs) const
Find the segment to which increase the phi measurement count.
CoordPlane
Define the coordinate planes.
BooleanProperty m_recalibInFit
Toggle the recalibration of hits during the segment fit.
DoubleProperty m_outlierRemovalCut
Cut on the segment chi2 / nDoF to launch the outlier removal.
DoubleProperty m_recoveryPull
Pull value for hit recovery.
Acts::SquareMatrix< 3 > m_beamspotCov
Covariance matrix of the beam spot.
DoubleProperty m_seedHitChi2
Two mdt seeds are the same if their defining parameters match wihin.
std::unique_ptr< LineFitter > m_nswFitter
Pointer to the NSW segment fitter.
std::pair< HitVec_t, std::optional< Line2D_t > > RegressionRes_t
Type alias for the result of the linear regression, consisting of the valid hits and line parameters.
std::pair< Seed_t, Segment_t > SegmentSeedPair_t
Struct to hold the segment and the seed for the needed lifetime.
SG::ReadHandleKey< GlobalPatternContainer > m_inPatterns
Write handle key for the output global patterns.
BooleanProperty m_ignoreFailedPreFit
Switch to try the full fit when the fast pre-fitter fails.
BooleanProperty m_beamSpotLength
Beam spot length.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Handle to the MuonIdHelper service.
virtual StatusCode execute(const EventContext &ctx) const override
ToolHandle< ISpacePointCalibrator > m_calibTool
Handle to the space point calibrator tool.
SG::WriteHandleKey< xAOD::CombinedMuonStripContainer > m_combMeasKey
Auxiliary container to model two measurements in the same gas gap as a single track state.
std::unique_ptr< Segment > Segment_t
Type alias for the segment type.
std::pair< HitVec_t, Parameters > initializePars(const Amg::Transform3D &localToGlobal, const HitVec_t &hits) const
Estimate the initial parameters for the segment fitting.
UnsignedIntegerProperty m_precHitCut
Minimum number of precision hits to accept the segment.
DecorKey_t m_prdStateKey
Decoration to the PrdLink state (I.e.
DecorKey_t m_localSegCovKey
Decoration of the local fit covariance parameters.
const SpacePoint * Hit_t
Type alias for the hit type & associated vector.
BooleanProperty m_beamSpotRadius
Beam spot radius.
DecorKey_t m_patternKey
Parent global pattern decoration of the segments.
BooleanProperty m_recalibSeed
Toggle seed recalibration.
ParamDefs2D
Define the line parameters.
@ slope
Tangent of the angle, defined as dy/dz or dx/dz according to the plane.
@ intercept
Intercept at z=0 (i.e.
ToolHandle< MuonValR4::IPatternVisualizationTool > m_segVisionTool
Handle to the visualization tool for segments.
std::optional< SegmentSeedPair_t > SegmentSeedOpt_t
Type alias for the segment-seed optional.
UnsignedIntegerProperty m_maxIter
Tune the number of iterations.
SpacePointPerLayerSorter m_spSorter
Spacepoint sorter per logical measurement layer.
double beamspotCov(const CoordPlane Plane, const Amg::Transform3D &localToGlobal) const
Helper method to compute the beamspot covariance in one local coordinate.
std::array< double, Acts::toUnderlying(ParamDefs2D::nParams)> Line2D_t
Type alias for the line representation.
BooleanProperty m_hessianResidual
Use the expliciit Hessian in the residual calculation.
DecorKey_t m_prdLinkKey
Decoration to the links to the associated Uncalibrated measurements.
ActsTrk::GeoContextReadKey_t m_geoCtxKey
Geometry context key.
std::vector< SegmentSeedPair_t > processPattern(const EventContext &ctx, const ActsTrk::GeometryContext &gctx, const GlobalPattern &pattern) const
Main methods steering the segment fitting.
std::unique_ptr< MdtSegmentSeeder > m_mdtSeeder
Pointer to the L-R segment seeder.
SegmentSeedOpt_t fitSegment(const EventContext &ctx, const Amg::Transform3D &localToGlobal, Bucket_t parentBucket, HitVec_t &&hits) const
Fit a segment in a station given the hits & their parent bucket.
DecorKey_t m_localSegParKey
Decoration of the local segment parameters.
DoubleProperty m_goodSegmentCut
Reduced chi2 defining a good segment, stopping the fit of other segments in the same station.
ToolHandle< IxAODSegmentCnvTool > m_segmentCnvTool
Segment converter tool.
RegressionRes_t linearRegression(const CoordPlane Plane, const HitVec_t &hits, const std::optional< Beamspot > &beamspot=std::nullopt) const
Estimate the segment parameters in the plane defined by the CoordPlane template parameter using a wei...
UnsignedIntegerProperty m_goodSegmentDoF
Number of degrees of freedom defining a good segment, stopping the fit of other segments in the same ...
SeedingState< HitVec_t, CalibCont_t, SeederStateBase > State_t
Define the state holder object.
Placeholder for what will later be the muon segment EDM representation.
unsigned int nDoF() const
Returns the number of degrees of freedom.
const MeasVec & measurements() const
Returns the associated measurements.
double chi2() const
Returns the chi2 of the segment fit.
const MuonGMR4::SpectrometerSector * msSector() const
returns th associated muonChamber
Auxiliary class to instantiate WriteDecorHandles.The handles can be created in an empty state.
std::uint8_t nTrigEtaLayers() const
Returns the number of trigger eta hits.
void setNHits(const std::uint8_t nPrecisionHits, const std::uint8_t nPhiLayers, const std::uint8_t nTrigEtaLayers)
Assign the segment hit summary.
std::uint8_t nPrecisionHits() const
Returns the number of precision hits.
std::uint8_t nPhiLayers() const
Returns the number of trigger phi hits.
Acts::CalibrationContext getCalibrationContext(const EventContext &ctx)
The Acts::Calibration context is piped through the Acts fitters to (re)calibrate the Acts::SourceLink...
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
std::pair< Amg::Vector3D, Amg::Vector3D > makeLine(const Parameters &pars)
Returns the parsed parameters into an Eigen line parametrization.
std::string toString(const Parameters &pars)
Dumps the parameters into a string with labels in front of each number.
This header ties the generic definitions in this package.
ISpacePointCalibrator::CalibSpacePointVec CalibSpacePointVec
std::string printSegment(const xAOD::MuonSegment &seg)
Print the details of a segment.
double houghTanBeta(const Amg::Vector3D &v)
Returns the hough tanBeta [y] / [z].
std::ostream & operator<<(std::ostream &ostr, const MuonR4::MsTrackSeed &seed)
DataVector< GlobalPattern > GlobalPatternContainer
Abrivation of the GlobalPattern container type.
bool isPrecisionHit(const SpacePoint &hit)
Returns whether the uncalibrated spacepoint is a precision hit (Mdt, micromegas, stgc strips).
std::string print(const cont_t &container)
Print a space point container to string.
bool isGoodHit(const CalibratedSpacePoint &hit)
Returns whether the calibrated spacepoint is valid and therefore suitable to be used in the segment f...
double houghTanAlpha(const Amg::Vector3D &v)
: Returns the hough tanAlpha [x] / [z]
StIndex toStationIndex(ChIndex index)
convert ChIndex into StIndex
bool isSmall(const ChIndex index)
Returns true if the chamber index is in a small sector.
bool isBarrel(const ChIndex index)
Returns true if the chamber index points to a barrel chamber.
LayerIndex
enum to classify the different layers in the muon spectrometer
const std::string & stName(StIndex index)
convert StIndex into a string
LayerIndex toLayerIndex(ChIndex index)
convert ChIndex into LayerIndex
l
Printing final latex table to .tex output file.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)
bool isNSW(const UncalibMeasType aodType)
Returns whether the measurement is a NSW measurement.
MuonSegment_v1 MuonSegment
Reference the current persistent version:
Define simplified beamspot measurement in a selected plane.
double coord
Coordinate of the beamspot in the selected plane, either y or x depending on the plane.
double cov_coordCoord
Variance of the beamspot coordinate in the selected plane.
double z
z-coordinate of the beamspot
const ISpacePointCalibrator * calibrator
Pointer to the calibrator.
bool doBeamSpot
Switch to insert a beamspot constraint if possible.
const Muon::IMuonIdHelperSvc * idHelperSvc
Pointer to the idHelperSvc.
unsigned nPrecHitCut
Minimum number of precision hits.
double outlierRemovalCut
Cut on the segment chi2 / nDoF to launch the outlier removal.
const MuonValR4::IPatternVisualizationTool * visionTool
Pointer to the visualization tool.
double recoveryPull
Maximum pull on a measurement to add it back on the line.
Full configuration object.