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

Helper class to group muon sgements that may belong to a muon trajectory. More...

#include <MsTrackSeeder.h>

Inheritance diagram for MuonR4::MsTrackSeeder:
Collaboration diagram for MuonR4::MsTrackSeeder:

Classes

struct  Config
 Configuration object. More...

Public Types

enum class  SectorProjector : std::int8_t { leftOverlap = -1 , center = 0 , rightOverlap = 1 }
 Enumeration to select the sector projection. More...
enum class  SeedCoords : std::uint8_t { eDetSection , eSector , ePosOnCylinder }
 Abrivation of the seed coordinates. More...
using SearchTree_t = Acts::KDTree<3, const xAOD::MuonSegment*, double, std::array, 6>
 Definition of the search tree class.
using Location = MsTrackSeed::Location
 Enum toggling whether the segment is in the endcap or barrel.
using VecOpt_t = std::optional<Amg::Vector3D>

Public Member Functions

 MsTrackSeeder (const std::string &msgName, Config &&cfg)
 Standard constructor.
SearchTree_t constructTree (const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegmentContainer &segments) const
 Construct a complete search tree from a MuonSegment container.
Amg::Vector2D expressOnCylinder (const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegment &segment, const Location loc, const SectorProjector proj) const
 Expresses the segment on the cylinder surface.
Amg::Vector3D projectOntoPhiPlane (const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegment &segment, const double projectPhi) const
Amg::Vector3D projectOntoSector (const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegment &segment, const SectorProjector proj) const
 Projects the segment's position onto the sector centre or onto the overlap point with one of the neighbouring sector.
Amg::Vector3D projectOntoSector (const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegment &segment, const MsTrackSeed &seed) const
 Projects the segment's position onto the sector centre or onto the overlap point with one of the neighbouring sector.
double estimateQtimesP (const ActsTrk::GeometryContext &gctx, const AtlasFieldCacheCondObj &magField, const MsTrackSeed &seed) const
 Estimate the q /p of the seed candidate from the contained segments.
bool withinBounds (const Amg::Vector2D &projPos, const Location loc) const
 Returns whether the expression on the cylinder is within the surface bounds.
std::unique_ptr< MsTrackSeedContainerfindTrackSeeds (const EventContext &ctx, const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegmentContainer &segments) const
 Constructs the MS track seeds from the segment container.
const MuonGMR4::SpectrometerSectorenvelope (const xAOD::MuonSegment &segment) const
 Returns the spectrometer envelope associated to the segment (Coord system where the parameter are expressed)
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.

Static Public Member Functions

static double projectedPhi (const int sector, const SectorProjector proj)
 Returns the projected phi for a given sector and projector.
static SectorProjector projectorFromSeed (const xAOD::MuonSegment &seg, const MsTrackSeed &refSeed)
 Returns the Sector projector within the context of a MsTrackSeed.

Private Types

using TreeRawVec_t = SearchTree_t::vector_t
 Abbrivation of the KDTree raw data vector.

Private Member Functions

std::optional< double > calculateRadius (VecOpt_t &&pI, VecOpt_t &&pM, VecOpt_t &&pO, const Amg::Vector3D &planeNorm) const
 Calculates the radius of the bending circle from three points using the sagitta.
void appendSegment (const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegment *segment, const Location loc, TreeRawVec_t &outContainer) const
 Append the to the raw data container.
std::unique_ptr< MsTrackSeedContainerresolveOverlaps (MsTrackSeedContainer &&unresolved) const
 Removes exact duplciates or partial subsets of the MsTrackSeeds.
void initMessaging () const
 Initialize our message level and MessageSvc.

Private Attributes

Config m_cfg {}
std::string m_nm
 Message source name.
boost::thread_specific_ptr< MsgStream > m_msg_tls
 MsgStream instance (a std::cout like with print-out levels)
std::atomic< IMessageSvc * > m_imsg { nullptr }
 MessageSvc pointer.
std::atomic< MSG::Level > m_lvl { MSG::NIL }
 Current logging level.
std::atomic_flag m_initialized ATLAS_THREAD_SAFE = ATOMIC_FLAG_INIT
 Messaging initialized (initMessaging)

Detailed Description

Helper class to group muon sgements that may belong to a muon trajectory.

The reconstructed muon segments are projected onto the surface of a cylinder crossing roughly the middle stations of the MS. They are then appended to a 3-dimensional search tree using the extrapolated coordinate on the cylnder, the cylinder surface index and the segment's associated sector number.

Definition at line 29 of file MsTrackSeeder.h.

Member Typedef Documentation

◆ Location

Enum toggling whether the segment is in the endcap or barrel.

Definition at line 56 of file MsTrackSeeder.h.

◆ SearchTree_t

using MuonR4::MsTrackSeeder::SearchTree_t = Acts::KDTree<3, const xAOD::MuonSegment*, double, std::array, 6>

Definition of the search tree class.

Definition at line 54 of file MsTrackSeeder.h.

◆ TreeRawVec_t

using MuonR4::MsTrackSeeder::TreeRawVec_t = SearchTree_t::vector_t
private

Abbrivation of the KDTree raw data vector.

Definition at line 160 of file MsTrackSeeder.h.

◆ VecOpt_t

Definition at line 58 of file MsTrackSeeder.h.

Member Enumeration Documentation

◆ SectorProjector

enum class MuonR4::MsTrackSeeder::SectorProjector : std::int8_t
strong

Enumeration to select the sector projection.

Enumerator
leftOverlap 
center 

Project the segment onto the overlap with the previous sector.

rightOverlap 

Project the segment onto the sector centre.

Definition at line 60 of file MsTrackSeeder.h.

60 : std::int8_t {
61 leftOverlap = -1,
62 center = 0,
63 rightOverlap = 1
64 };

◆ SeedCoords

enum class MuonR4::MsTrackSeeder::SeedCoords : std::uint8_t
strong

Abrivation of the seed coordinates.

Enumerator
eDetSection 

Encode the seed location (-1,1 -> endcaps, 0 -> barrel.

eSector 

Sector of the associated spectrometer sector.

ePosOnCylinder 

Extrapolation position along the cylinder surface.

Definition at line 66 of file MsTrackSeeder.h.

66 : std::uint8_t{
68 eDetSection,
70 eSector,
72 ePosOnCylinder
73 };

Constructor & Destructor Documentation

◆ MsTrackSeeder()

MuonR4::MsTrackSeeder::MsTrackSeeder ( const std::string & msgName,
Config && cfg )

Standard constructor.

Parameters
msgNameName of the seeder's msgStream
cfgConfigured cylinder dimensions, cuts & selection tool

Definition at line 79 of file MsTrackSeeder.cxx.

79 :
80 AthMessaging{msgName},
81 m_cfg{std::move(cfg)}{
82 auto& v{m_cfg.fieldExtpSteps};
83 v.insert(0.); v.insert(1.);
84 if (std::ranges::any_of(v, [](const double x){
85 return x < 0. || x > 1.;
86 })) {
87 THROW_EXCEPTION("Found invalid extrapolation steps.");
88 }
89 }
#define x
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10

Member Function Documentation

◆ appendSegment()

void MuonR4::MsTrackSeeder::appendSegment ( const ActsTrk::GeometryContext & gctx,
const xAOD::MuonSegment * segment,
const Location loc,
TreeRawVec_t & outContainer ) const
private

Append the to the raw data container.

If the projection onto the barrel cylinder / endcap discs exceeds the bounds, the segment is not added. Segments in sector 1/16 are mirrored into sector 0/17 to complete the search range

Parameters
gctxGeometry context to fetch the transforms of the associated sector envelope
segmentPointer to the segment to add
locSwitch whether the segment shall be projected onto barrel/endcap
outContainerRaw KDTree data vector where the segment is appended

Check whether the segment belongs to the left or right sector as well

Blow-up the number of sectors by a factor of 2. The even numbers represent the segments expressed @ the sector centre. The odd numbers represent the overlap region between two adjacent sectors. For sector 16, the right overlap region is mapped to 1

Enumeration to indicate whether the segment is expressed on the negative endcap (-1), the barrel (0) or the positive endcap

Coordinate on the cylinder

Definition at line 348 of file MsTrackSeeder.cxx.

351 {
352
353 const int segSector = segment->sector();
354 for (const auto proj : {SectorProjector::leftOverlap, SectorProjector::center, SectorProjector::rightOverlap}) {
356 const int projSector = ringSector(segSector + Acts::toUnderlying(proj));
357 if (segment->nPhiLayers() > 0 && proj != SectorProjector::center &&
358 !sectorMap.insideSector(projSector, segment->position().phi())) {
359 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Segment @"<<Amg::toString(segment->position())
360 <<" is not in sector "<<projSector<<" which is "<<to_string(proj) <<" to "<<segment->sector());
361 continue;
362 }
363 const Amg::Vector2D refPoint{expressOnCylinder(gctx, *segment, loc, proj)};
364 if (!withinBounds(refPoint, loc)) {
365 continue;
366 }
367 using enum SeedCoords;
368 std::array<double, 3> coords{};
372 const int treeSector = 2*segSector + Acts::toUnderlying(proj);
373 coords[Acts::toUnderlying(eSector)] = ringOverlap(treeSector);
376 coords[Acts::toUnderlying(eDetSection)] = Acts::copySign(Acts::toUnderlying(loc), refPoint[1]);
378 coords[Acts::toUnderlying(ePosOnCylinder)] = refPoint[Location::Barrel == loc];
379 ATH_MSG_VERBOSE("Add segment "<<print(*segment)<<", seed quality: "
380 <<m_cfg.selector->passSeedingQuality(Gaudi::Hive::currentContext(), *detailedSegment(*segment))
381 <<" with "<<coords<<" to the search tree");
382 outContainer.emplace_back(std::move(coords), segment);
383 }
384 }
#define ATH_MSG_VERBOSE(x)
void print(char *figname, TCanvas *c1)
bool withinBounds(const Amg::Vector2D &projPos, const Location loc) const
Returns whether the expression on the cylinder is within the surface bounds.
Amg::Vector2D expressOnCylinder(const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegment &segment, const Location loc, const SectorProjector proj) const
Expresses the segment on the cylinder surface.
SeedCoords
Abrivation of the seed coordinates.
@ eSector
Sector of the associated spectrometer sector.
@ ePosOnCylinder
Extrapolation position along the cylinder surface.
@ eDetSection
Encode the seed location (-1,1 -> endcaps, 0 -> barrel.
Amg::Vector3D position() const
Returns the position as Amg::Vector.
int nPhiLayers() const
Returns the number of phi layers.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, 2, 1 > Vector2D
std::string to_string(const SectorProjector proj)
const Segment * detailedSegment(const xAOD::MuonSegment &seg)
Helper function to navigate from the xAOD::MuonSegment to the MuonR4::Segment.

◆ calculateRadius()

std::optional< double > MuonR4::MsTrackSeeder::calculateRadius ( VecOpt_t && pI,
VecOpt_t && pM,
VecOpt_t && pO,
const Amg::Vector3D & planeNorm ) const
private

Calculates the radius of the bending circle from three points using the sagitta.

If one point is not defined, the origin is inserted instead. If two or more points are not set, a nullopt is returned

Derive the radius from the two equations. The line connecting pI and pO divides up the radius in the sagitta and the complementary section H R = S + H Also H is the catheter of the triangle <R, L / 2, H> R^{2} = L^{2} / 4 + H^{2} ---> R^{2} = L^{2} / 4 + (R-S)^{2} ---> 2*S*R = L^{2} / 4 + S^{2} (Approximating S^{2} = 0) ---> R = L^{2} / (8 * s)

Definition at line 186 of file MsTrackSeeder.cxx.

187 {
188 if (!pI || !pM || !pO) {
189 return std::nullopt;
190 }
191 const Amg::Vector3D leverL = (*pO) - (*pI);
192
193 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Construct sagitta from "
194 <<"\n --- Inner: "<<print(*pI) <<"\n --- Middle: "<<print(*pM)
195 <<"\n --- Outer: "<<print(*pO));
196 if (std::abs(planeNorm.dot(leverL)) > Acts::s_onSurfaceTolerance ||
197 std::abs(planeNorm.dot( (*pM) - (*pI))) > Acts::s_onSurfaceTolerance) {
198 THROW_EXCEPTION("The lever arm is in the bending plane: "<<Amg::toString(planeNorm)
199 <<", "<<Amg::toString(leverL.unit())<<", "<<Amg::toString( ((*pM) - (*pI)).unit()));
200 }
201 const Amg::Vector3D sagittaDir = leverL.cross(planeNorm).unit();
202 std::optional<double> sagitta = Amg::intersect<3>(*pI, leverL.unit(), *pM, sagittaDir);
203 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Estimated sagitta: "<<(sagitta ?
204 std::to_string(sagitta.value_or(0.)) : "---")<<", lever arm: "
205 <<(leverL.mag() / Gaudi::Units::m)<<" [m]" );
206 if (!sagitta) {
207 return std::nullopt;
208 }
217 return leverL.dot(leverL) / (8. * (*sagitta));
218 }
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
Eigen::Matrix< double, 3, 1 > Vector3D

◆ constructTree()

SearchTree_t MuonR4::MsTrackSeeder::constructTree ( const ActsTrk::GeometryContext & gctx,
const xAOD::MuonSegmentContainer & segments ) const

Construct a complete search tree from a MuonSegment container.

Parameters
gctxGeometry context to fetch the transforms of the associated sector envelope
segmentsReference to the segment container to construct.

Definition at line 385 of file MsTrackSeeder.cxx.

386 {
387 TreeRawVec_t rawData{};
388 rawData.reserve(3*segments.size());
389 for (const xAOD::MuonSegment* segment : segments){
390 appendSegment(gctx, segment, Location::Barrel, rawData);
391 appendSegment(gctx, segment, Location::Endcap, rawData);
392 }
393 ATH_MSG_VERBOSE("Create a new tree with "<<rawData.size()<<" entries. ");
394 return SearchTree_t{std::move(rawData)};
395 }
size_type size() const noexcept
Returns the number of elements in the collection.
SearchTree_t::vector_t TreeRawVec_t
Abbrivation of the KDTree raw data vector.
void appendSegment(const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegment *segment, const Location loc, TreeRawVec_t &outContainer) const
Append the to the raw data container.
Acts::KDTree< 3, const xAOD::MuonSegment *, double, std::array, 6 > SearchTree_t
Definition of the search tree class.
MuonSegment_v1 MuonSegment
Reference the current persistent version:

◆ envelope()

const MuonGMR4::SpectrometerSector * MuonR4::MsTrackSeeder::envelope ( const xAOD::MuonSegment & segment) const

Returns the spectrometer envelope associated to the segment (Coord system where the parameter are expressed)

Parameters
segmentReference to the segment of interest

Definition at line 97 of file MsTrackSeeder.cxx.

97 {
98 return m_cfg.detMgr->getSectorEnvelope(segment.chamberIndex(),
99 segment.sector(),
100 segment.etaIndex());
101 }
::Muon::MuonStationIndex::ChIndex chamberIndex() const
Returns the chamber index.
int etaIndex() const
Returns the eta index, which corresponds to stationEta in the offline identifiers (and the ).

◆ estimateQtimesP()

double MuonR4::MsTrackSeeder::estimateQtimesP ( const ActsTrk::GeometryContext & gctx,
const AtlasFieldCacheCondObj & magField,
const MsTrackSeed & seed ) const

Estimate the q /p of the seed candidate from the contained segments.

A circle from the inner, middle & outer segment points is constructed. To avoid side effects from (non)-present phi measurements, the segments are expressed on the sector planes

Parameters
gctxGeometry context to fetch the transforms of the associated sector envelope
magFielReference to the magnetic field holder
seedReference to the seed of interest.

Calculate the averaged phi from the segments

Calculate the sagitta points

Sample the magnetic field

Calculate the radius from the barrel segments

Calculate the radius from the endcap segments

If no radius could be calculated return the straight line estimator

Definition at line 219 of file MsTrackSeeder.cxx.

221 {
222
223 MagField::AtlasFieldCache fieldCache{};
224 magField.getInitializedCache(fieldCache);
225
227 double circPhi{0.};
228 unsigned nSegsWithPhi{0};
229 for (const xAOD::MuonSegment* segment : seed.segments()) {
230 if (segment->nPhiLayers() > 0) {
231 circPhi += std::atan2(segment->y(), segment->x());
232 ++nSegsWithPhi;
233 }
234 }
235 if (!nSegsWithPhi){
236 circPhi = projectedPhi(seed.segments()[0]->sector(),
237 projectorFromSeed(*seed.segments()[0], seed));
238 } else {
239 circPhi /=nSegsWithPhi;
240 }
241 auto layerPos{Acts::filledArray<VecOpt_t, 6>(std::nullopt)};
242 double avgBField{0.}, avgTheta{0.};
243 const xAOD::TruthParticle* truthMuon{nullptr};
244 const Amg::Vector3D planeNorm = Acts::makeDirectionFromPhiTheta(circPhi+ 90._degree, 90._degree);
245
246 {
247 Amg::Vector3D projPos = projectOntoPhiPlane(gctx, *seed.segments()[0], circPhi);
248 Amg::Vector3D projDir = dirForBField(*seed.segments()[0], circPhi);
249 Amg::Vector3D locField{Amg::Vector3D::Zero()};
250 unsigned nBFieldPoints{0};
251 const unsigned nSeedSeg = seed.segments().size();
252 using namespace Muon::MuonStationIndex;
253 for (unsigned int s = 0; s < nSeedSeg; ++s) {
254 avgTheta += projDir.theta();
256 const xAOD::MuonSegment& segment{*seed.segments()[s]};
257 if (!truthMuon) {
259 }
260 switch (toStationIndex(segment.chamberIndex())) {
261 using enum StIndex;
262 case BI:
263 case BE:{
264 average(projPos, layerPos[0]);
265 break;
266 } case BM: {
267 average(projPos, layerPos[1]);
268 break;
269 } case BO: {
270 average(projPos, layerPos[2]);
271 break;
272 } case EI:
273 case EE: {
274 average(projPos, layerPos[3]);
275 break;
276 } case EM : {
277 average(projPos, layerPos[4]);
278 break;
279 } case EO : {
280 average(projPos, layerPos[5]);
281 break;
282 } default: {
283 break;
284 }
285 }
286 if (s + 1 == nSeedSeg) {
287 break;
288 }
290 Amg::Vector3D nextDir = dirForBField(*seed.segments()[s+1], circPhi);
291 Amg::Vector3D nextPos = projectOntoPhiPlane(gctx, *seed.segments()[s+1], circPhi);
292
293 for (double fieldStep : m_cfg.fieldExtpSteps) {
294 /* The */
295 if (fieldStep == 0. && s > 0) {
296 continue;
297 }
298 const Amg::Vector3D extPos = (1. -fieldStep) * projPos + fieldStep * nextPos;
299 const Amg::Vector3D extDir = ((1. -fieldStep) * projDir + fieldStep * nextDir).unit();
300 // const Amg::Vector3D loc
301 fieldCache.getField(extPos.data(), locField.data());
302 const double localB = extDir.cross(locField).mag();
303
304 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Segment "<<s<<", step: "<<fieldStep
305 <<", position: "<<Amg::toString(extPos)<<", dir: "<<Amg::toString(extDir)
306 <<" --> localB: "<<(localB * 1000.)<<" T."
307 <<", B: "<<Amg::toString(locField* 1000.)
308 <<", PxB:"<<Amg::toString(extDir.cross(locField).unit())
309 <<", planeNorm: "<<Amg::toString(planeNorm));
310 avgBField += localB;
311 ++nBFieldPoints;
312 }
313 projPos = std::move(nextPos);
314 projDir = std::move(nextDir);
315 }
316 avgBField /= std::max(nBFieldPoints, 1u);
317 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - averaged field: "<<(avgBField * 1000.)
318 <<" T, number of points: "<<nBFieldPoints<<".");
319 }
320 avgTheta /= seed.segments().size();
322 std::optional<double> barrelR = calculateRadius(std::move(layerPos[0]),
323 std::move(layerPos[1]),
324 std::move(layerPos[2]), planeNorm);
326 std::optional<double> endcapR = calculateRadius(std::move(layerPos[3]),
327 std::move(layerPos[4]),
328 std::move(layerPos[5]), planeNorm);
330 if (!barrelR && !endcapR) {
331 return 5.*Gaudi::Units::TeV;
332 }
333 const double r = 0.5* ((barrelR ? *barrelR : *endcapR) +
334 (endcapR ? *endcapR : *barrelR));
336 const double P = 0.3* Gaudi::Units::GeV* avgBField * r / std::abs(std::sin(avgTheta));
337
338 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Estimated radius "<<r / Gaudi::Units::m<<" [m] --> P: "<<
339 (P / Gaudi::Units::GeV)<<" [GeV]");
340
341 if (truthMuon && Acts::copySign(1.f, P) != truthMuon->charge() && truthMuon->abseta() < 2.5 &&
342 (truthMuon->abseta() < 1.3 || truthMuon->abseta() > 1.4) ) {
343 ATH_MSG_WARNING("Invalid charge, pT: "<<(truthMuon->pt() / Gaudi::Units::GeV)<<" [GeV], eta: "
344 <<truthMuon->eta()<<", phi: "<<(truthMuon->phi() / 1._degree)<<", q: "<<truthMuon->charge());
345 }
346 return P;
347 }
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t P(Double_t *tt, Double_t *par)
void getInitializedCache(MagField::AtlasFieldCache &cache) const
get B field cache for evaluation as a function of 2-d or 3-d position.
void getField(const double *ATH_RESTRICT xyz, double *ATH_RESTRICT bxyz, double *ATH_RESTRICT deriv=nullptr)
get B field value at given position xyz[3] is in mm, bxyz[3] is in kT if deriv[9] is given,...
std::optional< double > calculateRadius(VecOpt_t &&pI, VecOpt_t &&pM, VecOpt_t &&pO, const Amg::Vector3D &planeNorm) const
Calculates the radius of the bending circle from three points using the sagitta.
static double projectedPhi(const int sector, const SectorProjector proj)
Returns the projected phi for a given sector and projector.
Amg::Vector3D projectOntoPhiPlane(const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegment &segment, const double projectPhi) const
static SectorProjector projectorFromSeed(const xAOD::MuonSegment &seg, const MsTrackSeed &refSeed)
Returns the Sector projector within the context of a MsTrackSeed.
int r
Definition globals.cxx:22
const xAOD::TruthParticle * getTruthMatchedParticle(const xAOD::MuonSegment &segment)
Returns the particle truth-matched to the segment.
StIndex
enum to classify the different station layers in the muon spectrometer
StIndex toStationIndex(ChIndex index)
convert ChIndex into StIndex
TruthParticle_v1 TruthParticle
Typedef to implementation.

◆ expressOnCylinder()

Amg::Vector2D MuonR4::MsTrackSeeder::expressOnCylinder ( const ActsTrk::GeometryContext & gctx,
const xAOD::MuonSegment & segment,
const Location loc,
const SectorProjector proj ) const

Expresses the segment on the cylinder surface.

Parameters
gctxGeometry context to fetch the transforms of the associated sector envelope
segmentReference to the segment of consideration
locSurface location: [barrel/endcap]

extrapolated position

Definition at line 150 of file MsTrackSeeder.cxx.

153 {
155 const Amg::Vector3D pos{projectOntoSector(gctx, segment, proj)};
156 const Amg::Vector3D dir{segment.direction()};
157
158 const Amg::Vector2D projPos{pos.perp(), pos.z()};
159 const Amg::Vector2D projDir{dir.perp(), dir.z()};
160
161 double lambda{0.};
162 if (Location::Barrel == loc) {
163 lambda = Amg::intersect<2>(projPos, projDir, Amg::Vector2D::UnitX(),
164 m_cfg.barrelRadius).value_or(10. * Gaudi::Units::km);
165 } else {
166 lambda = Amg::intersect<2>(projPos, projDir, Amg::Vector2D::UnitY(),
167 Acts::copySign(m_cfg.endcapDiscZ, projPos[1])).value_or(10. * Gaudi::Units::km);
168 }
169 return projPos + lambda * projDir;
170 }
Amg::Vector3D projectOntoSector(const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegment &segment, const SectorProjector proj) const
Projects the segment's position onto the sector centre or onto the overlap point with one of the neig...
Amg::Vector3D direction() const
Returns the direction as Amg::Vector.

◆ findTrackSeeds()

std::unique_ptr< MsTrackSeedContainer > MuonR4::MsTrackSeeder::findTrackSeeds ( const EventContext & ctx,
const ActsTrk::GeometryContext & gctx,
const xAOD::MuonSegmentContainer & segments ) const

Constructs the MS track seeds from the segment container.

Parameters
ctxEventContext to access conditions / event data
segmentsRefrence to the overall event's segment container

Bad segment not suitable for track seeding or the segment coordinates are just mirrored at the overlap between sector 1 -> 16

Define the search range.

Ensure that only endcap / barrel seeds are considered. The values are integers -> add tiny margin

Move 25 cm along the projected plane

Include the neighbouring sectors

Using the cube above, let the tree search for all compatible segments

Ensure that the sector overlap and momentum vectors are compatible with a MS trajectory

No segments were combined

Calculate the seed's position

Definition at line 396 of file MsTrackSeeder.cxx.

398 {
399 SearchTree_t orderedSegs{constructTree(gctx, segments)};
400 MsTrackSeedContainer trackSeeds{};
401 using enum SeedCoords;
402 for (const auto& [coords, seedCandidate] : orderedSegs) {
405 const Segment* recoSeedCandidate = detailedSegment(*seedCandidate);
406 if (!m_cfg.selector->passSeedingQuality(ctx, *recoSeedCandidate)){
407 continue;
408 }
410 SearchTree_t::range_t selectRange{};
413 selectRange[Acts::toUnderlying(eDetSection)].shrink(coords[Acts::toUnderlying(eDetSection)] - 0.1,
414 coords[Acts::toUnderlying(eDetSection)] + 0.1);
416 selectRange[Acts::toUnderlying(ePosOnCylinder)].shrink(coords[Acts::toUnderlying(ePosOnCylinder)] - m_cfg.seedHalfLength,
417 coords[Acts::toUnderlying(ePosOnCylinder)] + m_cfg.seedHalfLength);
419 selectRange[Acts::toUnderlying(eSector)].shrink(coords[Acts::toUnderlying(eSector)] -0.25,
420 coords[Acts::toUnderlying(eSector)] +0.25);
421
422 MsTrackSeed newSeed{static_cast<Location>(std::abs(coords[Acts::toUnderlying(eDetSection)])),
423 static_cast<int>(coords[Acts::toUnderlying(eSector)])};
425 ATH_MSG_VERBOSE("Search for compatible segments to "<<print(*seedCandidate)<<".");
426 orderedSegs.rangeSearchMapDiscard(selectRange, [&](
427 const SearchTree_t::coordinate_t& /*coords*/,
428 const xAOD::MuonSegment* extendWithMe) {
430 const Segment* extendCandidate = detailedSegment(*extendWithMe);
431 if (!m_cfg.selector->compatibleForTrack(ctx, *recoSeedCandidate, *extendCandidate)) {
432 ATH_MSG_VERBOSE("Segment "<<print(*extendWithMe)<<" is not compatible.");
433 return;
434 }
435 auto itr = std::ranges::find_if(newSeed.segments(), [extendWithMe](const xAOD::MuonSegment* onSeed){
436 return extendWithMe->chamberIndex() == onSeed->chamberIndex();
437 });
438 if (itr == newSeed.segments().end()){
439 ATH_MSG_VERBOSE("Add segment "<<print(*extendWithMe)<<" to seed.");
440 newSeed.addSegment(extendWithMe);
441 } else if (reducedChi2(**itr) > reducedChi2(*extendWithMe) &&
442 (*itr)->nPhiLayers() <= extendWithMe->nPhiLayers()) {
443 newSeed.replaceSegment(*itr, extendWithMe);
444 }
445 });
447 if (newSeed.segments().empty()) {
448 continue;
449 }
450 newSeed.addSegment(seedCandidate);
452 const double r = newSeed.location() == Location::Barrel ? m_cfg.barrelRadius
453 : coords[Acts::toUnderlying(ePosOnCylinder)];
454 const double z = newSeed.location() == Location::Barrel ? coords[Acts::toUnderlying(ePosOnCylinder)]
455 : coords[Acts::toUnderlying(eDetSection)]* m_cfg.endcapDiscZ;
456 const int secCoord = coords[Acts::toUnderlying(eSector)];
457
458 const double phi = sectorMap.sectorOverlapPhi( (secCoord - secCoord % 2) / 2, (secCoord + secCoord % 2) / 2 );
459 Amg::Vector3D pos = r * Acts::makeDirectionFromPhiTheta(phi, 90._degree)
460 + z * Amg::Vector3D::UnitZ();
461
462 newSeed.setPosition(std::move(pos));
463 ATH_MSG_VERBOSE("Add new seed "<<newSeed);
464 trackSeeds.emplace_back(std::move(newSeed));
465 }
466 ATH_MSG_VERBOSE("Found in total "<<trackSeeds.size()<<" before overlap removal");
467 return resolveOverlaps(std::move(trackSeeds));
468 }
Scalar phi() const
phi method
#define z
SearchTree_t constructTree(const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegmentContainer &segments) const
Construct a complete search tree from a MuonSegment container.
std::unique_ptr< MsTrackSeedContainer > resolveOverlaps(MsTrackSeedContainer &&unresolved) const
Removes exact duplciates or partial subsets of the MsTrackSeeds.
MsTrackSeed::Location Location
Enum toggling whether the segment is in the endcap or barrel.
std::vector< MsTrackSeed > MsTrackSeedContainer
Definition MsTrackSeed.h:63

◆ initMessaging()

void AthMessaging::initMessaging ( ) const
privateinherited

Initialize our message level and MessageSvc.

This method should only be called once.

Definition at line 39 of file AthMessaging.cxx.

40{
42 // If user did not set an explicit level, set a default
43 if (m_lvl == MSG::NIL) {
44 m_lvl = m_imsg ?
45 static_cast<MSG::Level>( m_imsg.load()->outputLevel(m_nm) ) :
46 MSG::INFO;
47 }
48}
std::string m_nm
Message source name.
std::atomic< IMessageSvc * > m_imsg
MessageSvc pointer.
std::atomic< MSG::Level > m_lvl
Current logging level.
IMessageSvc * getMessageSvc(bool quiet=false)

◆ msg() [1/2]

MsgStream & AthMessaging::msg ( ) const
inlineinherited

The standard message stream.

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

Definition at line 163 of file AthMessaging.h.

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

◆ msg() [2/2]

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

The standard message stream.

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

Definition at line 178 of file AthMessaging.h.

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

◆ msgLvl()

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

Test the output level.

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

Definition at line 151 of file AthMessaging.h.

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

◆ projectedPhi()

double MuonR4::MsTrackSeeder::projectedPhi ( const int sector,
const SectorProjector proj )
static

Returns the projected phi for a given sector and projector.

Parameters
sectorSector of interest [1-16]
projEnum indicating whether the angle at the left/right overlap or sector center shall be returned

Definition at line 92 of file MsTrackSeeder.cxx.

93 {
94 return sectorMap.sectorOverlapPhi(sector, ringSector(sector + Acts::toUnderlying(proj)));
95 }

◆ projectOntoPhiPlane()

Amg::Vector3D MuonR4::MsTrackSeeder::projectOntoPhiPlane ( const ActsTrk::GeometryContext & gctx,
const xAOD::MuonSegment & segment,
const double projectPhi ) const

Recall that the sector coordinate system is defined such that the x-axis is aligned with the nominal wire direction

Calculate the proper intersection point

Definition at line 129 of file MsTrackSeeder.cxx.

131 {
132 using enum SectorProjector;
133 const Amg::Vector3D segPos3D{segment.position()};
136 const Amg::Vector3D dirAlongTube{envelope(segment)->localToGlobalTrans(gctx).linear().col(0)};
137 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Project onto phi: "<<inDeg(projectPhi));
138 const Amg::Vector3D radialDir = Amg::getRotateZ3D(projectPhi) * Amg::Vector3D::UnitX();
139 using namespace Acts::detail::LineHelper;
141 const auto isect = lineIntersect<3>(segPos3D.z()*Amg::Vector3D::UnitZ(), radialDir,
142 segPos3D, dirAlongTube);
143 using namespace Muon::MuonStationIndex;
144 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Projected "<<printID(segment)
145 <<" segment in @"<<Amg::toString(segPos3D)<<" + "
146 <<Amg::toString(segment.direction())<<", chi2: "<<(segment.chiSquared() / std::max(1.f, segment.numberDoF()))
147 <<", nDoF: "<<segment.numberDoF()<<" --> "<<Amg::toString(isect.position()));
148 return isect.position();
149 }
const Amg::Transform3D & localToGlobalTrans(const ActsTrk::GeometryContext &gctx) const
Returns the local -> global tarnsformation from the sector.
const MuonGMR4::SpectrometerSector * envelope(const xAOD::MuonSegment &segment) const
Returns the spectrometer envelope associated to the segment (Coord system where the parameter are exp...
SectorProjector
Enumeration to select the sector projection.
float numberDoF() const
Returns the numberDoF.
float chiSquared() const
Amg::Transform3D getRotateZ3D(double angle)
get a rotation transformation around Z-axis
std::string printID(const xAOD::MuonSegment &seg)
Print the chamber ID of a segment, e.g.

◆ projectOntoSector() [1/2]

Amg::Vector3D MuonR4::MsTrackSeeder::projectOntoSector ( const ActsTrk::GeometryContext & gctx,
const xAOD::MuonSegment & segment,
const MsTrackSeed & seed ) const

Projects the segment's position onto the sector centre or onto the overlap point with one of the neighbouring sector.

Parameters
gctxGeometry context to fetch the transforms of the associated sector envelope
segmentReference to the segment to project
seedReference to the seed w.r.t. which the segment shall be projected

Definition at line 115 of file MsTrackSeeder.cxx.

117 {
118 return projectOntoSector(gctx, segment, projectorFromSeed(segment, seed));
119 }

◆ projectOntoSector() [2/2]

Amg::Vector3D MuonR4::MsTrackSeeder::projectOntoSector ( const ActsTrk::GeometryContext & gctx,
const xAOD::MuonSegment & segment,
const SectorProjector proj ) const

Projects the segment's position onto the sector centre or onto the overlap point with one of the neighbouring sector.

Parameters
gctxGeometry context to fetch the transforms of the associated sector envelope
segmentReference to the segment to project
projProjector indicating onto which fix point of the sector the projection happens

Fetch the phi onto which we want to project the segment without leaving the wire.

Definition at line 120 of file MsTrackSeeder.cxx.

122 {
124 const double sectorPhi{projectedPhi(segment.sector(), proj)};
125 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Project onto "<<to_string(proj)<<" in "
126 <<envelope(segment)->identString());
127 return projectOntoPhiPlane(gctx, segment, sectorPhi);
128 }

◆ projectorFromSeed()

MsTrackSeeder::SectorProjector MuonR4::MsTrackSeeder::projectorFromSeed ( const xAOD::MuonSegment & seg,
const MsTrackSeed & refSeed )
static

Returns the Sector projector within the context of a MsTrackSeed.

Parameters
segReference to the segment for which the Sector projector shall be returned
refSeedSeed context in which the segment is embedded

Definition at line 103 of file MsTrackSeeder.cxx.

104 {
105
106 int doubSector = 2 * seg.sector();
107 constexpr int nSectors = 2*Muon::MuonStationIndex::numberOfSectors();
108 if (refSeed.sector() == nSectors && doubSector ==2) {
109 return SectorProjector::leftOverlap;
110 } else if (refSeed.sector() == 1 && doubSector == nSectors) {
111 return SectorProjector::rightOverlap;
112 }
113 return static_cast<SectorProjector>(refSeed.sector() - doubSector );
114 }
constexpr unsigned numberOfSectors()
return total number of sectors

◆ resolveOverlaps()

std::unique_ptr< MsTrackSeedContainer > MuonR4::MsTrackSeeder::resolveOverlaps ( MsTrackSeedContainer && unresolved) const
private

Removes exact duplciates or partial subsets of the MsTrackSeeds.

Parameters
unresolvedInput MsTrackSeedContainer with duplicates

Resort the seeds starting from the ones with the most segments to the lowest

There is no segment which shares at least one segment with this candidate

Take the longer seed

Definition at line 470 of file MsTrackSeeder.cxx.

470 {
471
473 std::ranges::sort(unresolved, [](const MsTrackSeed& a, const MsTrackSeed&b) {
474 return a.segments().size() > b.segments().size();
475 });
476 auto outputSeeds = std::make_unique<MsTrackSeedContainer>();
477 outputSeeds->reserve(unresolved.size());
478 std::ranges::copy_if(std::move(unresolved), std::back_inserter(*outputSeeds),
479 [this, &outputSeeds](const MsTrackSeed& testMe) {
480 MsTrackSeedContainer::iterator test_itr =
481 std::ranges::find_if(*outputSeeds, [&testMe](const MsTrackSeed& good) {
482 if (ringOverlap(good.sector() - testMe.sector()) > 1) {
483 return false;
484 }
485 return std::ranges::find_if(testMe.segments(),
486 [&good](const xAOD::MuonSegment* segInTest) {
487 return std::ranges::find(good.segments(), segInTest) != good.segments().end();
488 }) != testMe.segments().end();
489 });
491 if (test_itr == outputSeeds->end()) {
492 ATH_MSG_VERBOSE("Add new seed "<<testMe);
493 return true;
494 }
496 if ( (*test_itr).segments().size() < testMe.segments().size()){
497 (*test_itr) = testMe;
498 }
499 return false;
500 });
501 return outputSeeds;
502 }
static Double_t a

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

◆ withinBounds()

bool MuonR4::MsTrackSeeder::withinBounds ( const Amg::Vector2D & projPos,
const Location loc ) const

Returns whether the expression on the cylinder is within the surface bounds.

Parameters
projPosProjected position on the cylinder
locSurface location: [barrel/endcap]

Definition at line 171 of file MsTrackSeeder.cxx.

172 {
173 using enum Location;
174 if (loc == Barrel && std::abs(projPos[1]) > std::min(m_cfg.endcapDiscZ, m_cfg.barrelLength)) {
175 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Position "<<Amg::toString(projPos)<<
176 " exceeds cylinder boundaries ("<<m_cfg.barrelRadius<<", "
177 <<std::min(m_cfg.endcapDiscZ, m_cfg.barrelLength)<<")");
178 return false;
179 } else if (loc == Endcap && (0 > projPos[0] || projPos[0] > m_cfg.endcapDiscRadius)) {
180 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Position "<<Amg::toString(projPos)<<
181 " exceeds endcap boundaries ("<<m_cfg.endcapDiscRadius<<", "<<Acts::copySign(m_cfg.endcapDiscZ, projPos[1])<<")");
182 return false;
183 }
184 return true;
185 }

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::MsTrackSeeder::m_cfg {}
private

Definition at line 176 of file MsTrackSeeder.h.

176{};

◆ m_imsg

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

MessageSvc pointer.

Definition at line 135 of file AthMessaging.h.

135{ nullptr };

◆ m_lvl

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

Current logging level.

Definition at line 138 of file AthMessaging.h.

138{ MSG::NIL };

◆ m_msg_tls

boost::thread_specific_ptr<MsgStream> AthMessaging::m_msg_tls
mutableprivateinherited

MsgStream instance (a std::cout like with print-out levels)

Definition at line 132 of file AthMessaging.h.

◆ m_nm

std::string AthMessaging::m_nm
privateinherited

Message source name.

Definition at line 129 of file AthMessaging.h.


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