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, 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 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) < m_fitter.config().parsToUse.size()){
153 return result;
154 }
155 fitOpts.measurements = std::move(calibHits);
156 fitOpts.localToGlobal = localToGlobal;
157 fitOpts.startParameters = startPars;
159 constexpr auto t0idx = toUnderlying(ParamDefs::t0);
160 fitOpts.startParameters[t0idx] = ActsTrk::timeToActs(fitOpts.startParameters[t0idx]);
162 result = m_fitter.fit(std::move(fitOpts));
164 if (m_fitter.config().fitT0){
165 result.parameters[t0idx] = ActsTrk::timeToAthena(result.parameters[t0idx]);
166 result.covariance(t0idx, t0idx) = Acts::square(ActsTrk::timeToAthena(1.)) * result.covariance(t0idx, t0idx);
167 for (ParamDefs p : {ParamDefs::x0, ParamDefs::y0, ParamDefs::phi, ParamDefs::theta}) {
168 auto pidx = toUnderlying(p);
169 result.covariance(t0idx, pidx) = ActsTrk::timeToAthena(result.covariance(t0idx, pidx));
170 result.covariance(pidx, t0idx) = ActsTrk::timeToAthena(result.covariance(pidx, t0idx));
171 }
172 }
173 centerAlongWire(result);
174 return result;
175 }
#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
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)

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

552 {
553 if (std::ranges::any_of(result.measurements,[](const Hit_t& h){
554 return h->measuresPhi();
555 })) {
556 ATH_MSG_VERBOSE("The segment has phi measurements. No centering needed");
557 return;
558 }
559 double avgX{0.};
560 const double nHits = result.measurements.size();
561 std::ranges::for_each(result.measurements, [&avgX, nHits](const Hit_t& hit) {
562 return avgX += hit->localPosition().x() / nHits;
563 });
564 result.parameters[toUnderlying(ParamDefs::x0)] = avgX;
565 }
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 328 of file SegmentLineFitter.cxx.

330 {
331 const SpacePointPerLayerSorter sorter{};
333 std::ranges::sort(hits, [&sorter, &linePos, &lineDir](const Hit_t&a ,const Hit_t& b){
334 if (a->isStraw() || b->isStraw()) {
335 return !a->isStraw();
336 }
337 if (a->type() == xAOD::UncalibMeasType::Other ||
338 b->type() == xAOD::UncalibMeasType::Other) {
339 return a->type() != xAOD::UncalibMeasType::Other;
340 }
341 const unsigned lay_a = sorter.sectorLayerNum(*a->spacePoint());
342 const unsigned lay_b = sorter.sectorLayerNum(*b->spacePoint());
343 if (lay_a != lay_b) {
344 return lay_a < lay_b;
345 }
346 return SeedingAux::chi2Term(linePos, lineDir, *a) <
347 SeedingAux::chi2Term(linePos, lineDir, *b);
348 });
350 for (HitVec_t::iterator itr = hits.begin(); itr != hits.end(); ++itr) {
351 const Hit_t& hit_a{*itr};
352 if (hit_a->isStraw()){
353 break;
354 }
355 if(hit_a->fitState() == HitState::Duplicate ||
356 hit_a->type() == xAOD::UncalibMeasType::Other) {
357 continue;
358 }
359 const unsigned lay_a = sorter.sectorLayerNum(*hit_a->spacePoint());
361 for (HitVec_t::iterator itr2 = itr + 1; itr2 != hits.end(); ++itr2) {
362 const Hit_t& hit_b{*itr2};
363 if (hit_b->type() == xAOD::UncalibMeasType::Other) {
364 continue;
365 }
366 if (lay_a != sorter.sectorLayerNum(*hit_b->spacePoint())) {
367 break;
368 }
370 if ( (hit_a->measuresEta() && hit_b->measuresEta()) ||
371 (hit_a->measuresPhi() && hit_b->measuresPhi())) {
372 ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__ <<": Reject "
373 <<m_cfg.idHelperSvc->toString(hit_b->spacePoint()->identify()) <<" in favour of "
374 <<m_cfg.idHelperSvc->toString(hit_a->spacePoint()->identify()));
375 hit_b->setFitState(HitState::Duplicate);
376 }
377 }
378 }
379 }
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 211 of file SegmentLineFitter.cxx.

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

306 {
307 auto [segPos, segDir] = makeLine(candidate.parameters);
308 cleanStripLayers(segPos, segDir, candidate.measurements);
309 candidate.measurements.erase(std::remove_if(candidate.measurements.begin(),
310 candidate.measurements.end(),
311 [&](const HitVec_t::value_type& hit){
312 if (hit->fitState() == HitState::Valid) {
313 return false;
314 } else if (hit->fitState() == HitState::Duplicate) {
315 return true;
316 }
319 const double dist = Amg::lineDistance(segPos, segDir,
320 hit->localPosition(),
321 hit->sensorDirection());
322 const auto* dc = static_cast<const xAOD::MdtDriftCircle*>(hit->spacePoint()->primaryMeasurement());
323 return dist >= dc->readoutElement()->innerTubeRadius();
324 }
325 return false;
326 }), candidate.measurements.end());
327 }
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 177 of file SegmentLineFitter.cxx.

181 {
182
183 const Acts::CalibrationContext cctx = ActsTrk::getCalibrationContext(ctx);
184 if (m_cfg.visionTool) {
185 Result_t preFit{};
186 preFit.parameters = startPars;
187 preFit.measurements = copy(calibHits);
188 auto seedCopy = convertToSegment(localToGlobal, parent, std::move(preFit));
189 m_cfg.visionTool->visualizeSegment(ctx, *seedCopy, "Prefit");
190 }
191 Result_t segFit = callLineFit(cctx, startPars, localToGlobal, std::move(calibHits));
192 if (m_cfg.visionTool && segFit.converged) {
193 auto seedCopy = convertToSegment(localToGlobal, parent, copy(segFit));
194 m_cfg.visionTool->visualizeSegment(ctx, *seedCopy, "Intermediate fit");
195 }
196 if (!removeOutliers(cctx, *parent, localToGlobal,
197 segFit.converged? segFit.parameters : startPars,
198 segFit)) {
199 return nullptr;
200 }
201 if (!plugHoles(cctx, *parent, localToGlobal, segFit)) {
202 return nullptr;
203 }
204 auto finalSeg = convertToSegment(localToGlobal, parent, std::move(segFit));
205 if (m_cfg.visionTool) {
206 m_cfg.visionTool->visualizeSegment(ctx, *finalSeg, "Final fit");
207 }
208 return finalSeg;
209 }
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 380 of file SegmentLineFitter.cxx.

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

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

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