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 63 of file MdtSegmentSeedGenerator.cxx.

65 :
67 m_cfg{configuration},
68 m_segmentSeed{segmentSeed} {
69
70 if (m_hitLayers.mdtHits().empty()) return;
71
72 if (std::ranges::any_of(m_hitLayers.mdtHits(), [this](const HitVec& vec){
73 return vec.size() > m_cfg.busyLayerLimit;
74 })) {
75 m_cfg.startWithPattern = false;
76 }
77 // Set the start for the upper layer
78 m_upperLayer = m_hitLayers.mdtHits().size()-1;
79
81 while (m_lowerLayer < m_upperLayer){
82 const HitVec& lower{m_hitLayers.mdtHits()[m_lowerLayer]};
83 if (lower.size() > m_cfg.busyLayerLimit || !firstGoodHit(lower, m_lowerHitIndex)) {
85 } else {
86 break;
87 }
88
89 }
91 while (m_lowerLayer < m_upperLayer){
92 const HitVec& upper{m_hitLayers.mdtHits()[m_upperLayer]};
93 if (upper.size() > m_cfg.busyLayerLimit || !firstGoodHit(upper, m_upperHitIndex)) {
95 } else {
96 break;
97 }
98
99 }
100
101 if (msgLvl(MSG::VERBOSE)) {
102 std::stringstream sstr{};
103 for (const auto [layCount, layer] : Acts::enumerate(m_hitLayers.mdtHits())) {
104 sstr<<"Mdt-hits in layer "<<layCount<<": "<<layer.size()<<std::endl;
105 for (const HoughHitType& hit : layer) {
106 sstr<<" **** "<<(*hit)<<std::endl;
107 }
108 }
109 for (const auto [layCount, layer] : Acts::enumerate(m_hitLayers.stripHits())) {
110 sstr<<"Hits in layer "<<layCount<<": "<<layer.size()<<std::endl;
111 for (const HoughHitType& hit : layer) {
112 sstr<<" **** "<<(*hit)<<std::endl;
113 }
114 }
115 ATH_MSG_VERBOSE("SeedGenerator - sorting of hits done. Mdt layers: "<<m_hitLayers.mdtHits().size()
116 <<", strip layers: "<<m_hitLayers.stripHits().size()<<std::endl<<sstr.str()<<std::endl<<std::endl);
117 }
118 }
#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 269 of file MdtSegmentSeedGenerator.cxx.

272 {
273
274 const Muon::IMuonIdHelperSvc* idHelperSvc{topHit->msSector()->idHelperSvc()};
275 if (!isGoodDC(*bottomHit) || !isGoodDC(*topHit)) {
276 THROW_EXCEPTION("Bad hit detected, despite that should have been captured upstream "
277 <<isGoodDC(*bottomHit)<<", "<<isGoodDC(*topHit)<<" - lowerLayer: "<<m_lowerLayer
278 <<", upperLayer"<<m_upperLayer<<", "<<"upperHit: "<<m_upperHitIndex<<", lowerHit: "<<m_lowerHitIndex<<" - "
279 <<m_hitLayers.mdtHits().at(m_lowerLayer).size()<<", "<<m_hitLayers.mdtHits().at(m_upperLayer).size());
280 }
281
282 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Attempt to construct seed from "<<idHelperSvc->toString(bottomHit->identify())
283 <<" && top tube "<<idHelperSvc->toString(topHit->identify()));
284
285 SeedSolution solCandidate{};
286 static_cast<TangentLine&>(solCandidate) = LineSeeder_t::constructTangentLine(*topHit, *bottomHit, ambi);
287
288 solCandidate.theta = LineSeeder_t::makeDirection(*bottomHit, solCandidate.theta).theta();
289
290 if (!isValidLine(solCandidate)) {
291 return std::nullopt;
292 }
293
294 std::unique_ptr<CalibratedSpacePoint> calibBottom{}, calibTop{};
296 const double t0 = m_segmentSeed->parameters()[Acts::toUnderlying(ParamDefs::t0)];
297 if (m_cfg.recalibSeedCircles) {
298 m_line.updateParameters(constructLinePars(solCandidate.theta, solCandidate.y0));
301 calibBottom = m_cfg.calibrator->calibrate(ctx, bottomHit, m_line.position(), m_line.direction(), t0);
302 calibTop = m_cfg.calibrator->calibrate(ctx, topHit, m_line.position(), m_line.direction(), t0);
303 static_cast<TangentLine&>(solCandidate) = LineSeeder_t::constructTangentLine(*calibTop, *calibBottom, ambi);
304 solCandidate.theta = LineSeeder_t::makeDirection(*calibBottom, solCandidate.theta).theta();
305 if (!isValidLine(solCandidate)) {
306 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Recalibrated segment seed is invalid");
307 return std::nullopt;
308 }
309 }
310
311 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Test new "<<solCandidate<<". "<<m_seenSolutions.size());
312
313 if (std::ranges::find_if(m_seenSolutions,
314 [&solCandidate, this] (const SeedSolution& seen) {
315 const double deltaY = std::abs(seen.y0 - solCandidate.y0);
316 const double limitY = std::hypot(seen.dY0, solCandidate.dY0);
317 const double dTheta = std::abs(seen.theta - solCandidate.theta);
318 const double limitTh = std::hypot(seen.dTheta, solCandidate.dTheta);
319 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": "<<seen
320 <<std::format(" delta Y: {:.2f} {:} {:.2f}", deltaY, deltaY < limitY ? '<' : '>', limitY)
321 <<std::format(" delta theta: {:.2f} {:} {:.2f}", dTheta, dTheta < limitTh ? '<' : '>', limitTh) );
322 return deltaY < limitY && dTheta < limitTh;;
323 }) != m_seenSolutions.end()){
324 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Reject due to similarity");
325 return std::nullopt;
326 }
327
328 DriftCircleSeed candidateSeed{};
329 candidateSeed.parentBucket = m_segmentSeed->parentBucket();
330
331 const auto finalSeedPars = constructLinePars(solCandidate.theta,solCandidate.y0);
332 m_line.updateParameters(finalSeedPars);
334 for (const auto [layerNr, hitsInLayer] : Acts::enumerate(m_hitLayers.mdtHits())) {
335 ATH_MSG_VERBOSE( __func__<<"() "<<__LINE__<<": "<<hitsInLayer.size()<<" hits in layer "<<(layerNr +1));
336 bool hadGoodHit{false};
337 for (const HoughHitType testMe : hitsInLayer) {
338 using namespace Acts::detail::LineHelper;
339 const double distance = Acts::abs(signedDistance(testMe->localPosition(), testMe->sensorDirection(),
340 m_line.position(), m_line.direction()));
341 const double pull = Acts::abs(distance - testMe->driftRadius()) / std::sqrt(testMe->covariance()[covIdx]);
342
343 const auto* re = static_cast<const xAOD::MdtDriftCircle*>(testMe->primaryMeasurement())->readoutElement();
344
345 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Test hit "<<idHelperSvc->toString(testMe->identify())
346 <<" "<<Amg::toString(testMe->localPosition())<<", pull: "<<pull<<", distance: "<<distance);
347 if (pull < m_cfg.hitPullCut && distance < re->tubeRadius()) {
348 hadGoodHit = true;
349 solCandidate.seedHits.emplace_back(testMe);
350 candidateSeed.nMdt += isGoodDC(*testMe);
351 }
352 else if (hadGoodHit) {
353 break;
354 }
355 }
356 }
358 const unsigned hitCut = std::max(1.*m_cfg.nMdtHitCut,
359 m_cfg.nMdtLayHitCut * m_hitLayers.mdtHits().size());
360
361 if (1.*candidateSeed.nMdt < hitCut) {
362 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Too few hits associated "<<candidateSeed.nMdt<<", expect: "<<hitCut<<" hits.");
363 return std::nullopt;
364 }
365 /* Calculate the left-right signs of the used hits */
366 if (m_cfg.overlapCorridor) {
367 solCandidate.solutionSigns = SeedingAux::strawSigns(m_line, solCandidate.seedHits);
368 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Circle solutions for seed "
369 <<idHelperSvc->toStringChamber(bottomHit->identify())<<" - "<<solCandidate);
371 for (unsigned int a = m_cfg.startWithPattern; a< m_seenSolutions.size() ;++a) {
372 const SeedSolution& accepted = m_seenSolutions[a];
373 unsigned int nOverlap{0};
374 std::vector<int> corridor = SeedingAux::strawSigns(m_line, accepted.seedHits);
375 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Test seed against accepted "<<accepted<<", updated signs: "<<corridor);
377 for (unsigned int l = 0; l < accepted.seedHits.size(); ++l){
378 nOverlap += (corridor[l] == accepted.solutionSigns[l]);
379 }
382 if (nOverlap == corridor.size() && accepted.seedHits.size() >= solCandidate.seedHits.size()) {
383 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Same set of hits collected within the same corridor");
384 return std::nullopt;
385 }
386 }
387 }
388 candidateSeed.parameters[Acts::toUnderlying(ParamDefs::t0)] = t0;
389 for (const auto p : { ParamDefs::x0, ParamDefs::theta, ParamDefs::phi, ParamDefs::y0}) {
390 candidateSeed.parameters[Acts::toUnderlying(p)] = finalSeedPars[Acts::toUnderlying(p)];
391 }
393 for (const HoughHitType& hit : solCandidate.seedHits){
394 //calibBottom is nullptr after it has been moved, so...
395 //cppcheck-suppress accessMoved
396 if (hit == bottomHit && calibBottom) {
397 candidateSeed.measurements.emplace_back(std::move(calibBottom));
398 }
399 //calibTop is nullptr after it has been moved, so...
400 //cppcheck-suppress accessMoved
401 else if (hit == topHit && calibTop) {
402 candidateSeed.measurements.emplace_back(std::move(calibTop));
403 } else {
404 candidateSeed.measurements.emplace_back(m_cfg.calibrator->calibrate(ctx, hit, m_line.position(),
405 m_line.direction(), t0));
406 }
407 }
408
410 m_seenSolutions.emplace_back(std::move(solCandidate));
413 if (m_cfg.tightenHitCut) {
414 m_cfg.nMdtHitCut = std::max(m_cfg.nMdtHitCut, candidateSeed.nMdt);
415 }
416 ++m_nGenSeeds;
417 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": In event "<<ctx.eventID().event_number()<<" found new seed solution "<<toString(candidateSeed.parameters));
418
420 for (const std::vector<HoughHitType>& hitsInLayer : m_hitLayers.stripHits()) {
421 HoughHitType bestHitLoc0{nullptr}, bestHitLoc1{nullptr};
422 double bestPullLoc0{m_cfg.hitPullCut}, bestPullLoc1{m_cfg.hitPullCut};
423 for (const HoughHitType testMe : hitsInLayer) {
424 const double pull = std::sqrt(SeedingAux::chi2Term(m_line, *testMe));
425 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<": Test hit "<<idHelperSvc->toString(testMe->identify())
426 <<" "<<Amg::toString(testMe->localPosition())<<", pull: "<<pull<<".");
427 if (testMe->measuresLoc0() && pull < bestPullLoc0) {
428 bestPullLoc0 = pull;
429 bestHitLoc0 = testMe;
430 }
431 if (testMe->measuresLoc1() && pull < bestPullLoc1) {
432 bestPullLoc1 = pull;
433 bestHitLoc1 = testMe;
434 }
435 }
436 if (bestHitLoc0) {
437 candidateSeed.measurements.push_back(m_cfg.calibrator->calibrate(ctx, bestHitLoc0, m_line.position(),
438 m_line.direction(), t0));
439 }
440 if (bestHitLoc1 && bestHitLoc1 != bestHitLoc0) {
441 candidateSeed.measurements.push_back(m_cfg.calibrator->calibrate(ctx, bestHitLoc1, m_line.position(),
442 m_line.direction(), t0));
443 }
444
445 }
446 return candidateSeed;
447 }
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 58 of file MdtSegmentSeedGenerator.cxx.

58 {
59 return m_cfg;
60 }

◆ 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 233 of file MdtSegmentSeedGenerator.cxx.

233 {
234 Line_t::ParamVector pars{};
235 pars[Acts::toUnderlying(ParamDefs::y0)] = y0;
236 pars[Acts::toUnderlying(ParamDefs::x0)] = m_segmentSeed->interceptX();
237 if (Acts::abs(m_segmentSeed->tanAlpha()) > std::numeric_limits<double>::epsilon()) {
238 const Amg::Vector3D dirFromTan = Acts::makeDirectionFromAxisTangents(m_segmentSeed->tanAlpha(),
239 std::tan(theta));
240 pars[Acts::toUnderlying(ParamDefs::phi)] = dirFromTan.phi();
241 pars[Acts::toUnderlying(ParamDefs::theta)] = dirFromTan.theta();
242 } else {
243 pars[Acts::toUnderlying(ParamDefs::phi)] = 90._degree;
244 pars[Acts::toUnderlying(ParamDefs::theta)] = theta;
245 }
246 return pars;
247 }
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 248 of file MdtSegmentSeedGenerator.cxx.

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

◆ 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 123 of file MdtSegmentSeedGenerator.cxx.

123 {
124 const HitVec& lower = m_hitLayers.mdtHits()[m_lowerLayer];
125 const HitVec& upper = m_hitLayers.mdtHits()[m_upperLayer];
127 if (++m_signComboIndex < s_signCombos.size()) {
128 return;
129 }
130 m_signComboIndex = 0;
131
133 if (moveToNextHit(lower, m_lowerHitIndex)) {
134 return;
135 }
137 if (firstGoodHit(lower, m_lowerHitIndex)) {
140 return;
141 }
142 }
145 while (m_lowerLayer < m_upperLayer) {
146 const HitVec& nextLower{m_hitLayers.mdtHits()[++m_lowerLayer]};
147 if (nextLower.size() > m_cfg.busyLayerLimit) {
148 continue;
149 }
151 if (firstGoodHit(nextLower, m_lowerHitIndex)) {
152 break;
153 }
154 }
155
158 return;
159 }
161 if (m_lowerLayer >= m_hitLayers.firstLayerFrom2ndMl() && numGenerated()){
163 return;
164 }
166 m_lowerLayer = 0;
167 do {
169 const HitVec& nextLower{m_hitLayers.mdtHits()[m_lowerLayer]};
170 if (nextLower.size() > m_cfg.busyLayerLimit) {
171 continue;
172 }
174 if (firstGoodHit(nextLower, m_lowerHitIndex)) {
175 break;
176 }
177 } while (++m_lowerLayer < m_upperLayer);
178
179 while (m_lowerLayer < m_upperLayer) {
180 const HitVec& nextUpper{m_hitLayers.mdtHits()[--m_upperLayer]};
181 if (nextUpper.size() > m_cfg.busyLayerLimit) {
182 continue;
183 }
184 if (firstGoodHit(nextUpper, m_upperHitIndex)) {
185 break;
186 }
187 }
188 }
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 163 of file AthMessaging.h.

164{
165 MsgStream* ms = m_msg_tls.get();
166 if (!ms) {
167 if (!m_initialized.test_and_set()) initMessaging();
168 ms = new MsgStream(m_imsg,m_nm);
169 m_msg_tls.reset( ms );
170 }
171
172 ms->setLevel (m_lvl);
173 return *ms;
174}
boost::thread_specific_ptr< MsgStream > m_msg_tls
MsgStream instance (a std::cout like with print-out levels)
void initMessaging() const
Initialize our message level and MessageSvc.

◆ msg() [2/2]

MsgStream & AthMessaging::msg ( const MSG::Level lvl) const
inlineinherited

The standard message stream.

Returns a reference to the default message stream May not be invoked before sysInitialize() has been invoked.

Definition at line 178 of file AthMessaging.h.

179{ return msg() << lvl; }
MsgStream & msg() const
The standard message stream.

◆ msgLvl()

bool AthMessaging::msgLvl ( const MSG::Level lvl) const
inlineinherited

Test the output level.

Parameters
lvlThe message level to test against
Returns
boolean Indicating if messages at given level will be printed
Return values
trueMessages at level "lvl" will be printed

Definition at line 151 of file AthMessaging.h.

152{
153 if (m_lvl <= lvl) {
154 msg() << lvl;
155 return true;
156 } else {
157 return false;
158 }
159}

◆ 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 190 of file MdtSegmentSeedGenerator.cxx.

190 {
191 std::optional<DriftCircleSeed> found = std::nullopt;
192 if (!m_nGenSeeds && m_cfg.startWithPattern) {
193 ++m_nGenSeeds;
194 found = std::make_optional<DriftCircleSeed>();
195 found->parameters = m_segmentSeed->parameters();
196 found->measurements = m_cfg.calibrator->calibrate(ctx,
197 m_segmentSeed->getHitsInMax(),
198 m_segmentSeed->localPosition(),
199 m_segmentSeed->localDirection(),0.);
200 found->parentBucket = m_segmentSeed->parentBucket();
201 found->nMdt = std::ranges::count_if(m_segmentSeed->getHitsInMax(),
202 [](const SpacePoint* hit){
203 return hit->type() == xAOD::UncalibMeasType::MdtDriftCircleType;
204 });
205 SeedSolution patternSeed{};
206 patternSeed.seedHits = m_segmentSeed->getHitsInMax();
207 patternSeed.solutionSigns.resize(2*m_hitLayers.mdtHits().size());
208 patternSeed.y0 = m_segmentSeed->interceptY();
209 patternSeed.theta = m_segmentSeed->tanBeta();
210 m_seenSolutions.push_back(std::move(patternSeed));
211 return found;
212 }
213
214 while (m_lowerLayer < m_upperLayer) {
215 const HitVec& lower = m_hitLayers.mdtHits().at(m_lowerLayer);
216 const HitVec& upper = m_hitLayers.mdtHits().at(m_upperLayer);
217 ATH_MSG_VERBOSE("Layers with hits: "<<m_hitLayers.mdtHits().size()
218 <<" -- next bottom hit: "<<m_lowerLayer<<", hit: "<<m_lowerHitIndex
219 <<" ("<<lower.size()<<"), top hit " <<m_upperLayer<<", "<<m_upperHitIndex
220 <<" ("<<upper.size()<<") - ambiguity "
221 <<LineSeeder_t::toString(s_signCombos[m_signComboIndex]));
222
227 if (found) {
228 return found;
229 }
230 }
231 return std::nullopt;
232 }
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 120 of file MdtSegmentSeedGenerator.cxx.

120 {
121 return m_nGenSeeds;
122 }

◆ 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 134 of file MdtSegmentSeedGenerator.h.

134{};

◆ m_hitLayers

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

Definition at line 139 of file MdtSegmentSeedGenerator.h.

139{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 137 of file MdtSegmentSeedGenerator.h.

137{};

◆ m_lowerHitIndex

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

Explicit hit to pick in the selected bottom layer.

Definition at line 146 of file MdtSegmentSeedGenerator.h.

146{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 144 of file MdtSegmentSeedGenerator.h.

144{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 154 of file MdtSegmentSeedGenerator.h.

154{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 152 of file MdtSegmentSeedGenerator.h.

152{};

◆ m_segmentSeed

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

Definition at line 138 of file MdtSegmentSeedGenerator.h.

138{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 150 of file MdtSegmentSeedGenerator.h.

150{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 148 of file MdtSegmentSeedGenerator.h.

148{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 142 of file MdtSegmentSeedGenerator.h.

142{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: