ATLAS Offline Software
Loading...
Searching...
No Matches
MsTrackSeeder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
8
9#include "Acts/Utilities/Helpers.hpp"
10#include "Acts/Surfaces/detail/LineHelper.hpp"
11#include "Acts/Definitions/Units.hpp"
12#include "GaudiKernel/PhysicalConstants.h"
13namespace {
14 using namespace Acts::UnitLiterals;
15 constexpr double inDeg(const double a) {
16 return a / 1._degree;
17 }
21 constexpr int ringSector(const int sector) {
22 constexpr int nSectors = Muon::MuonStationIndex::numberOfSectors();
23 return sector == 0 ? nSectors : (sector > nSectors ? 1 : sector);
24 }
26 constexpr int ringOverlap(const int sector) {
27 constexpr int nSectors = 2*Muon::MuonStationIndex::numberOfSectors();
28 return sector > nSectors ? 1 : sector;
29 }
31 void average(const Amg::Vector3D& segPos, std::optional<Amg::Vector3D>& posSlot) {
32 if (!posSlot) {
33 posSlot = segPos;
34 } else {
35 *posSlot = 0.5 * (*posSlot + segPos);
36 }
37 }
39 inline Amg::Vector3D dirForBField(const xAOD::MuonSegment& seg,
40 const double circPhi) {
41 //if (seg.nPhiLayers() > 0) {
42 // return seg.direction();
43 //}
44 const double theta = std::atan2(Acts::fastHypot(seg.px(), seg.py()), seg.pz());
45 return Acts::makeDirectionFromPhiTheta(circPhi, theta);
46 }
47 std::string print(const Amg::Vector3D& v){
48 return std::format("r: {:.2f}, z: {:.2f}, phi: {:.2f}, theta: {:.2f}",
49 v.perp(), v.z(), inDeg((v.phi())), inDeg(v.theta()));
50 }
51
52 float reducedChi2(const xAOD::MuonSegment& seg) {
53 return seg.chiSquared() / std::max(1.f, seg.numberDoF());
54 }
55 std::string print(const xAOD::MuonSegment& seg) {
56 return std::format("{:}, nPrecHits: {:}, nPhiHits: {:}", MuonR4::printID(seg),
57 seg.nPrecisionHits(), seg.nPhiLayers());
58 }
59 static const Muon::MuonSectorMapping sectorMap{};
60}
61
62namespace MuonR4{
65 std::string to_string(const SectorProjector proj){
66 using enum SectorProjector;
67 switch (proj) {
68 case leftOverlap:
69 return "overlap with left sector";
70 case center:
71 return "sector center";
72 case rightOverlap:
73 return "overlap with right sector";
74 default:
75 return "";
76 }
77 }
78
79 MsTrackSeeder::MsTrackSeeder(const std::string& msgName, Config&& cfg):
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 }
90
91
92 double MsTrackSeeder::projectedPhi(const int sector,
93 const SectorProjector proj) {
94 return sectorMap.sectorOverlapPhi(sector, ringSector(sector + Acts::toUnderlying(proj)));
95 }
98 return m_cfg.detMgr->getSectorEnvelope(segment.chamberIndex(),
99 segment.sector(),
100 segment.etaIndex());
101 }
104 const MsTrackSeed& refSeed) {
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 }
116 const xAOD::MuonSegment& segment,
117 const MsTrackSeed& seed) const {
118 return projectOntoSector(gctx, segment, projectorFromSeed(segment, seed));
119 }
121 const xAOD::MuonSegment& segment,
122 const SectorProjector proj) const {
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 }
130 const xAOD::MuonSegment& segment,
131 const double projectPhi) const {
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 }
151 const xAOD::MuonSegment& segment,
152 const Location loc,
153 const SectorProjector proj) const {
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 }
172 const Location loc) const {
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 }
186 std::optional<double> MsTrackSeeder::calculateRadius(VecOpt_t&& pI, VecOpt_t&& pM, VecOpt_t&& pO,
187 const Amg::Vector3D& planeNorm) const {
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 }
220 const AtlasFieldCacheCondObj& magField,
221 const MsTrackSeed& seed) const {
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) {
258 truthMuon = getTruthMatchedParticle(segment);
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 }
349 const xAOD::MuonSegment* segment,
350 const Location loc,
351 TreeRawVec_t& outContainer) const {
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 }
386 const xAOD::MuonSegmentContainer& segments) const{
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 }
396 std::unique_ptr<MsTrackSeedContainer> MsTrackSeeder::findTrackSeeds(const EventContext& ctx,
397 const ActsTrk::GeometryContext& gctx,
398 const xAOD::MuonSegmentContainer& segments) const {
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 }
469 std::unique_ptr<MsTrackSeedContainer>
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 }
503}
Scalar phi() const
phi method
Scalar theta() const
theta method
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t a
static Double_t P(Double_t *tt, Double_t *par)
void print(char *figname, TCanvas *c1)
#define x
#define z
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
void getInitializedCache(MagField::AtlasFieldCache &cache) const
get B field cache for evaluation as a function of 2-d or 3-d position.
size_type size() const noexcept
Returns the number of elements in the collection.
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h)
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,...
A spectrometer sector forms the envelope of all chambers that are placed in the same MS sector & laye...
const Amg::Transform3D & localToGlobalTrans(const ActsTrk::GeometryContext &gctx) const
Returns the local -> global tarnsformation from the sector.
int sector() const
Returns the seed's sector.
Definition MsTrackSeed.h:55
void addSegment(const xAOD::MuonSegment *seg)
Append a segment to the seed.
Location location() const
Returns the location of the seed.
const std::vector< const xAOD::MuonSegment * > & segments() const
Returns the vector of associated segments.
void replaceSegment(const xAOD::MuonSegment *exist, const xAOD::MuonSegment *updated)
Replaces an already added segment in the seed with a better suited one.
void setPosition(Amg::Vector3D &&pos)
set the seed's position
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.
bool withinBounds(const Amg::Vector2D &projPos, const Location loc) const
Returns whether the expression on the cylinder is within the surface bounds.
SearchTree_t constructTree(const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegmentContainer &segments) const
Construct a complete search tree from a MuonSegment container.
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...
SearchTree_t::vector_t TreeRawVec_t
Abbrivation of the KDTree raw data vector.
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.
std::unique_ptr< MsTrackSeedContainer > resolveOverlaps(MsTrackSeedContainer &&unresolved) const
Removes exact duplciates or partial subsets of the MsTrackSeeds.
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.
const MuonGMR4::SpectrometerSector * envelope(const xAOD::MuonSegment &segment) const
Returns the spectrometer envelope associated to the segment (Coord system where the parameter are exp...
static double projectedPhi(const int sector, const SectorProjector proj)
Returns the projected phi for a given sector and projector.
MsTrackSeeder(const std::string &msgName, Config &&cfg)
Standard constructor.
MsTrackSeed::Location Location
Enum toggling whether the segment is in the endcap or barrel.
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.
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.
std::unique_ptr< MsTrackSeedContainer > findTrackSeeds(const EventContext &ctx, const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegmentContainer &segments) const
Constructs the MS track seeds from the segment container.
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.
std::optional< Amg::Vector3D > VecOpt_t
SectorProjector
Enumeration to select the sector projection.
Placeholder for what will later be the muon segment EDM representation.
float px() const
float pz() const
Returns the pz.
float numberDoF() const
Returns the numberDoF.
int nPrecisionHits() const
Amg::Vector3D direction() const
Returns the direction as Amg::Vector.
float chiSquared() const
float py() const
Returns the py.
::Muon::MuonStationIndex::ChIndex chamberIndex() const
Returns the chamber index.
Amg::Vector3D position() const
Returns the position as Amg::Vector.
int nPhiLayers() const
Returns the number of phi layers.
int etaIndex() const
Returns the eta index, which corresponds to stationEta in the offline identifiers (and the ).
int r
Definition globals.cxx:22
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.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Amg::Transform3D getRotateZ3D(double angle)
get a rotation transformation around Z-axis
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
This header ties the generic definitions in this package.
const xAOD::TruthParticle * getTruthMatchedParticle(const xAOD::MuonSegment &segment)
Returns the particle truth-matched to the segment.
std::vector< MsTrackSeed > MsTrackSeedContainer
Definition MsTrackSeed.h:63
std::string printID(const xAOD::MuonSegment &seg)
Print the chamber ID of a segment, e.g.
MsTrackSeeder::SearchTree_t SearchTree_t
std::string to_string(const SectorProjector proj)
MsTrackSeeder::SectorProjector SectorProjector
const Segment * detailedSegment(const xAOD::MuonSegment &seg)
Helper function to navigate from the xAOD::MuonSegment to the MuonR4::Segment.
StIndex
enum to classify the different station layers in the muon spectrometer
StIndex toStationIndex(ChIndex index)
convert ChIndex into StIndex
constexpr unsigned numberOfSectors()
return total number of sectors
STL namespace.
MuonSegmentContainer_v1 MuonSegmentContainer
Definition of the current "MuonSegment container version".
TruthParticle_v1 TruthParticle
Typedef to implementation.
MuonSegment_v1 MuonSegment
Reference the current persistent version:
Configuration object.
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10