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

void centerAlongWire (Result_t &fitResult) const
 Moves the segment to the average x0 position, if the segment does not contain any measurement.
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, 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 107 of file SegmentLineFitter.cxx.

107 :
110 m_cfg{config} {
111 m_goodHitSel.connect<isGoodHit>();
112 }
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.

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 113 of file SegmentLineFitter.cxx.

116 {
118 if (m_cfg.doBeamSpot && countPhiHits(calibHits) > 0) {
119 const Amg::Transform3D globToLoc{localToGlobal.inverse()};
120 Amg::Vector3D beamSpot{globToLoc.translation()};
121 Amg::Vector3D beamLine{globToLoc.linear().col(2)};
122 SpacePoint::Cov_t covariance{};
123 covariance[toUnderlying(AxisDefs::etaCov)] = square(m_cfg.beamSpotRadius);
124 covariance[toUnderlying(AxisDefs::phiCov)] = square(m_cfg.beamSpotLength);
126 auto beamSpotSP = std::make_unique<CalibratedSpacePoint>(nullptr, std::move(beamSpot));
127 beamSpotSP->setBeamDirection(std::move(beamLine));
128 beamSpotSP->setCovariance(std::move(covariance));
129 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__<<": Beam spot constraint "
130 <<Amg::toString(beamSpotSP->localPosition())<<", "<<beamSpotSP->covariance());
131 calibHits.push_back(std::move(beamSpotSP));
132 }
133
134 if (msgLvl(MSG::VERBOSE)) {
135 const auto [pos, dir] = makeLine(startPars);
136 std::stringstream hitStream{};
137 for (const Hit_t& hit : calibHits) {
138 hitStream<<" **** "<< (*hit)<<", pull: "
139 <<std::sqrt(SeedingAux::chi2Term(pos, dir, *hit)) <<std::endl;
140 }
141 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__ <<": Start segment fit with parameters "
142 <<toString(startPars) <<", plane location: "<<Amg::toString(localToGlobal)<<std::endl
143 <<hitStream.str());
144 }
145 FitOpts_t fitOpts{};
147 fitOpts.calibContext = cctx;
148 fitOpts.calibrator = m_cfg.calibrator;
149 fitOpts.selector = m_goodHitSel;
150 //check the degrees of freedom before try the fit
151 const auto dOF = m_fitter.countDoF(calibHits, fitOpts.selector);
152 if((dOF.bending + dOF.nonBending) < startPars.size()){
153 return result;
154 }
155 fitOpts.measurements = std::move(calibHits);
156 fitOpts.localToGlobal = localToGlobal;
157 fitOpts.startParameters = startPars;
159 fitOpts.startParameters[toUnderlying(ParamDefs::t0)] = ActsTrk::timeToActs(fitOpts.startParameters[toUnderlying(ParamDefs::t0)]);
161 result = m_fitter.fit(std::move(fitOpts));
163 result.parameters[toUnderlying(ParamDefs::t0)] = ActsTrk::timeToAthena(result.parameters[toUnderlying(ParamDefs::t0)]);
164 centerAlongWire(result);
165 return result;
166 }
#define ATH_MSG_VERBOSE(x)
bool msgLvl(const MSG::Level lvl) const
Test the output level.
void centerAlongWire(Result_t &fitResult) const
Moves the segment to the average x0 position, if the segment does not contain any measurement.
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
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)

◆ centerAlongWire()

void MuonR4::SegmentFit::SegmentLineFitter::centerAlongWire ( Result_t & fitResult) const
private

Moves the segment to the average x0 position, if the segment does not contain any measurement.

Definition at line 538 of file SegmentLineFitter.cxx.

538 {
539 if (std::ranges::any_of(result.measurements,[](const Hit_t& h){
540 return h->measuresPhi();
541 })) {
542 ATH_MSG_VERBOSE("The segment has phi measurements. No centering needed");
543 return;
544 }
545 double avgX{0.};
546 const double nHits = result.measurements.size();
547 std::ranges::for_each(result.measurements, [&avgX, nHits](const Hit_t& hit) {
548 return avgX += hit->localPosition().x() / nHits;
549 });
550 result.parameters[toUnderlying(ParamDefs::x0)] = avgX;
551 }
static const uint32_t nHits

◆ 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 314 of file SegmentLineFitter.cxx.

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

202 {
203 const auto [locPos, locDir] = makeLine(data.parameters);
204 Amg::Vector3D globPos = locToGlob * locPos;
205 Amg::Vector3D globDir = locToGlob.linear()* locDir;
206
207 std::ranges::sort(data.measurements, [](const Hit_t& a, const Hit_t& b){
208 return a->localPosition().z() < b->localPosition().z();
209 });
210 if (msgLvl(MSG::VERBOSE)) {
211 std::stringstream sstr{};
212 for (const Hit_t& h : data.measurements) {
213 sstr<<" **** "<<(*h)<<", pull: "
214 <<std::sqrt(SeedingAux::chi2Term(locPos, locDir, *h))<<std::endl;
215 }
216 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__ <<": Create new segment "
217 <<toString(data.parameters)<<" in "<<patternSeed->msSector()->identString()<<"built from:\n"<<sstr.str());
218 }
219
220 auto finalSeg = std::make_unique<Segment>(std::move(globPos), std::move(globDir),
221 patternSeed, std::move(data.measurements),
222 data.chi2, data.nDoF);
223 finalSeg->setCallsToConverge(data.nIter);
224 finalSeg->setParUncertainties(std::move(data.covariance));
225 if (m_fitter.config().fitT0) {
226 finalSeg->setSegmentT0(data.parameters[toUnderlying(ParamDefs::t0)]);
227 }
228 return finalSeg;
229 }
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 292 of file SegmentLineFitter.cxx.

292 {
293 auto [segPos, segDir] = makeLine(candidate.parameters);
294 cleanStripLayers(segPos, segDir, candidate.measurements);
295 candidate.measurements.erase(std::remove_if(candidate.measurements.begin(),
296 candidate.measurements.end(),
297 [&](const HitVec_t::value_type& hit){
298 if (hit->fitState() == HitState::Valid) {
299 return false;
300 } else if (hit->fitState() == HitState::Duplicate) {
301 return true;
302 }
305 const double dist = Amg::lineDistance(segPos, segDir,
306 hit->localPosition(),
307 hit->sensorDirection());
308 const auto* dc = static_cast<const xAOD::MdtDriftCircle*>(hit->spacePoint()->primaryMeasurement());
309 return dist >= dc->readoutElement()->innerTubeRadius();
310 }
311 return false;
312 }), candidate.measurements.end());
313 }
if(febId1==febId2)
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 168 of file SegmentLineFitter.cxx.

172 {
173
174 const Acts::CalibrationContext cctx = ActsTrk::getCalibrationContext(ctx);
175 if (m_cfg.visionTool) {
176 Result_t preFit{};
177 preFit.parameters = startPars;
178 preFit.measurements = copy(calibHits);
179 auto seedCopy = convertToSegment(localToGlobal, parent, std::move(preFit));
180 m_cfg.visionTool->visualizeSegment(ctx, *seedCopy, "Prefit");
181 }
182 Result_t segFit = callLineFit(cctx, startPars, localToGlobal, std::move(calibHits));
183 if (m_cfg.visionTool && segFit.converged) {
184 auto seedCopy = convertToSegment(localToGlobal, parent, copy(segFit));
185 m_cfg.visionTool->visualizeSegment(ctx, *seedCopy, "Intermediate fit");
186 }
187 if (!removeOutliers(cctx, *parent, localToGlobal, segFit)) {
188 return nullptr;
189 }
190 if (!plugHoles(cctx, *parent, localToGlobal, segFit)) {
191 return nullptr;
192 }
193 auto finalSeg = convertToSegment(localToGlobal, parent, std::move(segFit));
194 if (m_cfg.visionTool) {
195 m_cfg.visionTool->visualizeSegment(ctx, *finalSeg, "Final fit");
196 }
197 return finalSeg;
198 }
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.
bool removeOutliers(const Acts::CalibrationContext &cctx, const SegmentSeed &seed, const Amg::Transform3D &localToGlobal, Result_t &fitResult) const
Cleans the fitted segment from the most outlier hit and then attempts to refit the segment.
std::unique_ptr< Segment > convertToSegment(const Amg::Transform3D &locToGlobTrf, const SegmentSeed *parentSeed, Result_t &&toConvert) const
Converts the fit result into a segment object.
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 366 of file SegmentLineFitter.cxx.

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

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

◆ 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: