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

Helper class to generate valid seeds for the segment fit. More...

#include <MdtSegmentSeedGenerator.h>

Inheritance diagram for MuonR4::SegmentFit::MdtSegmentSeedGenerator:
Collaboration diagram for MuonR4::SegmentFit::MdtSegmentSeedGenerator:

Classes

struct  Config
 Configuration switches of the module. More...
struct  DriftCircleSeed
 Helper struct from a generated Mdt seed. More...
struct  SeedSolution
 Cache of all solutions seen thus far. More...

Public Types

using LineSeeder_t = Acts::Experimental::CompositeSpacePointLineSeeder
using HitVec = SpacePointPerLayerSplitter::HitVec

Public Member Functions

 MdtSegmentSeedGenerator (const std::string &name, const SegmentSeed *segmentSeed, const Config &configuration)
 Standard constructor taking the segmentSeed to start with and then few configuration tunes.
 ~MdtSegmentSeedGenerator ()
std::optional< DriftCircleSeednextSeed (const EventContext &ctx)
 returns the next seed in the row
unsigned int numGenerated () const
 Returns how many seeds have been generated.
const Configconfig () const
 Returns the current seed configuration.
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 Types

using TangentLine = LineSeeder_t::TwoCircleTangentPars
using TangentAmbi = LineSeeder_t::TangentAmbi

Private Member Functions

bool isValidLine (const TangentLine &solution) const
 Checks whether the intercept and the angle are witihn the allowed ranges.
Line_t::ParamVector constructLinePars (const double theta, const double y0) const
 Construct the 3D-Line parameters from the estimates theta & y0 from the tangent line.
std::optional< DriftCircleSeedbuildSeed (const EventContext &ctx, const HoughHitType &topHit, const HoughHitType &bottomHit, const TangentAmbi ambi)
 Tries to build the seed from the two hits.
void moveToNextCandidate ()
 Prepares the generator to generate the seed from the next pair of drift circles.
void initMessaging () const
 Initialize our message level and MessageSvc.

Static Private Member Functions

static SeedingAux::Config translate (const Config &cfg)
 Translate the SeedGenerator config to a Seed auxillary config.

Private Attributes

Config m_cfg {}
Line_t m_line {}
 Line to instantiate the seed parameters.
const SegmentSeedm_segmentSeed {nullptr}
SpacePointPerLayerSplitter m_hitLayers {m_segmentSeed->getHitsInMax()}
std::size_t m_upperLayer {0}
 Considered layer to pick the top drift circle from.
std::size_t m_lowerLayer {0}
 Considered layer to pick the bottom drift circle from.
std::size_t m_lowerHitIndex {0}
 Explicit hit to pick in the selected bottom layer.
std::size_t m_upperHitIndex {0}
 Explicit hit to pick in the selected top layer.
std::size_t m_signComboIndex {0}
 Index of the left-right ambiguity between the circles.
std::vector< SeedSolutionm_seenSolutions {}
 Vector caching equivalent solutions to avoid double seeding.
unsigned int m_nGenSeeds {0}
 Counter on how many seeds have been generated.
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)

Static Private Attributes

static constexpr std::array< TangentAmbi, 4 > s_signCombos

Detailed Description

Helper class to generate valid seeds for the segment fit.

The generator first returns a seed directly made from the patten recogntion. Afterwards it builds seeds by lying tangent lines to a pair of drift circles. The pairing starts from the innermost & outermost layers with tubes. A valid seed must have at least 4 associated hits which are within a chi2 of 5. If two seeds within the parameter resolution are generated, then the latter one is skipped.

Definition at line 27 of file MdtSegmentSeedGenerator.h.

Member Typedef Documentation

◆ HitVec

◆ LineSeeder_t

using MuonR4::SegmentFit::MdtSegmentSeedGenerator::LineSeeder_t = Acts::Experimental::CompositeSpacePointLineSeeder

Definition at line 29 of file MdtSegmentSeedGenerator.h.

◆ TangentAmbi

using MuonR4::SegmentFit::MdtSegmentSeedGenerator::TangentAmbi = LineSeeder_t::TangentAmbi
private

Definition at line 97 of file MdtSegmentSeedGenerator.h.

◆ TangentLine

using MuonR4::SegmentFit::MdtSegmentSeedGenerator::TangentLine = LineSeeder_t::TwoCircleTangentPars
private

Definition at line 96 of file MdtSegmentSeedGenerator.h.

Constructor & Destructor Documentation

◆ MdtSegmentSeedGenerator()

MuonR4::SegmentFit::MdtSegmentSeedGenerator::MdtSegmentSeedGenerator ( const std::string & name,
const SegmentSeed * segmentSeed,
const Config & configuration )

Standard constructor taking the segmentSeed to start with and then few configuration tunes.

Parameters
nameName of the Seed generator's logger
segmentSeedSeed from which the seeds for the fit are built
configurationPassed configuration settings of the generator

Check whether the first layer is too busy

Check whether the lower layer is too busy

Definition at line 62 of file MdtSegmentSeedGenerator.cxx.

64 :
66 m_cfg{configuration},
67 m_segmentSeed{segmentSeed} {
68
69 if (m_hitLayers.mdtHits().empty()) return;
70
71 if (std::ranges::any_of(m_hitLayers.mdtHits(), [this](const HitVec& vec){
72 return vec.size() > m_cfg.busyLayerLimit;
73 })) {
74 m_cfg.startWithPattern = false;
75 }
76 // Set the start for the upper layer
77 m_upperLayer = m_hitLayers.mdtHits().size()-1;
78
80 while (m_lowerLayer < m_upperLayer){
81 const HitVec& lower{m_hitLayers.mdtHits()[m_lowerLayer]};
82 if (lower.size() > m_cfg.busyLayerLimit || !firstGoodHit(lower, m_lowerHitIndex)) {
84 } else {
85 break;
86 }
87
88 }
90 while (m_lowerLayer < m_upperLayer){
91 const HitVec& upper{m_hitLayers.mdtHits()[m_upperLayer]};
92 if (upper.size() > m_cfg.busyLayerLimit || !firstGoodHit(upper, m_upperHitIndex)) {
94 } else {
95 break;
96 }
97
98 }
99
100 if (msgLvl(MSG::VERBOSE)) {
101 std::stringstream sstr{};
102 for (const auto [layCount, layer] : Acts::enumerate(m_hitLayers.mdtHits())) {
103 sstr<<"Mdt-hits in layer "<<layCount<<": "<<layer.size()<<std::endl;
104 for (const HoughHitType& hit : layer) {
105 sstr<<" **** "<<(*hit)<<std::endl;
106 }
107 }
108 for (const auto [layCount, layer] : Acts::enumerate(m_hitLayers.stripHits())) {
109 sstr<<"Hits in layer "<<layCount<<": "<<layer.size()<<std::endl;
110 for (const HoughHitType& hit : layer) {
111 sstr<<" **** "<<(*hit)<<std::endl;
112 }
113 }
114 ATH_MSG_VERBOSE("SeedGenerator - sorting of hits done. Mdt layers: "<<m_hitLayers.mdtHits().size()
115 <<", strip layers: "<<m_hitLayers.stripHits().size()<<std::endl<<sstr.str()<<std::endl<<std::endl);
116 }
117 }
#define ATH_MSG_VERBOSE(x)
std::vector< size_t > vec
int upper(int c)
bool msgLvl(const MSG::Level lvl) const
Test the output level.
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
std::size_t m_upperLayer
Considered layer to pick the top drift circle from.
std::size_t m_lowerHitIndex
Explicit hit to pick in the selected bottom layer.
std::size_t m_lowerLayer
Considered layer to pick the bottom drift circle from.
std::size_t m_upperHitIndex
Explicit hit to pick in the selected top layer.
bool firstGoodHit(const HitVec &hits, std::size_t &hitIdx)
Find the first good hit in a layer.
const SpacePoint * HoughHitType
@ layer
Definition HitInfo.h:79

◆ ~MdtSegmentSeedGenerator()

MuonR4::SegmentFit::MdtSegmentSeedGenerator::~MdtSegmentSeedGenerator ( )
default

Member Function Documentation

◆ buildSeed()

std::optional< MdtSegmentSeedGenerator::DriftCircleSeed > MuonR4::SegmentFit::MdtSegmentSeedGenerator::buildSeed ( const EventContext & ctx,
const HoughHitType & topHit,
const HoughHitType & bottomHit,
const TangentAmbi ambi )
private

Tries to build the seed from the two hits.

Fails if the solution is invalid or if the seed has already been built before

Parameters
topHitHit candidate from the upper layer
bottomHitHit candidate from the lower layer
signObject encoding whether the tangent is left / right

If there's an estimate on the time of arrival use it

Create a new line position & direction which also takes the potential phi estimates into account

Collect all hits close to the seed line

what ever comes after is not matching onto the segment

Reject seeds with too litle Mdt hit association

Last check wheather another seed with the same left-right combination hasn't already been found

All seed hits are of the same size

Including the places where no seed hit was assigned. Both solutions match in terms of left-right solutions. It's very likely that they're converging to the same segment.

Calibrate the seed hits

Add the solution to the list. That we don't iterate twice over it

If we found a long Mdt seed, then ensure that all subsequent seeds have at least the same amount of Mdt hits.

Associate strip hits

Definition at line 268 of file MdtSegmentSeedGenerator.cxx.

271 {
272
273 const Muon::IMuonIdHelperSvc* idHelperSvc{topHit->msSector()->idHelperSvc()};
274 if (!isGoodDC(*bottomHit) || !isGoodDC(*topHit)) {
275 THROW_EXCEPTION("Bad hit detected, despite that should have been captured upstream "
276 <<isGoodDC(*bottomHit)<<", "<<isGoodDC(*topHit)<<" - lowerLayer: "<<m_lowerLayer
277 <<", upperLayer"<<m_upperLayer<<", "<<"upperHit: "<<m_upperHitIndex<<", lowerHit: "<<m_lowerHitIndex<<" - "
278 <<m_hitLayers.mdtHits().at(m_lowerLayer).size()<<", "<<m_hitLayers.mdtHits().at(m_upperLayer).size());
279 }
280
281 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Attempt to construct seed from "<<idHelperSvc->toString(bottomHit->identify())
282 <<" && top tube "<<idHelperSvc->toString(topHit->identify()));
283
284 SeedSolution solCandidate{};
285 static_cast<TangentLine&>(solCandidate) = LineSeeder_t::constructTangentLine(*topHit, *bottomHit, ambi);
286
287 solCandidate.theta = LineSeeder_t::makeDirection(*bottomHit, solCandidate.theta).theta();
288
289 if (!isValidLine(solCandidate)) {
290 return std::nullopt;
291 }
292
293 std::unique_ptr<CalibratedSpacePoint> calibBottom{}, calibTop{};
295 const double t0 = m_segmentSeed->parameters()[Acts::toUnderlying(ParamDefs::t0)];
296 if (m_cfg.recalibSeedCircles) {
297 m_line.updateParameters(constructLinePars(solCandidate.theta, solCandidate.y0));
300 calibBottom = m_cfg.calibrator->calibrate(ctx, bottomHit, m_line.position(), m_line.direction(), t0);
301 calibTop = m_cfg.calibrator->calibrate(ctx, topHit, m_line.position(), m_line.direction(), t0);
302 static_cast<TangentLine&>(solCandidate) = LineSeeder_t::constructTangentLine(*calibTop, *calibBottom, ambi);
303 solCandidate.theta = LineSeeder_t::makeDirection(*calibBottom, solCandidate.theta).theta();
304 if (!isValidLine(solCandidate)) {
305 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Recalibrated segment seed is invalid");
306 return std::nullopt;
307 }
308 }
309
310 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Test new "<<solCandidate<<". "<<m_seenSolutions.size());
311
312 if (std::ranges::find_if(m_seenSolutions,
313 [&solCandidate, this] (const SeedSolution& seen) {
314 const double deltaY = std::abs(seen.y0 - solCandidate.y0);
315 const double limitY = std::hypot(seen.dY0, solCandidate.dY0);
316 const double dTheta = std::abs(seen.theta - solCandidate.theta);
317 const double limitTh = std::hypot(seen.dTheta, solCandidate.dTheta);
318 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": "<<seen
319 <<std::format(" delta Y: {:.2f} {:} {:.2f}", deltaY, deltaY < limitY ? '<' : '>', limitY)
320 <<std::format(" delta theta: {:.2f} {:} {:.2f}", dTheta, dTheta < limitTh ? '<' : '>', limitTh) );
321 return deltaY < limitY && dTheta < limitTh;;
322 }) != m_seenSolutions.end()){
323 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Reject due to similarity");
324 return std::nullopt;
325 }
326
327 DriftCircleSeed candidateSeed{};
328 candidateSeed.parentBucket = m_segmentSeed->parentBucket();
329
330 const auto finalSeedPars = constructLinePars(solCandidate.theta,solCandidate.y0);
331 m_line.updateParameters(finalSeedPars);
333 for (const auto [layerNr, hitsInLayer] : Acts::enumerate(m_hitLayers.mdtHits())) {
334 ATH_MSG_VERBOSE( __func__<<"() "<<__LINE__<<": "<<hitsInLayer.size()<<" hits in layer "<<(layerNr +1));
335 bool hadGoodHit{false};
336 for (const HoughHitType testMe : hitsInLayer) {
337 using namespace Acts::detail::LineHelper;
338 const double distance = Acts::abs(signedDistance(testMe->localPosition(), testMe->sensorDirection(),
339 m_line.position(), m_line.direction()));
340 const double pull = Acts::abs(distance - testMe->driftRadius()) / std::sqrt(testMe->covariance()[covIdx]);
341
342 const auto* re = static_cast<const xAOD::MdtDriftCircle*>(testMe->primaryMeasurement())->readoutElement();
343
344 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Test hit "<<idHelperSvc->toString(testMe->identify())
345 <<" "<<Amg::toString(testMe->localPosition())<<", pull: "<<pull<<", distance: "<<distance);
346 if (pull < m_cfg.hitPullCut && distance < re->tubeRadius()) {
347 hadGoodHit = true;
348 solCandidate.seedHits.emplace_back(testMe);
349 candidateSeed.nMdt += isGoodDC(*testMe);
350 }
351 else if (hadGoodHit) {
352 break;
353 }
354 }
355 }
357 const unsigned hitCut = std::max(1.*m_cfg.nMdtHitCut,
358 m_cfg.nMdtLayHitCut * m_hitLayers.mdtHits().size());
359
360 if (1.*candidateSeed.nMdt < hitCut) {
361 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Too few hits associated "<<candidateSeed.nMdt<<", expect: "<<hitCut<<" hits.");
362 return std::nullopt;
363 }
364 /* Calculate the left-right signs of the used hits */
365 if (m_cfg.overlapCorridor) {
366 solCandidate.solutionSigns = SeedingAux::strawSigns(m_line, solCandidate.seedHits);
367 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Circle solutions for seed "
368 <<idHelperSvc->toStringChamber(bottomHit->identify())<<" - "<<solCandidate);
370 for (unsigned int a = m_cfg.startWithPattern; a< m_seenSolutions.size() ;++a) {
371 const SeedSolution& accepted = m_seenSolutions[a];
372 unsigned int nOverlap{0};
373 std::vector<int> corridor = SeedingAux::strawSigns(m_line, accepted.seedHits);
374 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Test seed against accepted "<<accepted<<", updated signs: "<<corridor);
376 for (unsigned int l = 0; l < accepted.seedHits.size(); ++l){
377 nOverlap += (corridor[l] == accepted.solutionSigns[l]);
378 }
381 if (nOverlap == corridor.size() && accepted.seedHits.size() >= solCandidate.seedHits.size()) {
382 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Same set of hits collected within the same corridor");
383 return std::nullopt;
384 }
385 }
386 }
387 candidateSeed.parameters[Acts::toUnderlying(ParamDefs::t0)] = t0;
388 for (const auto p : { ParamDefs::x0, ParamDefs::theta, ParamDefs::phi, ParamDefs::y0}) {
389 candidateSeed.parameters[Acts::toUnderlying(p)] = finalSeedPars[Acts::toUnderlying(p)];
390 }
392 for (const HoughHitType& hit : solCandidate.seedHits){
393 //calibBottom is nullptr after it has been moved, so...
394 //cppcheck-suppress accessMoved
395 if (hit == bottomHit && calibBottom) {
396 candidateSeed.measurements.emplace_back(std::move(calibBottom));
397 }
398 //calibTop is nullptr after it has been moved, so...
399 //cppcheck-suppress accessMoved
400 else if (hit == topHit && calibTop) {
401 candidateSeed.measurements.emplace_back(std::move(calibTop));
402 } else {
403 candidateSeed.measurements.emplace_back(m_cfg.calibrator->calibrate(ctx, hit, m_line.position(),
404 m_line.direction(), t0));
405 }
406 }
407
409 m_seenSolutions.emplace_back(std::move(solCandidate));
412 if (m_cfg.tightenHitCut) {
413 m_cfg.nMdtHitCut = std::max(m_cfg.nMdtHitCut, candidateSeed.nMdt);
414 }
415 ++m_nGenSeeds;
416 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": In event "<<ctx.eventID().event_number()<<" found new seed solution "<<toString(candidateSeed.parameters));
417
419 for (const std::vector<HoughHitType>& hitsInLayer : m_hitLayers.stripHits()) {
420 HoughHitType bestHitLoc0{nullptr}, bestHitLoc1{nullptr};
421 double bestPullLoc0{m_cfg.hitPullCut}, bestPullLoc1{m_cfg.hitPullCut};
422 for (const HoughHitType testMe : hitsInLayer) {
423 const double pull = std::sqrt(SeedingAux::chi2Term(m_line, *testMe));
424 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Test hit "<<idHelperSvc->toString(testMe->identify())
425 <<" "<<Amg::toString(testMe->localPosition())<<", pull: "<<pull<<".");
426 if (testMe->measuresLoc0() && pull < bestPullLoc0) {
427 bestPullLoc0 = pull;
428 bestHitLoc0 = testMe;
429 }
430 if (testMe->measuresLoc1() && pull < bestPullLoc1) {
431 bestPullLoc1 = pull;
432 bestHitLoc1 = testMe;
433 }
434 }
435 if (bestHitLoc0) {
436 candidateSeed.measurements.push_back(m_cfg.calibrator->calibrate(ctx, bestHitLoc0, m_line.position(),
437 m_line.direction(), t0));
438 }
439 if (bestHitLoc1 && bestHitLoc1 != bestHitLoc0) {
440 candidateSeed.measurements.push_back(m_cfg.calibrator->calibrate(ctx, bestHitLoc1, m_line.position(),
441 m_line.direction(), t0));
442 }
443
444 }
445 return candidateSeed;
446 }
const boost::regex re(r_e)
static Double_t a
static Double_t t0
Line_t m_line
Line to instantiate the seed parameters.
bool isValidLine(const TangentLine &solution) const
Checks whether the intercept and the angle are witihn the allowed ranges.
LineSeeder_t::TwoCircleTangentPars TangentLine
std::vector< SeedSolution > m_seenSolutions
Vector caching equivalent solutions to avoid double seeding.
Line_t::ParamVector constructLinePars(const double theta, const double y0) const
Construct the 3D-Line parameters from the estimates theta & y0 from the tangent line.
unsigned int m_nGenSeeds
Counter on how many seeds have been generated.
virtual std::string toStringChamber(const Identifier &id) const =0
print all fields up to chamber to string
virtual std::string toString(const Identifier &id) const =0
print all fields to string
const MuonGMR4::MdtReadoutElement * readoutElement() const
Retrieve the associated MdtReadoutElement.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
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.
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
bool isGoodDC(const SpacePoint &dc)
Returns whether the Mdt measurement has a valid space point.
std::string toString(const Parameters &pars)
Dumps the parameters into a string with labels in front of each number.
l
Printing final latex table to .tex output file.
MdtDriftCircle_v1 MdtDriftCircle
const SpacePointBucket * parentBucket
Pointer to the parent bucket.
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10

◆ config()

const MdtSegmentSeedGenerator::Config & MuonR4::SegmentFit::MdtSegmentSeedGenerator::config ( ) const

Returns the current seed configuration.

Definition at line 57 of file MdtSegmentSeedGenerator.cxx.

57 {
58 return m_cfg;
59 }

◆ constructLinePars()

Line_t::ParamVector MuonR4::SegmentFit::MdtSegmentSeedGenerator::constructLinePars ( const double theta,
const double y0 ) const
private

Construct the 3D-Line parameters from the estimates theta & y0 from the tangent line.

Parameters
thetaTangent line theta in the y-z plane
y0Y intercept at z=0

Definition at line 232 of file MdtSegmentSeedGenerator.cxx.

232 {
233 Line_t::ParamVector pars{};
234 pars[Acts::toUnderlying(ParamDefs::y0)] = y0;
235 pars[Acts::toUnderlying(ParamDefs::x0)] = m_segmentSeed->interceptX();
236 if (Acts::abs(m_segmentSeed->tanAlpha()) > std::numeric_limits<double>::epsilon()) {
237 const Amg::Vector3D dirFromTan = Acts::makeDirectionFromAxisTangents(m_segmentSeed->tanAlpha(),
238 std::tan(theta));
239 pars[Acts::toUnderlying(ParamDefs::phi)] = dirFromTan.phi();
240 pars[Acts::toUnderlying(ParamDefs::theta)] = dirFromTan.theta();
241 } else {
242 pars[Acts::toUnderlying(ParamDefs::phi)] = 90._degree;
243 pars[Acts::toUnderlying(ParamDefs::theta)] = theta;
244 }
245 return pars;
246 }
Scalar theta() const
theta method
Eigen::Matrix< double, 3, 1 > Vector3D

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

◆ isValidLine()

bool MuonR4::SegmentFit::MdtSegmentSeedGenerator::isValidLine ( const TangentLine & solution) const
private

Checks whether the intercept and the angle are witihn the allowed ranges.

Parameters
solutionReference to the tangent line solution to check

Definition at line 247 of file MdtSegmentSeedGenerator.cxx.

247 {
248 if (solution.theta < m_cfg.thetaRange[0] ||
249 solution.theta > m_cfg.thetaRange[1]) {
250 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": The theta angle: "
251 <<(solution.theta / 1._degree)
252 <<" is out of the valid range ["<<(m_cfg.thetaRange[0] / 1._degree)
253 <<"-"<<(m_cfg.thetaRange[1] / 1._degree)<<"].");
254 return false;
255 }
256 if (solution.y0 < m_cfg.interceptRange[0] ||
257 solution.y0 > m_cfg.interceptRange[1]) {
258 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": The intercept: "
259 <<solution.y0
260 <<" is out of the valid range ["<<m_cfg.interceptRange[0]
261 <<"-"<<m_cfg.interceptRange[1] <<"].");
262 return false;
263 }
264 return true;
265
266 }

◆ moveToNextCandidate()

void MuonR4::SegmentFit::MdtSegmentSeedGenerator::moveToNextCandidate ( )
inlineprivate

Prepares the generator to generate the seed from the next pair of drift circles.

Vary the left-right solutions

Move to the next hit in the lower layer

Ensure that the first hit in the lower layer is good for seeding

--> So we can update to the next hit in the upper layer

All combinations of hits & lines in both layers are processed Switch to the next lowerLayer. But skip the busy ones according to the configuration

The layer has ineed a good hit

Abort the loop if we parsed the multi-layer boundary

Go to the first lower layer

But search at least the first valid hit there

The layer has ineed a good hit

Definition at line 122 of file MdtSegmentSeedGenerator.cxx.

122 {
123 const HitVec& lower = m_hitLayers.mdtHits()[m_lowerLayer];
124 const HitVec& upper = m_hitLayers.mdtHits()[m_upperLayer];
126 if (++m_signComboIndex < s_signCombos.size()) {
127 return;
128 }
129 m_signComboIndex = 0;
130
132 if (moveToNextHit(lower, m_lowerHitIndex)) {
133 return;
134 }
136 if (firstGoodHit(lower, m_lowerHitIndex)) {
139 return;
140 }
141 }
144 while (m_lowerLayer < m_upperLayer) {
145 const HitVec& nextLower{m_hitLayers.mdtHits()[++m_lowerLayer]};
146 if (nextLower.size() > m_cfg.busyLayerLimit) {
147 continue;
148 }
150 if (firstGoodHit(nextLower, m_lowerHitIndex)) {
151 break;
152 }
153 }
154
157 return;
158 }
160 if (m_lowerLayer >= m_hitLayers.firstLayerFrom2ndMl() && numGenerated()){
162 return;
163 }
165 m_lowerLayer = 0;
166 do {
168 const HitVec& nextLower{m_hitLayers.mdtHits()[m_lowerLayer]};
169 if (nextLower.size() > m_cfg.busyLayerLimit) {
170 continue;
171 }
173 if (firstGoodHit(nextLower, m_lowerHitIndex)) {
174 break;
175 }
176 } while (++m_lowerLayer < m_upperLayer);
177
178 while (m_lowerLayer < m_upperLayer) {
179 const HitVec& nextUpper{m_hitLayers.mdtHits()[--m_upperLayer]};
180 if (nextUpper.size() > m_cfg.busyLayerLimit) {
181 continue;
182 }
183 if (firstGoodHit(nextUpper, m_upperHitIndex)) {
184 break;
185 }
186 }
187 }
std::size_t m_signComboIndex
Index of the left-right ambiguity between the circles.
unsigned int numGenerated() const
Returns how many seeds have been generated.
static constexpr std::array< TangentAmbi, 4 > s_signCombos
bool moveToNextHit(const HitVec &hits, std::size_t &hitIdx)
Move to the next space point with valid drift radius.

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

◆ nextSeed()

std::optional< MdtSegmentSeedGenerator::DriftCircleSeed > MuonR4::SegmentFit::MdtSegmentSeedGenerator::nextSeed ( const EventContext & ctx)

returns the next seed in the row

Increment for the next candidate

If a candidate is built return it. Otherwise continue the process

Definition at line 189 of file MdtSegmentSeedGenerator.cxx.

189 {
190 std::optional<DriftCircleSeed> found = std::nullopt;
191 if (!m_nGenSeeds && m_cfg.startWithPattern) {
192 ++m_nGenSeeds;
193 found = std::make_optional<DriftCircleSeed>();
194 found->parameters = m_segmentSeed->parameters();
195 found->measurements = m_cfg.calibrator->calibrate(ctx,
196 m_segmentSeed->getHitsInMax(),
197 m_segmentSeed->localPosition(),
198 m_segmentSeed->localDirection(),0.);
199 found->parentBucket = m_segmentSeed->parentBucket();
200 found->nMdt = std::ranges::count_if(m_segmentSeed->getHitsInMax(),
201 [](const SpacePoint* hit){
202 return hit->type() == xAOD::UncalibMeasType::MdtDriftCircleType;
203 });
204 SeedSolution patternSeed{};
205 patternSeed.seedHits = m_segmentSeed->getHitsInMax();
206 patternSeed.solutionSigns.resize(2*m_hitLayers.mdtHits().size());
207 patternSeed.y0 = m_segmentSeed->interceptY();
208 patternSeed.theta = m_segmentSeed->tanBeta();
209 m_seenSolutions.push_back(std::move(patternSeed));
210 return found;
211 }
212
213 while (m_lowerLayer < m_upperLayer) {
214 const HitVec& lower = m_hitLayers.mdtHits().at(m_lowerLayer);
215 const HitVec& upper = m_hitLayers.mdtHits().at(m_upperLayer);
216 ATH_MSG_VERBOSE("Layers with hits: "<<m_hitLayers.mdtHits().size()
217 <<" -- next bottom hit: "<<m_lowerLayer<<", hit: "<<m_lowerHitIndex
218 <<" ("<<lower.size()<<"), top hit " <<m_upperLayer<<", "<<m_upperHitIndex
219 <<" ("<<upper.size()<<") - ambiguity "
220 <<LineSeeder_t::toString(s_signCombos[m_signComboIndex]));
221
226 if (found) {
227 return found;
228 }
229 }
230 return std::nullopt;
231 }
std::optional< DriftCircleSeed > buildSeed(const EventContext &ctx, const HoughHitType &topHit, const HoughHitType &bottomHit, const TangentAmbi ambi)
Tries to build the seed from the two hits.
void moveToNextCandidate()
Prepares the generator to generate the seed from the next pair of drift circles.

◆ numGenerated()

unsigned int MuonR4::SegmentFit::MdtSegmentSeedGenerator::numGenerated ( ) const

Returns how many seeds have been generated.

Definition at line 119 of file MdtSegmentSeedGenerator.cxx.

119 {
120 return m_nGenSeeds;
121 }

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

◆ translate()

SeedingAux::Config MuonR4::SegmentFit::MdtSegmentSeedGenerator::translate ( const Config & cfg)
staticprivate

Translate the SeedGenerator config to a Seed auxillary config.

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

Config MuonR4::SegmentFit::MdtSegmentSeedGenerator::m_cfg {}
private

Definition at line 135 of file MdtSegmentSeedGenerator.h.

135{};

◆ m_hitLayers

SpacePointPerLayerSplitter MuonR4::SegmentFit::MdtSegmentSeedGenerator::m_hitLayers {m_segmentSeed->getHitsInMax()}
private

Definition at line 140 of file MdtSegmentSeedGenerator.h.

140{m_segmentSeed->getHitsInMax()};

◆ m_imsg

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

MessageSvc pointer.

Definition at line 135 of file AthMessaging.h.

135{ nullptr };

◆ m_line

Line_t MuonR4::SegmentFit::MdtSegmentSeedGenerator::m_line {}
private

Line to instantiate the seed parameters.

Definition at line 138 of file MdtSegmentSeedGenerator.h.

138{};

◆ m_lowerHitIndex

std::size_t MuonR4::SegmentFit::MdtSegmentSeedGenerator::m_lowerHitIndex {0}
private

Explicit hit to pick in the selected bottom layer.

Definition at line 147 of file MdtSegmentSeedGenerator.h.

147{0};

◆ m_lowerLayer

std::size_t MuonR4::SegmentFit::MdtSegmentSeedGenerator::m_lowerLayer {0}
private

Considered layer to pick the bottom drift circle from.

Definition at line 145 of file MdtSegmentSeedGenerator.h.

145{0};

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

unsigned int MuonR4::SegmentFit::MdtSegmentSeedGenerator::m_nGenSeeds {0}
private

Counter on how many seeds have been generated.

Definition at line 155 of file MdtSegmentSeedGenerator.h.

155{0};

◆ m_nm

std::string AthMessaging::m_nm
privateinherited

Message source name.

Definition at line 129 of file AthMessaging.h.

◆ m_seenSolutions

std::vector<SeedSolution> MuonR4::SegmentFit::MdtSegmentSeedGenerator::m_seenSolutions {}
private

Vector caching equivalent solutions to avoid double seeding.

Definition at line 153 of file MdtSegmentSeedGenerator.h.

153{};

◆ m_segmentSeed

const SegmentSeed* MuonR4::SegmentFit::MdtSegmentSeedGenerator::m_segmentSeed {nullptr}
private

Definition at line 139 of file MdtSegmentSeedGenerator.h.

139{nullptr};

◆ m_signComboIndex

std::size_t MuonR4::SegmentFit::MdtSegmentSeedGenerator::m_signComboIndex {0}
private

Index of the left-right ambiguity between the circles.

Definition at line 151 of file MdtSegmentSeedGenerator.h.

151{0};

◆ m_upperHitIndex

std::size_t MuonR4::SegmentFit::MdtSegmentSeedGenerator::m_upperHitIndex {0}
private

Explicit hit to pick in the selected top layer.

Definition at line 149 of file MdtSegmentSeedGenerator.h.

149{0};

◆ m_upperLayer

std::size_t MuonR4::SegmentFit::MdtSegmentSeedGenerator::m_upperLayer {0}
private

Considered layer to pick the top drift circle from.

Definition at line 143 of file MdtSegmentSeedGenerator.h.

143{0};

◆ s_signCombos

std::array<TangentAmbi, 4> MuonR4::SegmentFit::MdtSegmentSeedGenerator::s_signCombos
staticconstexprprivate
Initial value:
{TangentAmbi::LL, TangentAmbi::RR,
TangentAmbi::LR, TangentAmbi::RL}

Definition at line 98 of file MdtSegmentSeedGenerator.h.

98 {TangentAmbi::LL, TangentAmbi::RR,
99 TangentAmbi::LR, TangentAmbi::RL};

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