ATLAS Offline Software
Loading...
Searching...
No Matches
MuonR4::SegmentFit::SegmentLineFitter Class Reference

The SegmentLineFitter is a standalone module to fit a straight line to calibrated muon space points. More...

#include <SegmentLineFitter.h>

Inheritance diagram for MuonR4::SegmentFit::SegmentLineFitter:
Collaboration diagram for MuonR4::SegmentFit::SegmentLineFitter:

Classes

struct  Config
 Full configuration object. More...
struct  ConfigSwitches
 Configuration object of the ATLAS implementation. More...

Public Types

using Fitter_t = Acts::Experimental::CompositeSpacePointLineFitter
 Abrivation of the actual line fitter.
using LinePar_t = Fitter_t::ParamVec_t
 Abrivation of the fitted line parameters.
using Hit_t = std::unique_ptr<CalibratedSpacePoint>
 Abrivation of the space point type to use.
using HitVec_t = std::vector<Hit_t>
 Collection of space points.
using FitPars_t = Fitter_t::FitParameters
 Abrivation of the fit parameters.
using Result_t = Fitter_t::FitResult<HitVec_t>
 Abrivation of the fit result.
using FitOpts_t = Fitter_t::FitOptions<HitVec_t, ISpacePointCalibrator>
 Abrivation of the fit options.
using Selector_t = Fitter_t::Selector_t<CalibratedSpacePoint>
 Abrivation of the hit selector to choose valid hits.
using HitState = CalibratedSpacePoint::State
 Abrivation of the fit state flag.

Public Member Functions

 SegmentLineFitter (const std::string &name, Config &&config)
 Standard constructor.
std::unique_ptr< SegmentfitSegment (const EventContext &ctx, const SegmentSeed *parent, const LinePar_t &startPars, const Amg::Transform3D &localToGlobal, HitVec_t &&calibHits) const
 Fit a set of measurements to a straight segment line.
bool msgLvl (const MSG::Level lvl) const
 Test the output level.
MsgStream & msg () const
 The standard message stream.
MsgStream & msg (const MSG::Level lvl) const
 The standard message stream.
void setLevel (MSG::Level lvl)
 Change the current logging level.

Private Member Functions

Result_t callLineFit (const Acts::CalibrationContext &cctx, const Parameters &startPars, const Amg::Transform3D &localToGlobal, HitVec_t &&calibHits) const
 Calls the underlying line fitter to determine the segment parameters.
bool removeOutliers (const Acts::CalibrationContext &cctx, const SegmentSeed &seed, const Amg::Transform3D &localToGlobal, const LinePar_t &startPars, Result_t &fitResult) const
 Cleans the fitted segment from the most outlier hit and then attempts to refit the segment.
bool plugHoles (const Acts::CalibrationContext &cctx, const SegmentSeed &seed, const Amg::Transform3D &localToGlobal, Result_t &toRecover) const
 Recovery of missed hits.
void eraseWrongHits (Result_t &candidate) const
 Removes all hits from the segment which are obvious outliers.
void cleanStripLayers (const Amg::Vector3D &linePos, const Amg::Vector3D &lineDir, HitVec_t &hits) const
 Marks duplicate hits on a strip layer as outliers to avoid competing contributions from the same layers in the fit.
std::unique_ptr< SegmentconvertToSegment (const Amg::Transform3D &locToGlobTrf, const SegmentSeed *parentSeed, Result_t &&toConvert) const
 Converts the fit result into a segment object.
void initMessaging () const
 Initialize our message level and MessageSvc.

Private Attributes

Fitter_t m_fitter
 Actual implementation of the straight line fit.
ConfigSwitches m_cfg {}
 Configuration switches of the ATLAS fitter implementation.
Selector_t m_goodHitSel {}
 Selector to identify the valid hits.
std::string m_nm
 Message source name.
boost::thread_specific_ptr< MsgStream > m_msg_tls
 MsgStream instance (a std::cout like with print-out levels)
std::atomic< IMessageSvc * > m_imsg { nullptr }
 MessageSvc pointer.
std::atomic< MSG::Level > m_lvl { MSG::NIL }
 Current logging level.
std::atomic_flag m_initialized ATLAS_THREAD_SAFE = ATOMIC_FLAG_INIT
 Messaging initialized (initMessaging)

Detailed Description

The SegmentLineFitter is a standalone module to fit a straight line to calibrated muon space points.

The CompositeSpacePointLineFitter from the ACTS toolkit is used to perform the actual fit to the measurements. The SegmentLineFitter is a wrapper class taking care of relaunching fits of poor quality but with cleaned measurements and also to put back meaurements on the line that have been missed by the initial line fit.

Definition at line 28 of file SegmentLineFitter.h.

Member Typedef Documentation

◆ FitOpts_t

Abrivation of the fit options.

Definition at line 43 of file SegmentLineFitter.h.

◆ FitPars_t

using MuonR4::SegmentFit::SegmentLineFitter::FitPars_t = Fitter_t::FitParameters

Abrivation of the fit parameters.

Definition at line 39 of file SegmentLineFitter.h.

◆ Fitter_t

using MuonR4::SegmentFit::SegmentLineFitter::Fitter_t = Acts::Experimental::CompositeSpacePointLineFitter

Abrivation of the actual line fitter.

Definition at line 31 of file SegmentLineFitter.h.

◆ Hit_t

Abrivation of the space point type to use.

Definition at line 35 of file SegmentLineFitter.h.

◆ HitState

Abrivation of the fit state flag.

Definition at line 47 of file SegmentLineFitter.h.

◆ HitVec_t

Collection of space points.

Definition at line 37 of file SegmentLineFitter.h.

◆ LinePar_t

Abrivation of the fitted line parameters.

Definition at line 33 of file SegmentLineFitter.h.

◆ Result_t

Abrivation of the fit result.

Definition at line 41 of file SegmentLineFitter.h.

◆ Selector_t

Abrivation of the hit selector to choose valid hits.

Definition at line 45 of file SegmentLineFitter.h.

Constructor & Destructor Documentation

◆ SegmentLineFitter()

MuonR4::SegmentFit::SegmentLineFitter::SegmentLineFitter ( const std::string & name,
Config && config )

Standard constructor.

Parameters
nameName to be printed in the messaging
configFit configuration parameters

Definition at line 90 of file SegmentLineFitter.cxx.

90 :
93 m_cfg{config} {
94 m_goodHitSel.connect<isGoodHit>();
95 }
std::unique_ptr< const Acts::Logger > makeActsAthenaLogger(IMessageSvc *svc, const std::string &name, int level, std::optional< std::string > parent_name)
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
Selector_t m_goodHitSel
Selector to identify the valid hits.
ConfigSwitches m_cfg
Configuration switches of the ATLAS fitter implementation.
Fitter_t m_fitter
Actual implementation of the straight line fit.
bool isGoodHit(const CalibratedSpacePoint &hit)
Returns whether the calibrated spacepoint is valid and therefore suitable to be used in the segment f...

Member Function Documentation

◆ callLineFit()

Result_t MuonR4::SegmentFit::SegmentLineFitter::callLineFit ( const Acts::CalibrationContext & cctx,
const Parameters & startPars,
const Amg::Transform3D & localToGlobal,
HitVec_t && calibHits ) const
private

Calls the underlying line fitter to determine the segment parameters.

Parameters
cctxCalibration context to fetch later the measurement's calib constants from StoreGate (It's a packed EventContext*)
startParsInitial line parameters guess
localToGlobalTransform to align the segment's station inside ATLAS (Mainly neede if the time is fit)
calibHitsList of hits that will be fitted

Check whether a beamspot constraint should be appended

placeholder for a very generous beam spot: 300mm in X,Y (tracking volume), 20000 along Z

Recall that the time is not the same in Acts & Athena

Fit the measurements

Convert back to athena time units

Definition at line 96 of file SegmentLineFitter.cxx.

99 {
101 if (m_cfg.doBeamSpot && countPhiHits(calibHits) > 0) {
102 const Amg::Transform3D globToLoc{localToGlobal.inverse()};
103 Amg::Vector3D beamSpot{globToLoc.translation()};
104 Amg::Vector3D beamLine{globToLoc.linear().col(2)};
105 SpacePoint::Cov_t covariance{};
106 covariance[toUnderlying(AxisDefs::etaCov)] = square(m_cfg.beamSpotRadius);
107 covariance[toUnderlying(AxisDefs::phiCov)] = square(m_cfg.beamSpotLength);
109 auto beamSpotSP = std::make_unique<CalibratedSpacePoint>(nullptr, std::move(beamSpot));
110 beamSpotSP->setBeamDirection(std::move(beamLine));
111 beamSpotSP->setCovariance(std::move(covariance));
112 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__<<": Beam spot constraint "
113 <<Amg::toString(beamSpotSP->localPosition())<<", "<<beamSpotSP->covariance());
114 calibHits.push_back(std::move(beamSpotSP));
115 }
116
117 if (msgLvl(MSG::VERBOSE)) {
118 const auto [pos, dir] = makeLine(startPars);
119 std::stringstream hitStream{};
120 for (const Hit_t& hit : calibHits) {
121 hitStream<<" **** "<< (*hit)<<", pull: "
122 <<std::sqrt(SeedingAux::chi2Term(pos, dir, *hit)) <<std::endl;
123 }
124 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__ <<": Start segment fit with parameters "
125 <<toString(startPars) <<", plane location: "<<Amg::toString(localToGlobal)<<std::endl
126 <<hitStream.str());
127 }
128 FitOpts_t fitOpts{};
130 fitOpts.calibContext = cctx;
131 fitOpts.calibrator = m_cfg.calibrator;
132 fitOpts.selector = m_goodHitSel;
133 //check the degrees of freedom before try the fit
134 const auto dOF = m_fitter.countDoF(calibHits, fitOpts.selector);
135 if((dOF.bending + dOF.nonBending) < m_fitter.config().parsToUse.size()){
136 return result;
137 }
138 fitOpts.measurements = std::move(calibHits);
139 fitOpts.localToGlobal = localToGlobal;
140 fitOpts.startParameters = startPars;
142 constexpr auto t0idx = toUnderlying(ParamDefs::t0);
143 fitOpts.startParameters[t0idx] = ActsTrk::timeToActs(fitOpts.startParameters[t0idx]);
145 result = m_fitter.fit(std::move(fitOpts));
147 if (m_fitter.config().fitT0){
148 result.parameters[t0idx] = ActsTrk::timeToAthena(result.parameters[t0idx]);
149 result.covariance(t0idx, t0idx) = Acts::square(ActsTrk::timeToAthena(1.)) * result.covariance(t0idx, t0idx);
150 for (ParamDefs p : {ParamDefs::x0, ParamDefs::y0, ParamDefs::phi, ParamDefs::theta}) {
151 auto pidx = toUnderlying(p);
152 result.covariance(t0idx, pidx) = ActsTrk::timeToAthena(result.covariance(t0idx, pidx));
153 result.covariance(pidx, t0idx) = ActsTrk::timeToAthena(result.covariance(pidx, t0idx));
154 }
155 }
156 return result;
157 }
#define ATH_MSG_VERBOSE(x)
bool hit(const std::valarray< int > &ids, int pdgId)
bool msgLvl(const MSG::Level lvl) const
Test the output level.
std::unique_ptr< CalibratedSpacePoint > Hit_t
Abrivation of the space point type to use.
Fitter_t::FitResult< HitVec_t > Result_t
Abrivation of the fit result.
Fitter_t::FitOptions< HitVec_t, ISpacePointCalibrator > FitOpts_t
Abrivation of the fit options.
std::array< double, 3 > Cov_t
Abrivation of the covariance type.
constexpr double timeToAthena(const double actsT)
Converts a time unit from Acts to Athena units.
constexpr double timeToActs(const double athenaT)
Converts a time unit from Athena to Acts units.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
SeedingAux::FitParIndex ParamDefs
Use the same parameter indices as used by the CompSpacePointAuxiliaries.
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.
AthConfigFlags beamSpot(AthConfigFlags flags, str instanceName, str recoMode)

◆ cleanStripLayers()

void MuonR4::SegmentFit::SegmentLineFitter::cleanStripLayers ( const Amg::Vector3D & linePos,
const Amg::Vector3D & lineDir,
HitVec_t & hits ) const
inlineprivate

Marks duplicate hits on a strip layer as outliers to avoid competing contributions from the same layers in the fit.

Hits on the same layer are sorted by their chi2 and the worse ones are rejected if they don't provide additional information

Parameters
linePosPosition of the latest segment line
lineDirDirection of the latest segment line
hitsList of hit measurements to clean

We need to sort out strip hits on the same layer

Loop over the hits to mark the less compatible hits on the layer as outlier

Both hits measure eta. They've been sorted by lower chi2 -> reject b

Definition at line 310 of file SegmentLineFitter.cxx.

312 {
313 const SpacePointPerLayerSorter sorter{};
315 std::ranges::sort(hits, [&sorter, &linePos, &lineDir](const Hit_t&a ,const Hit_t& b){
316 if (a->isStraw() || b->isStraw()) {
317 return !a->isStraw();
318 }
319 if (a->type() == xAOD::UncalibMeasType::Other ||
320 b->type() == xAOD::UncalibMeasType::Other) {
321 return a->type() != xAOD::UncalibMeasType::Other;
322 }
323 const unsigned lay_a = sorter.sectorLayerNum(*a->spacePoint());
324 const unsigned lay_b = sorter.sectorLayerNum(*b->spacePoint());
325 if (lay_a != lay_b) {
326 return lay_a < lay_b;
327 }
328 return SeedingAux::chi2Term(linePos, lineDir, *a) <
329 SeedingAux::chi2Term(linePos, lineDir, *b);
330 });
332 for (HitVec_t::iterator itr = hits.begin(); itr != hits.end(); ++itr) {
333 const Hit_t& hit_a{*itr};
334 if (hit_a->isStraw()){
335 break;
336 }
337 if(hit_a->fitState() == HitState::Duplicate ||
338 hit_a->type() == xAOD::UncalibMeasType::Other) {
339 continue;
340 }
341 const unsigned lay_a = sorter.sectorLayerNum(*hit_a->spacePoint());
343 for (HitVec_t::iterator itr2 = itr + 1; itr2 != hits.end(); ++itr2) {
344 const Hit_t& hit_b{*itr2};
345 if (hit_b->type() == xAOD::UncalibMeasType::Other) {
346 continue;
347 }
348 if (lay_a != sorter.sectorLayerNum(*hit_b->spacePoint())) {
349 break;
350 }
352 if ( (hit_a->measuresEta() && hit_b->measuresEta()) ||
353 (hit_a->measuresPhi() && hit_b->measuresPhi())) {
354 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__ <<": Reject "
355 <<m_cfg.idHelperSvc->toString(hit_b->spacePoint()->identify()) <<" in favour of "
356 <<m_cfg.idHelperSvc->toString(hit_a->spacePoint()->identify()));
357 hit_b->setFitState(HitState::Duplicate);
358 }
359 }
360 }
361 }
static Double_t a

◆ convertToSegment()

std::unique_ptr< Segment > MuonR4::SegmentFit::SegmentLineFitter::convertToSegment ( const Amg::Transform3D & locToGlobTrf,
const SegmentSeed * parentSeed,
Result_t && toConvert ) const
private

Converts the fit result into a segment object.

Parameters
locToGlobTrfLocal to global transform to translate the segment parameters into global parameters
parentSeedSegment seed from which the segment was built
toConvertFitted segment that needs conversion

Definition at line 193 of file SegmentLineFitter.cxx.

195 {
196 const auto [locPos, locDir] = makeLine(data.parameters);
197 Amg::Vector3D globPos = locToGlob * locPos;
198 Amg::Vector3D globDir = locToGlob.linear()* locDir;
199
200 std::ranges::sort(data.measurements, [](const Hit_t& a, const Hit_t& b){
201 return a->localPosition().z() < b->localPosition().z();
202 });
203 if (msgLvl(MSG::VERBOSE)) {
204 std::stringstream sstr{};
205 for (const Hit_t& h : data.measurements) {
206 sstr<<" **** "<<(*h)<<", pull: "
207 <<std::sqrt(SeedingAux::chi2Term(locPos, locDir, *h))<<std::endl;
208 }
209 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__ <<": Create new segment "
210 <<toString(data.parameters)<<" in "<<patternSeed->msSector()->identString()<<"built from:\n"<<sstr.str());
211 }
212
213 auto finalSeg = std::make_unique<Segment>(std::move(globPos), std::move(globDir),
214 patternSeed, std::move(data.measurements),
215 data.chi2, data.nDoF);
216 finalSeg->setCallsToConverge(data.nIter);
217 finalSeg->setParUncertainties(std::move(data.covariance));
218 if (m_fitter.config().fitT0) {
219 finalSeg->setSegmentT0(data.parameters[toUnderlying(ParamDefs::t0)]);
220 }
221 return finalSeg;
222 }
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11

◆ eraseWrongHits()

void MuonR4::SegmentFit::SegmentLineFitter::eraseWrongHits ( Result_t & candidate) const
private

Removes all hits from the segment which are obvious outliers.

E.g. tubes which cannot be crossed by the segment.

Parameters
candidateReference of the segment candidate to prune.

The segment has never crossed the tube

Definition at line 288 of file SegmentLineFitter.cxx.

288 {
289 auto [segPos, segDir] = makeLine(candidate.parameters);
290 cleanStripLayers(segPos, segDir, candidate.measurements);
291 candidate.measurements.erase(std::remove_if(candidate.measurements.begin(),
292 candidate.measurements.end(),
293 [&](const HitVec_t::value_type& hit){
294 if (hit->fitState() == HitState::Valid) {
295 return false;
296 } else if (hit->fitState() == HitState::Duplicate) {
297 return true;
298 }
301 const double dist = Amg::lineDistance(segPos, segDir,
302 hit->localPosition(),
303 hit->sensorDirection());
304 const auto* dc = static_cast<const xAOD::MdtDriftCircle*>(hit->spacePoint()->primaryMeasurement());
305 return dist >= dc->readoutElement()->innerTubeRadius();
306 }
307 return false;
308 }), candidate.measurements.end());
309 }
void cleanStripLayers(const Amg::Vector3D &linePos, const Amg::Vector3D &lineDir, HitVec_t &hits) const
Marks duplicate hits on a strip layer as outliers to avoid competing contributions from the same laye...
DataModel_detail::iterator< DVL > remove_if(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, Predicate pred)
Specialization of remove_if for DataVector/List.

◆ fitSegment()

std::unique_ptr< Segment > MuonR4::SegmentFit::SegmentLineFitter::fitSegment ( const EventContext & ctx,
const SegmentSeed * parent,
const LinePar_t & startPars,
const Amg::Transform3D & localToGlobal,
HitVec_t && calibHits ) const

Fit a set of measurements to a straight segment line.

Badish initial fits are cleaned and then holes are put filled back Returns a nullptr if the fit failed

Parameters
ctxEventContext to access the calibration constants
parentPointer to the seed from which the hits to fit are taken. The seed gives also access to the parent bucket to recover lost hits
startParsList of parameters serving as an initial guess
localToGlobalTransform to align the segment's station inside ATLAS (Mainly neede if the time is fit)
calibHitsList of hits that will be fitted

Definition at line 159 of file SegmentLineFitter.cxx.

163 {
164
165 const Acts::CalibrationContext cctx = ActsTrk::getCalibrationContext(ctx);
166 if (m_cfg.visionTool) {
167 Result_t preFit{};
168 preFit.parameters = startPars;
169 preFit.measurements = copy(calibHits);
170 auto seedCopy = convertToSegment(localToGlobal, parent, std::move(preFit));
171 m_cfg.visionTool->visualizeSegment(ctx, *seedCopy, "Prefit");
172 }
173 Result_t segFit = callLineFit(cctx, startPars, localToGlobal, std::move(calibHits));
174 if (m_cfg.visionTool && segFit.converged) {
175 auto seedCopy = convertToSegment(localToGlobal, parent, copy(segFit));
176 m_cfg.visionTool->visualizeSegment(ctx, *seedCopy, "Intermediate fit");
177 }
178 if (!removeOutliers(cctx, *parent, localToGlobal,
179 segFit.converged? segFit.parameters : startPars,
180 segFit)) {
181 return nullptr;
182 }
183 if (!plugHoles(cctx, *parent, localToGlobal, segFit)) {
184 return nullptr;
185 }
186 auto finalSeg = convertToSegment(localToGlobal, parent, std::move(segFit));
187 if (m_cfg.visionTool) {
188 m_cfg.visionTool->visualizeSegment(ctx, *finalSeg, "Final fit");
189 }
190 return finalSeg;
191 }
bool plugHoles(const Acts::CalibrationContext &cctx, const SegmentSeed &seed, const Amg::Transform3D &localToGlobal, Result_t &toRecover) const
Recovery of missed hits.
Result_t callLineFit(const Acts::CalibrationContext &cctx, const Parameters &startPars, const Amg::Transform3D &localToGlobal, HitVec_t &&calibHits) const
Calls the underlying line fitter to determine the segment parameters.
std::unique_ptr< Segment > convertToSegment(const Amg::Transform3D &locToGlobTrf, const SegmentSeed *parentSeed, Result_t &&toConvert) const
Converts the fit result into a segment object.
bool removeOutliers(const Acts::CalibrationContext &cctx, const SegmentSeed &seed, const Amg::Transform3D &localToGlobal, const LinePar_t &startPars, Result_t &fitResult) const
Cleans the fitted segment from the most outlier hit and then attempts to refit the segment.
Acts::CalibrationContext getCalibrationContext(const EventContext &ctx)
The Acts::Calibration context is piped through the Acts fitters to (re)calibrate the Acts::SourceLink...
bool copy
Definition calibdata.py:26

◆ initMessaging()

void AthMessaging::initMessaging ( ) const
privateinherited

Initialize our message level and MessageSvc.

This method should only be called once.

Definition at line 39 of file AthMessaging.cxx.

40{
42 // If user did not set an explicit level, set a default
43 if (m_lvl == MSG::NIL) {
44 m_lvl = m_imsg ?
45 static_cast<MSG::Level>( m_imsg.load()->outputLevel(m_nm) ) :
46 MSG::INFO;
47 }
48}
std::string m_nm
Message source name.
std::atomic< IMessageSvc * > m_imsg
MessageSvc pointer.
std::atomic< MSG::Level > m_lvl
Current logging level.
IMessageSvc * getMessageSvc(bool quiet=false)

◆ msg() [1/2]

MsgStream & AthMessaging::msg ( ) const
inlineinherited

The standard message stream.

Returns a reference to the default message stream May not be invoked before sysInitialize() has been invoked.

Definition at line 167 of file AthMessaging.h.

168{
169 MsgStream* ms = m_msg_tls.get();
170 if (!ms) {
171 if (!m_initialized.test_and_set()) initMessaging();
172 ms = new MsgStream(m_imsg,m_nm);
173 m_msg_tls.reset( ms );
174 }
175
176 ms->setLevel (m_lvl);
177 return *ms;
178}
boost::thread_specific_ptr< MsgStream > m_msg_tls
MsgStream instance (a std::cout like with print-out levels)
void initMessaging() const
Initialize our message level and MessageSvc.

◆ msg() [2/2]

MsgStream & AthMessaging::msg ( const MSG::Level lvl) const
inlineinherited

The standard message stream.

Returns a reference to the default message stream May not be invoked before sysInitialize() has been invoked.

Definition at line 182 of file AthMessaging.h.

183{ return msg() << lvl; }
MsgStream & msg() const
The standard message stream.

◆ msgLvl()

bool AthMessaging::msgLvl ( const MSG::Level lvl) const
inlineinherited

Test the output level.

Parameters
lvlThe message level to test against
Returns
boolean Indicating if messages at given level will be printed
Return values
trueMessages at level "lvl" will be printed

Definition at line 151 of file AthMessaging.h.

152{
153 // If user did not set explicit message level we have to initialize
154 // the messaging and retrieve the default via the MessageSvc.
155 if (m_lvl==MSG::NIL && !m_initialized.test_and_set()) initMessaging();
156
157 if (m_lvl <= lvl) {
158 msg() << lvl;
159 return true;
160 } else {
161 return false;
162 }
163}

◆ plugHoles()

bool MuonR4::SegmentFit::SegmentLineFitter::plugHoles ( const Acts::CalibrationContext & cctx,
const SegmentSeed & seed,
const Amg::Transform3D & localToGlobal,
Result_t & toRecover ) const
private

Recovery of missed hits.

Hits in the space point bucket that are maximally <RecoveryPull> away from the fitted segment are put onto the segment candidate and the candidate is refitted. If the refitted candidate has a chi2/nDoF < <OutlierRemoval> the canidate is automatically choosen otherwise, its chi needs to be better.

Parameters
cctxCalibration context to fetch later the measurement's calib constants from StoreGate (It's a packed EventContext*)
seedParent seed from which the segment fit is actually triggered The seed is mainly used for visualization purposes
localToGlobalTransform to align the spectrometer sector within ATLAS mainly used for the t0 fit
fitResultPreviously achieved fit result to be checked. The measurements on the result and the paramters are updated accordingly

We've the first estimator of the segment fit

Setup a map to replace space points if they better suite

Loop over all hits in the parent bucket

Hit already used in the segment fit

If the hit is a phi measurement check at least if it can be hit by the segment

Use the pull of the uncalibrated measurement to estimate whether a calibration is actually worth

No extra hit has been found

Remove the beamspot constraint measurement

Nothing has been recovered. Just bail out

If the chi2 is less than 5, no outlier rejection is launched. So also accept any recovered segment below that threshold

Next check whether the recovery made measurements marked as outlier feasable the hole recovery

Definition at line 362 of file SegmentLineFitter.cxx.

365 {
367 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__ <<": segment "<<toString(toRecover.parameters)
368 <<", chi2: "<<toRecover.chi2 /std::max(toRecover.nDoF, 1ul)
369 <<", nDoF: "<<toRecover.nDoF);
371
372
373 std::unordered_set<const SpacePoint*> usedSpacePoints{};
374 for (auto& hit : toRecover.measurements) {
375 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__ <<": "<<(*hit)<<" is known");
376 usedSpacePoints.insert(hit->spacePoint());
377 }
379 const EventContext& ctx{*cctx.get<const EventContext*>()};
380
381 const double timeOff = toRecover.parameters[toUnderlying(ParamDefs::t0)];
382 HitVec_t candidateHits{};
383 bool hasCandidate{false};
384 const auto [locPos, locDir] = makeLine(toRecover.parameters);
385
387 for (const auto& hit : *seed.parentBucket()){
389 if (usedSpacePoints.count(hit.get())){
390 continue;
391 }
392 Hit_t calibHit{};
393 double pull{-1.};
394 if (hit->isStraw()) {
395 using namespace Acts::detail::LineHelper;
396 const double dist = signedDistance(locPos, locDir, hit->localPosition(), hit->sensorDirection());
397 const auto* dc = static_cast<const xAOD::MdtDriftCircle*>(hit->primaryMeasurement());
398 // Check whether the tube is crossed by the hit
399 if (Acts::abs(dist) >= dc->readoutElement()->innerTubeRadius()) {
400 continue;
401 }
402 } else {
404 if (!hit->measuresEta() &&
405 std::abs(hit->sensorDirection().dot(hit->localPosition() -
406 SeedingAux::extrapolateToPlane(locPos,locDir, *hit))) >
407 std::sqrt(hit->covariance()[toUnderlying(AxisDefs::etaCov)])){
408 continue;
409 }
412 pull = std::sqrt(SeedingAux::chi2Term(locPos, locDir, *hit));
413 if (pull > 1.1 * m_cfg.recoveryPull) {
414 continue;
415 }
416 }
417 calibHit = m_cfg.calibrator->calibrate(ctx, hit.get(), locPos, locDir, ActsTrk::timeToActs(timeOff));
418 pull = std::sqrt(SeedingAux::chi2Term(locPos, locDir, *calibHit));
419 if (pull <= m_cfg.recoveryPull) {
420 hasCandidate |= calibHit->fitState() == HitState::Valid;
421 } else {
422 calibHit->setFitState(HitState::Outlier);
423 }
424 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__<<": Candidate hit for recovery "
425 <<seed.msSector()->idHelperSvc()->toString(hit->identify())<<", pull: "<<pull);
426 candidateHits.push_back(std::move(calibHit));
427 }
429 if (!hasCandidate) {
430 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__<<": No space point candidates for recovery were found");
431 toRecover.measurements.insert(toRecover.measurements.end(),
432 std::make_move_iterator(candidateHits.begin()),
433 std::make_move_iterator(candidateHits.end()));
434 eraseWrongHits(toRecover);
435 return toRecover.nDoF > 0;
436 }
437
438
439 HitVec_t copied = copy(toRecover.measurements);
440 HitVec_t copiedCandidates = copy(candidateHits);
442 if (m_cfg.doBeamSpot) {
443 removeBeamSpot(copied);
444 }
445
446 candidateHits.insert(candidateHits.end(),
447 std::make_move_iterator(copied.begin()),
448 std::make_move_iterator(copied.end()));
449
450 cleanStripLayers(locPos, locDir, candidateHits);
451 Result_t recovered = callLineFit(cctx, toRecover.parameters, localToGlobal,
452 std::move(candidateHits));
453 if (!recovered.converged) {
454 return false;
455 }
457 if (recovered.nDoF <= toRecover.nDoF) {
458 for (HitVec_t::value_type& hit : copiedCandidates) {
459 hit->setFitState(HitState::Outlier);
460 toRecover.measurements.push_back(std::move(hit));
461 }
462 eraseWrongHits(toRecover);
463 return true;
464 }
465 std::vector<const CalibratedSpacePoint*> stripOutliers{};
466 stripOutliers.reserve(toRecover.measurements.size());
467 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__<<": Before - chi2: "<<toRecover.chi2
468 <<", nDoF "<<toRecover.nDoF<<" <=> after recovery - chi2: "
469 <<recovered.chi2<<", nDoF: "<<recovered.nDoF);
470
471 double redChi2 = recovered.chi2 / std::max(recovered.nDoF, 1ul);
474 if (redChi2 < m_cfg.outlierRemovalCut ||
475 toRecover.nDoF == 0 || redChi2 < toRecover.chi2 / toRecover.nDoF) {
476 ATH_MSG_VERBOSE("Accept segment with recovered "<<(recovered.nDoF - toRecover.nDoF)<<" hits.");
477 recovered.nIter += toRecover.nIter;
478 toRecover = std::move(recovered);
481 unsigned recovLoop{0u};
482 while (++recovLoop <= m_cfg.nRecoveryLoops) {
483 copied = copy(toRecover.measurements);
484 if (m_cfg.doBeamSpot) {
485 removeBeamSpot(copied);
486 }
487 const auto [beforePos, beforeDir] = makeLine(toRecover.parameters);
488
489 for (HitVec_t::value_type& copyHit : copied) {
490 if (copyHit->fitState() != HitState::Outlier) {
491 continue;
492 }
493 if (std::sqrt(SeedingAux::chi2Term(beforePos, beforeDir, *copyHit)) < m_cfg.recoveryPull) {
494 copyHit->setFitState(HitState::Valid);
495 stripOutliers.push_back(copyHit.get());
496 }
497 }
498 // Nothing to recover
499 if (stripOutliers.empty()) {
500 break;
501 }
502 cleanStripLayers(beforePos, beforeDir, copied);
503 // Recovery turned out to be duplicates on the same layer
504 if (std::ranges::none_of(stripOutliers,[](const CalibratedSpacePoint* sp){
505 return sp->fitState() == HitState::Valid;
506 })) {
507 break;
508 }
509 stripOutliers.clear();
510 recovered = callLineFit(cctx, toRecover.parameters, localToGlobal, std::move(copied));
511 if (!recovered.converged) {
512 break;
513 }
514 if (recovered.nDoF <= toRecover.nDoF) {
515 break;
516 }
517 redChi2 = recovered.chi2 / std::max(recovered.nDoF, 1ul);
518 if (redChi2 < m_cfg.outlierRemovalCut || redChi2 < toRecover.chi2 / toRecover.nDoF) {
519 recovered.nIter += toRecover.nIter;
520 toRecover = std::move(recovered);
521 } else {
522 break;
523 }
524 }
525 } else{
526 for (HitVec_t::value_type& hit : copiedCandidates) {
527 hit->setFitState(HitState::Outlier);
528 toRecover.measurements.push_back(std::move(hit));
529 }
530 }
531 eraseWrongHits(toRecover);
532 return true;
533 }
static Double_t sp
void eraseWrongHits(Result_t &candidate) const
Removes all hits from the segment which are obvious outliers.
std::vector< Hit_t > HitVec_t
Collection of space points.
double signedDistance(const Amg::Vector3D &posA, const Amg::Vector3D &dirA, const Amg::Vector3D &posB, const Amg::Vector3D &dirB)
Calculates the signed distance between two lines in 3D space.
@ u
Enums for curvilinear frames.
Definition ParamDefs.h:77
MdtDriftCircle_v1 MdtDriftCircle

◆ removeOutliers()

bool MuonR4::SegmentFit::SegmentLineFitter::removeOutliers ( const Acts::CalibrationContext & cctx,
const SegmentSeed & seed,
const Amg::Transform3D & localToGlobal,
const LinePar_t & startPars,
Result_t & fitResult ) const
private

Cleans the fitted segment from the most outlier hit and then attempts to refit the segment.

The outlier removal is not run if the segment has already a chi2 / nDoF better than <outlierRemovalCut>. Returns false if the recovery lead to the destruction of all nDoF

Parameters
cctxCalibration context to fetch later the measurement's calib constants from StoreGate (It's a packed EventContext*)
seedParent seed from which the segment fit is actually triggered The seed is mainly used for visualization purposes
localToGlobalTransform to align the spectrometer sector within ATLAS mainly used for the t0 fit
startParsThe initial parameters from which the fit shall be launched In case of out of bound parameters, the start parameters are returned otherwise the last obtained fit parameters
fitResultPreviously achieved fit result to be checked. The measurements on the result and the paramters are updated accordingly

Remove a priori the beamspot constaint as it never should pose any problem and another one will be added anyway in the next iteration

Next sort the measurements by ascending chi2

Refit the segment line without the measurement

Definition at line 224 of file SegmentLineFitter.cxx.

228 {
229
230
231 if (countPrecHits(fitResult.measurements) < m_cfg.nPrecHitCut || fitResult.nDoF == 0
232 || fitResult.nIter > m_fitter.config().maxIter) {
233 for(const auto& meas : fitResult.measurements){
234 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__<<": Measurement from fitresult is" << (*meas));
235 }
236 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__
237 <<": No degree of freedom available. What shall be removed?!. nDoF: "
238 <<fitResult.nDoF<<", n-meas: "<<countPrecHits(fitResult.measurements));
239 return false;
240 }
241 if (fitResult.converged && fitResult.chi2 / std::max(fitResult.nDoF, 1ul) < m_cfg.outlierRemovalCut) {
242 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__ <<": The segment "<<toString(fitResult.parameters)
243 <<" is already of good quality "<<fitResult.chi2 / std::max(fitResult.nDoF, 1ul)
244 <<". Don't remove outliers");
245 return true;
246 }
247 if (fitResult.nDoF == 0u){
248 return false;
249 }
250 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__ <<": Segment "
251 <<toString(fitResult.parameters)<<" is of badish quality. Remove worst hit");
252
255 if (m_cfg.doBeamSpot) {
256 removeBeamSpot(fitResult.measurements);
257 }
258 const auto [segPos, segDir] = makeLine(fitResult.parameters);
260 std::ranges::sort(fitResult.measurements,
261 [&segPos, &segDir](const HitVec_t::value_type& a, const HitVec_t::value_type& b){
262 const double chiSqA = isGoodHit(*a) ? SeedingAux::chi2Term(segPos, segDir, *a) : 0.;
263 const double chiSqB = isGoodHit(*b) ? SeedingAux::chi2Term(segPos, segDir, *b) : 0.;
264 return chiSqA < chiSqB;
265 });
266 fitResult.measurements.back()->setFitState(HitState::Outlier);
267
269 Result_t newAttempt = callLineFit(cctx, startPars, localToGlobal,
270 std::move(fitResult.measurements));
271 if (newAttempt.converged) {
272 newAttempt.nIter+=fitResult.nIter;
273 fitResult = std::move(newAttempt);
274 if (m_cfg.visionTool) {
275 const EventContext& ctx{*cctx.get<const EventContext*>()};
276 auto seedCopy = convertToSegment(localToGlobal, &seed, copy(fitResult));
277 m_cfg.visionTool->visualizeSegment(ctx, *seedCopy, "Bad fit recovery");
278 }
279 } else {
280 fitResult.nIter+=newAttempt.nIter;
281 fitResult.measurements = std::move(newAttempt.measurements);
282 }
283 return removeOutliers(cctx, seed, localToGlobal,
284 fitResult.converged ? fitResult.parameters : startPars,
285 fitResult);
286 }

◆ setLevel()

void AthMessaging::setLevel ( MSG::Level lvl)
inherited

Change the current logging level.

Use this rather than msg().setLevel() for proper operation with MT.

Definition at line 28 of file AthMessaging.cxx.

29{
30 m_lvl = lvl;
31}

Member Data Documentation

◆ ATLAS_THREAD_SAFE

std::atomic_flag m_initialized AthMessaging::ATLAS_THREAD_SAFE = ATOMIC_FLAG_INIT
mutableprivateinherited

Messaging initialized (initMessaging)

Definition at line 141 of file AthMessaging.h.

◆ m_cfg

ConfigSwitches MuonR4::SegmentFit::SegmentLineFitter::m_cfg {}
private

Configuration switches of the ATLAS fitter implementation.

Definition at line 108 of file SegmentLineFitter.h.

108{};

◆ m_fitter

Fitter_t MuonR4::SegmentFit::SegmentLineFitter::m_fitter
private

Actual implementation of the straight line fit.

Definition at line 106 of file SegmentLineFitter.h.

◆ m_goodHitSel

Selector_t MuonR4::SegmentFit::SegmentLineFitter::m_goodHitSel {}
private

Selector to identify the valid hits.

Definition at line 110 of file SegmentLineFitter.h.

110{};

◆ m_imsg

std::atomic<IMessageSvc*> AthMessaging::m_imsg { nullptr }
mutableprivateinherited

MessageSvc pointer.

Definition at line 135 of file AthMessaging.h.

135{ nullptr };

◆ m_lvl

std::atomic<MSG::Level> AthMessaging::m_lvl { MSG::NIL }
mutableprivateinherited

Current logging level.

Definition at line 138 of file AthMessaging.h.

138{ MSG::NIL };

◆ m_msg_tls

boost::thread_specific_ptr<MsgStream> AthMessaging::m_msg_tls
mutableprivateinherited

MsgStream instance (a std::cout like with print-out levels)

Definition at line 132 of file AthMessaging.h.

◆ m_nm

std::string AthMessaging::m_nm
privateinherited

Message source name.

Definition at line 129 of file AthMessaging.h.


The documentation for this class was generated from the following files: