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

108 :
111 m_cfg{config} {
112 m_goodHitSel.connect<isGoodHit>();
113 }
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 114 of file SegmentLineFitter.cxx.

117 {
119 if (m_cfg.doBeamSpot && countPhiHits(calibHits) > 0) {
120 const Amg::Transform3D globToLoc{localToGlobal.inverse()};
121 Amg::Vector3D beamSpot{globToLoc.translation()};
122 Amg::Vector3D beamLine{globToLoc.linear().col(2)};
123 SpacePoint::Cov_t covariance{};
124 covariance[toUnderlying(AxisDefs::etaCov)] = square(m_cfg.beamSpotRadius);
125 covariance[toUnderlying(AxisDefs::phiCov)] = square(m_cfg.beamSpotLength);
127 auto beamSpotSP = std::make_unique<CalibratedSpacePoint>(nullptr, std::move(beamSpot));
128 beamSpotSP->setBeamDirection(std::move(beamLine));
129 beamSpotSP->setCovariance(std::move(covariance));
130 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__<<": Beam spot constraint "
131 <<Amg::toString(beamSpotSP->localPosition())<<", "<<beamSpotSP->covariance());
132 calibHits.push_back(std::move(beamSpotSP));
133 }
134
135 if (msgLvl(MSG::VERBOSE)) {
136 const auto [pos, dir] = makeLine(startPars);
137 std::stringstream hitStream{};
138 for (const Hit_t& hit : calibHits) {
139 hitStream<<" **** "<< (*hit)<<", pull: "
140 <<std::sqrt(SeedingAux::chi2Term(pos, dir, *hit)) <<std::endl;
141 }
142 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__ <<": Start segment fit with parameters "
143 <<toString(startPars) <<", plane location: "<<Amg::toString(localToGlobal)<<std::endl
144 <<hitStream.str());
145 }
146 FitOpts_t fitOpts{};
147 fitOpts.calibContext = cctx;
148 fitOpts.calibrator = m_cfg.calibrator;
149 fitOpts.selector = m_goodHitSel;
150 fitOpts.measurements = std::move(calibHits);
151 fitOpts.localToGlobal = localToGlobal;
152 fitOpts.startParameters = startPars;
154 fitOpts.startParameters[toUnderlying(ParamDefs::t0)] = ActsTrk::timeToActs(fitOpts.startParameters[toUnderlying(ParamDefs::t0)]);
156 Result_t result = m_fitter.fit(std::move(fitOpts));
158 result.parameters[toUnderlying(ParamDefs::t0)] = ActsTrk::timeToAthena(result.parameters[toUnderlying(ParamDefs::t0)]);
159 centerAlongWire(result);
160 return result;
161 }
#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 535 of file SegmentLineFitter.cxx.

535 {
536 if (std::ranges::any_of(result.measurements,[](const Hit_t& h){
537 return h->measuresPhi();
538 })) {
539 ATH_MSG_VERBOSE("The segment has phi measurements. No centering needed");
540 return;
541 }
542 double avgX{0.};
543 const double nHits = result.measurements.size();
544 std::ranges::for_each(result.measurements, [&avgX, nHits](const Hit_t& hit) {
545 return avgX += hit->localPosition().x() / nHits;
546 });
547 result.parameters[toUnderlying(ParamDefs::x0)] = avgX;
548 }
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 304 of file SegmentLineFitter.cxx.

306 {
307 const SpacePointPerLayerSorter sorter{};
309 std::ranges::sort(hits, [&sorter, &linePos, &lineDir](const Hit_t&a ,const Hit_t& b){
310 if (a->isStraw() || b->isStraw()) {
311 return !a->isStraw();
312 }
313 if (a->type() == xAOD::UncalibMeasType::Other ||
314 b->type() == xAOD::UncalibMeasType::Other) {
315 return a->type() != xAOD::UncalibMeasType::Other;
316 }
317 const unsigned lay_a = sorter.sectorLayerNum(*a->spacePoint());
318 const unsigned lay_b = sorter.sectorLayerNum(*b->spacePoint());
319 if (lay_a != lay_b) {
320 return lay_a < lay_b;
321 }
322 return SeedingAux::chi2Term(linePos, lineDir, *a) <
323 SeedingAux::chi2Term(linePos, lineDir, *b);
324 });
326 for (HitVec_t::iterator itr = hits.begin(); itr != hits.end(); ++itr) {
327 const Hit_t& hit_a{*itr};
328 if (hit_a->isStraw()){
329 break;
330 }
331 if(hit_a->fitState() == HitState::Duplicate ||
332 hit_a->type() == xAOD::UncalibMeasType::Other) {
333 continue;
334 }
335 const unsigned lay_a = sorter.sectorLayerNum(*hit_a->spacePoint());
337 for (HitVec_t::iterator itr2 = itr + 1; itr2 != hits.end(); ++itr2) {
338 const Hit_t& hit_b{*itr2};
339 if (hit_b->type() == xAOD::UncalibMeasType::Other) {
340 continue;
341 }
342 if (lay_a != sorter.sectorLayerNum(*hit_b->spacePoint())) {
343 break;
344 }
346 if ( (hit_a->measuresEta() && hit_b->measuresEta()) ||
347 (hit_a->measuresPhi() && hit_b->measuresPhi())) {
348 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__ <<": Reject "
349 <<m_cfg.idHelperSvc->toString(hit_b->spacePoint()->identify()) <<" in favour of "
350 <<m_cfg.idHelperSvc->toString(hit_a->spacePoint()->identify()));
351 hit_b->setFitState(HitState::Duplicate);
352 static std::atomic<unsigned> warnCounter{0};
353 if (hit_a->type() == xAOD::UncalibMeasType::sTgcStripType && (++warnCounter)< 1000) {
354 ATH_MSG_WARNING(__func__<<"() - "<<__LINE__
355 <<": Please check whether the overlap removal between "
356 <<m_cfg.idHelperSvc->toString(hit_a->spacePoint()->identify()) <<" & "
357 <<m_cfg.idHelperSvc->toString(hit_b->spacePoint()->identify())<<" is correct.");
358 }
359 }
360 }
361 }
362 }
#define ATH_MSG_WARNING(x)
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

TODO: Add the config retrieval to the composite space point line fitter

Definition at line 195 of file SegmentLineFitter.cxx.

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

282 {
283 auto [segPos, segDir] = makeLine(candidate.parameters);
284 cleanStripLayers(segPos, segDir, candidate.measurements);
285 candidate.measurements.erase(std::remove_if(candidate.measurements.begin(),
286 candidate.measurements.end(),
287 [&](const HitVec_t::value_type& hit){
288 if (hit->fitState() == HitState::Valid) {
289 return false;
290 } else if (hit->fitState() == HitState::Duplicate) {
291 return true;
292 }
295 const double dist = Amg::lineDistance(segPos, segDir,
296 hit->localPosition(),
297 hit->sensorDirection());
298 const auto* dc = static_cast<const xAOD::MdtDriftCircle*>(hit->spacePoint()->primaryMeasurement());
299 return dist >= dc->readoutElement()->innerTubeRadius();
300 }
301 return false;
302 }), candidate.measurements.end());
303 }
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 163 of file SegmentLineFitter.cxx.

167 {
168
169 const Acts::CalibrationContext cctx = ActsTrk::getCalibrationContext(ctx);
170 if (m_cfg.visionTool) {
171 Result_t preFit{};
172 preFit.parameters = startPars;
173 preFit.measurements = copy(calibHits);
174 auto seedCopy = convertToSegment(localToGlobal, parent, std::move(preFit));
175 m_cfg.visionTool->visualizeSegment(ctx, *seedCopy, "Prefit");
176 }
177 Result_t segFit = callLineFit(cctx, startPars, localToGlobal, std::move(calibHits));
178 if (m_cfg.visionTool && segFit.converged) {
179 auto seedCopy = convertToSegment(localToGlobal, parent, copy(segFit));
180 m_cfg.visionTool->visualizeSegment(ctx, *seedCopy, "Intermediate fit");
181 }
182 if (!removeOutliers(cctx, *parent, localToGlobal, segFit)) {
183 return nullptr;
184 }
185 if (!plugHoles(cctx, *parent, localToGlobal, segFit)) {
186 return nullptr;
187 }
188 auto finalSeg = convertToSegment(localToGlobal, parent, std::move(segFit));
189 if (m_cfg.visionTool) {
190 m_cfg.visionTool->visualizeSegment(ctx, *finalSeg, "Final fit");
191 }
192 return finalSeg;
193 }
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 163 of file AthMessaging.h.

164{
165 MsgStream* ms = m_msg_tls.get();
166 if (!ms) {
167 if (!m_initialized.test_and_set()) initMessaging();
168 ms = new MsgStream(m_imsg,m_nm);
169 m_msg_tls.reset( ms );
170 }
171
172 ms->setLevel (m_lvl);
173 return *ms;
174}
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 178 of file AthMessaging.h.

179{ 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 (m_lvl <= lvl) {
154 msg() << lvl;
155 return true;
156 } else {
157 return false;
158 }
159}

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

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

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

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

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