ATLAS Offline Software
Classes | Public Types | Public Member Functions | Private Member Functions | Private Attributes | List of all members
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. More...
 
using LinePar_t = Fitter_t::ParamVec_t
 Abrivation of the fitted line parameters. More...
 
using Hit_t = std::unique_ptr< CalibratedSpacePoint >
 Abrivation of the space point type to use. More...
 
using HitVec_t = std::vector< Hit_t >
 Collection of space points. More...
 
using FitPars_t = Fitter_t::FitParameters
 Abrivation of the fit parameters
More...
 
using Result_t = Fitter_t::FitResult< HitVec_t >
 Abrivation of the fit result. More...
 
using FitOpts_t = Fitter_t::FitOptions< HitVec_t, ISpacePointCalibrator >
 Abrivation of the fit options. More...
 
using Selector_t = Fitter_t::Selector_t< CalibratedSpacePoint >
 Abrivation of the hit selector to choose valid hits. More...
 
using HitState = CalibratedSpacePoint::State
 Abrivation of the fit state flag. More...
 

Public Member Functions

 SegmentLineFitter (const std::string &name, Config &&config)
 Standard constructor. More...
 
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. More...
 
bool msgLvl (const MSG::Level lvl) const
 Test the output level. More...
 
MsgStream & msg () const
 The standard message stream. More...
 
MsgStream & msg (const MSG::Level lvl) const
 The standard message stream. More...
 
void setLevel (MSG::Level lvl)
 Change the current logging level. More...
 

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. More...
 
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. More...
 
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. More...
 
bool plugHoles (const Acts::CalibrationContext &cctx, const SegmentSeed &seed, const Amg::Transform3D &localToGlobal, Result_t &toRecover) const
 Recovery of missed hits. More...
 
void eraseWrongHits (Result_t &candidate) const
 Removes all hits from the segment which are obvious outliers. More...
 
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. More...
 
std::unique_ptr< SegmentconvertToSegment (const Amg::Transform3D &locToGlobTrf, const SegmentSeed *parentSeed, Result_t &&toConvert) const
 Converts the fit result into a segment object. More...
 
void initMessaging () const
 Initialize our message level and MessageSvc. More...
 

Private Attributes

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

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  }

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)]);
160  return result;
161  }

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

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

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

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

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

◆ 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  m_lvl = m_imsg ?
43  static_cast<MSG::Level>( m_imsg.load()->outputLevel(m_nm) ) :
44  MSG::INFO;
45 }

◆ 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 164 of file AthMessaging.h.

165 {
166  MsgStream* ms = m_msg_tls.get();
167  if (!ms) {
168  if (!m_initialized.test_and_set()) initMessaging();
169  ms = new MsgStream(m_imsg,m_nm);
170  m_msg_tls.reset( ms );
171  }
172 
173  ms->setLevel (m_lvl);
174  return *ms;
175 }

◆ 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 179 of file AthMessaging.h.

180 { return msg() << lvl; }

◆ 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_initialized.test_and_set()) initMessaging();
154  if (m_lvl <= lvl) {
155  msg() << lvl;
156  return true;
157  } else {
158  return false;
159  }
160 }

◆ 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);
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  }

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

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

◆ m_imsg

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

MessageSvc pointer.

Definition at line 135 of file AthMessaging.h.

◆ m_lvl

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

Current logging level.

Definition at line 138 of file AthMessaging.h.

◆ 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:
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
MuonR4::SegmentFit::SegmentLineFitter::centerAlongWire
void centerAlongWire(Result_t &fitResult) const
Moves the segment to the average x0 position, if the segment does not contain any measurement.
Definition: SegmentLineFitter.cxx:535
MuonR4::SegmentFit::SegmentLineFitter::FitOpts_t
Fitter_t::FitOptions< HitVec_t, ISpacePointCalibrator > FitOpts_t
Abrivation of the fit options.
Definition: SegmentLineFitter.h:43
AthMessaging::m_lvl
std::atomic< MSG::Level > m_lvl
Current logging level.
Definition: AthMessaging.h:138
ActsTrk::getCalibrationContext
Acts::CalibrationContext getCalibrationContext(const EventContext &ctx)
The Acts::Calibration context is piped through the Acts fitters to (re)calibrate the Acts::SourceLink...
Definition: CalibrationContext.h:15
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
TRTCalib_Extractor.hits
hits
Definition: TRTCalib_Extractor.py:35
get_generator_info.result
result
Definition: get_generator_info.py:21
MuonR4::SegmentFit::SegmentLineFitter::ConfigSwitches::nPrecHitCut
unsigned nPrecHitCut
Minimum number of precision hits.
Definition: SegmentLineFitter.h:66
MuonR4::CalibratedSpacePoint::State::Valid
@ Valid
MuonR4::SegmentFit::SegmentLineFitter::m_cfg
ConfigSwitches m_cfg
Configuration switches of the ATLAS fitter implementation.
Definition: SegmentLineFitter.h:108
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
MuonR4::SegmentFit::SegmentLineFitter::m_goodHitSel
Selector_t m_goodHitSel
Selector to identify the valid hits.
Definition: SegmentLineFitter.h:110
python.base_data.config
config
Definition: base_data.py:20
MuonR4::SpacePoint::Cov_t
std::array< double, 3 > Cov_t
Abrivation of the covariance type.
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/MuonSpacePoint/SpacePoint.h:27
ALFA_EventTPCnv_Dict::t0
std::vector< ALFA_RawData_p1 > t0
Definition: ALFA_EventTPCnvDict.h:42
MuonValR4::IPatternVisualizationTool::visualizeSegment
virtual void visualizeSegment(const EventContext &ctx, const MuonR4::Segment &segment, const std::string &extraLabel) const =0
Visualize the used space points of the segment together with the seed parameters.
MuonR4::ISpacePointCalibrator::calibrate
virtual CalibSpacePointPtr calibrate(const EventContext &ctx, const SpacePoint *spacePoint, const Amg::Vector3D &seedPosInChamb, const Amg::Vector3D &seedDirInChamb, const double timeDelay) const =0
Calibrates a single space point.
postInclude.sorter
sorter
Definition: postInclude.SortInput.py:23
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
xAOD::UncalibMeasType::sTgcStripType
@ sTgcStripType
MuonR4::SpacePoint::CovIdx::etaCov
@ etaCov
MuonR4::SegmentFit::makeLine
std::pair< Amg::Vector3D, Amg::Vector3D > makeLine(const Parameters &pars)
Returns the parsed parameters into an Eigen line parametrization.
Definition: SegmentFitterEventData.cxx:35
AthMessaging::m_imsg
std::atomic< IMessageSvc * > m_imsg
MessageSvc pointer.
Definition: AthMessaging.h:135
Trk::u
@ u
Enums for curvilinear frames.
Definition: ParamDefs.h:77
ActsTrk::timeToAthena
constexpr double timeToAthena(const double actsT)
Converts a time unit from Acts to Athena units.
Definition: UnitConverters.h:56
Athena::getMessageSvc
IMessageSvc * getMessageSvc(bool quiet=false)
Definition: getMessageSvc.cxx:20
config
Definition: PhysicsAnalysis/AnalysisCommon/AssociationUtils/python/config.py:1
makeActsAthenaLogger
std::unique_ptr< const Acts::Logger > makeActsAthenaLogger(IMessageSvc *svc, const std::string &name, int level, std::optional< std::string > parent_name)
Definition: Tracking/Acts/ActsInterop/src/Logger.cxx:64
MuonR4::SegmentFit::SegmentLineFitter::removeOutliers
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.
Definition: SegmentLineFitter.cxx:227
ActsTrk::timeToActs
constexpr double timeToActs(const double athenaT)
Converts a time unit from Athena to Acts units.
Definition: UnitConverters.h:49
MuonR4::CalibratedSpacePoint::State::Outlier
@ Outlier
Amg::toString
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Definition: GeoPrimitivesToStringConverter.h:40
Generate_dsid_ranseed.seed
seed
Definition: Generate_dsid_ranseed.py:10
TrigConf::MSGTC::Level
Level
Definition: Trigger/TrigConfiguration/TrigConfBase/TrigConfBase/MsgStream.h:21
AthMessaging::msgLvl
bool msgLvl(const MSG::Level lvl) const
Test the output level.
Definition: AthMessaging.h:151
MuonR4::SegmentFit::SegmentLineFitter::ConfigSwitches::outlierRemovalCut
double outlierRemovalCut
Cut on the segment chi2 / nDoF to launch the outlier removal.
Definition: SegmentLineFitter.h:62
h
MuonR4::SegmentFit::SegmentLineFitter::eraseWrongHits
void eraseWrongHits(Result_t &candidate) const
Removes all hits from the segment which are obvious outliers.
Definition: SegmentLineFitter.cxx:282
MuonR4::SegmentFit::SegmentLineFitter::callLineFit
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.
Definition: SegmentLineFitter.cxx:114
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
MuonR4::SegmentFit::SegmentLineFitter::cleanStripLayers
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...
Definition: SegmentLineFitter.cxx:304
MuonR4::CalibratedSpacePoint::State::Duplicate
@ Duplicate
test_pyathena.parent
parent
Definition: test_pyathena.py:15
AthMessaging
Class to provide easy MsgStream access and capabilities.
Definition: AthMessaging.h:55
xAOD::Other
@ Other
python.StandardJetMods.pull
pull
Definition: StandardJetMods.py:309
MuonR4::SegmentFit::toString
std::string toString(const Parameters &pars)
Dumps the parameters into a string with labels in front of each number.
Definition: SegmentFitterEventData.cxx:73
MuonR4::SegmentFit::SegmentLineFitter::plugHoles
bool plugHoles(const Acts::CalibrationContext &cctx, const SegmentSeed &seed, const Amg::Transform3D &localToGlobal, Result_t &toRecover) const
Recovery of missed hits.
Definition: SegmentLineFitter.cxx:363
detail::ul
unsigned long ul
Definition: PrimitiveHelpers.h:46
MuonR4::SegmentFit::SegmentLineFitter::ConfigSwitches::calibrator
const ISpacePointCalibrator * calibrator
Pointer to the calibrator.
Definition: SegmentLineFitter.h:51
AthMessaging::msg
MsgStream & msg() const
The standard message stream.
Definition: AthMessaging.h:164
beamspotman.dir
string dir
Definition: beamspotman.py:619
MuonR4::SegmentFit::SegmentLineFitter::ConfigSwitches::doBeamSpot
bool doBeamSpot
Switch to insert a beamspot constraint if possible.
Definition: SegmentLineFitter.h:57
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
MuonR4::SpacePoint::CovIdx::phiCov
@ phiCov
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
python.copyTCTOutput.locDir
locDir
Definition: copyTCTOutput.py:110
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:16
MuonR4::SegmentFit::SegmentLineFitter::convertToSegment
std::unique_ptr< Segment > convertToSegment(const Amg::Transform3D &locToGlobTrf, const SegmentSeed *parentSeed, Result_t &&toConvert) const
Converts the fit result into a segment object.
Definition: SegmentLineFitter.cxx:195
MuonR4::SegmentFit::SegmentLineFitter::ConfigSwitches::idHelperSvc
const Muon::IMuonIdHelperSvc * idHelperSvc
Pointer to the idHelperSvc.
Definition: SegmentLineFitter.h:55
MuonR4::SegmentFit::SegmentLineFitter::m_fitter
Fitter_t m_fitter
Actual implementation of the straight line fit
Definition: SegmentLineFitter.h:106
MuonR4::SegmentFit::SegmentLineFitter::ConfigSwitches::beamSpotLength
double beamSpotLength
Definition: SegmentLineFitter.h:60
a
TList * a
Definition: liststreamerinfos.cxx:10
Muon::IMuonIdHelperSvc::toString
virtual std::string toString(const Identifier &id) const =0
print all fields to string
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
python.Constants.INFO
int INFO
Definition: Control/AthenaCommon/python/Constants.py:15
MuonR4::SegmentFit::SegmentLineFitter::ConfigSwitches::nRecoveryLoops
unsigned nRecoveryLoops
Maximum trials to recover outliers.
Definition: SegmentLineFitter.h:68
AthMessaging::m_nm
std::string m_nm
Message source name.
Definition: AthMessaging.h:129
MuonR4::SegmentFit::SegmentLineFitter::ConfigSwitches::beamSpotRadius
double beamSpotRadius
Parameters of the beamspot measurement.
Definition: SegmentLineFitter.h:59
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:567
MuonR4::SegmentFit::SegmentLineFitter::Result_t
Fitter_t::FitResult< HitVec_t > Result_t
Abrivation of the fit result.
Definition: SegmentLineFitter.h:41
Amg::signedDistance
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.
Definition: GeoPrimitivesHelpers.h:329
python.BuildSignatureFlags.beamSpot
AthConfigFlags beamSpot(AthConfigFlags flags, str instanceName, str recoMode)
Definition: BuildSignatureFlags.py:491
calibdata.copy
bool copy
Definition: calibdata.py:26
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:13
AthMessaging::initMessaging
void initMessaging() const
Initialize our message level and MessageSvc.
Definition: AthMessaging.cxx:39
xAOD::MdtDriftCircle_v1
https://gitlab.cern.ch/atlas/athena/-/blob/master/MuonSpectrometer/MuonReconstruction/MuonRecEvent/Mu...
Definition: MdtDriftCircle_v1.h:21
AthMessaging::m_msg_tls
boost::thread_specific_ptr< MsgStream > m_msg_tls
MsgStream instance (a std::cout like with print-out levels)
Definition: AthMessaging.h:132
MuonR4::SegmentFit::SegmentLineFitter::HitVec_t
std::vector< Hit_t > HitVec_t
Collection of space points.
Definition: SegmentLineFitter.h:37
MuonR4::SegmentFit::SegmentLineFitter::Hit_t
std::unique_ptr< CalibratedSpacePoint > Hit_t
Abrivation of the space point type to use.
Definition: SegmentLineFitter.h:35
xAOD::UncalibMeasType::MdtDriftCircleType
@ MdtDriftCircleType
MuonR4::SegmentFit::SegmentLineFitter::ConfigSwitches::recoveryPull
double recoveryPull
Maximum pull on a measurement to add it back on the line.
Definition: SegmentLineFitter.h:64
MuonR4::SegmentFit::SegmentLineFitter::ConfigSwitches::visionTool
const MuonValR4::IPatternVisualizationTool * visionTool
Pointer to the visualization tool.
Definition: SegmentLineFitter.h:53
python.SystemOfUnits.ms
float ms
Definition: SystemOfUnits.py:148