19 #include "AthLinks/ElementLink.h"
40 struct SegmentExtrCache {
41 SegmentExtrCache(
const std::shared_ptr<const Trk::AtaPlane>& extp,
const Trk::Surface& surf) :
42 segment_surface{&surf}, segment_pars{extp} {}
44 std::shared_ptr<const Trk::AtaPlane> segment_pars{
nullptr};
51 declareInterface<IMuonSegmentTagTool>(
this);
68 return StatusCode::SUCCESS;
77 for (
unsigned int i = 0;
i < SurfDef::NumSurf; ++
i) {
78 const double recyc_extr = m_recycledIntersect[
i] + m_extrapolated[
i];
79 auto calc_ratio = [&recyc_extr](
unsigned int N) ->
double {
return recyc_extr > 0. ? 100. *
N / recyc_extr : 0; };
81 <<
" (" << calc_ratio(m_extrapolated[
i]) <<
" %) "
82 <<
" recycled " << m_recycledIntersect[
i] <<
" (" << calc_ratio(m_recycledIntersect[
i]) <<
"%) "
83 <<
" good " << m_goodExtrapolated[
i] <<
" (" << calc_ratio(m_goodExtrapolated[
i]) <<
"%)");
85 return StatusCode::SUCCESS;
89 if (inDetCandidates.
empty())
return;
91 std::vector<const Muon::MuonSegment*> FilteredSegmentCollection =
getCandidateSegments(segments);
93 ATH_MSG_DEBUG(
"Filtered segments... in: " << segments.size() <<
", out: " << FilteredSegmentCollection.size());
95 if (FilteredSegmentCollection.empty())
return;
97 unsigned int trackCount{0};
98 ATH_MSG_DEBUG(
"performing tag of " << inDetCandidates.
size() <<
" tracks with " << FilteredSegmentCollection.size()
104 std::vector<MuonCombined::MuonSegmentInfo> segmentsInfoSelected;
105 segmentsInfoSelected.reserve(FilteredSegmentCollection.size());
113 bool matchedSegment{
false};
120 const double eta = std::abs(
track.eta());
121 const double p = std::abs(1.0 /
track.qOverP());
122 if (
eta > 1.4 &&
eta < 1.7 &&
p < 6000.)
continue;
124 ATH_MSG_DEBUG(
"Treating track " << trackCount <<
" " << idTP->toString());
131 const bool trkEtaInfo = nrIDetaHits >= 5;
132 if (!trkEtaInfo)
ATH_MSG_DEBUG(
"Track has no ID eta information! (" << nrIDetaHits <<
" etaHits)");
138 if (assocStat.empty())
continue;
140 const unsigned int num_assoc_segs =
142 [](
unsigned int N,
const std::pair<
int, std::vector<const Muon::MuonSegment*>>& seg_stat) {
143 return N + seg_stat.second.size();
146 std::vector<MuonCombined::MuonSegmentInfo> segmentsInfo;
147 segmentsInfo.reserve(num_assoc_segs);
150 std::optional<std::vector<std::string>> didExtrapolate =
151 m_doTable ? std::make_optional<std::vector<std::string>>(SurfDef::NumSurf * multiply,
"o") : std::nullopt;
152 std::optional<std::vector<std::string>> segStation =
153 m_doTable ? std::make_optional<std::vector<std::string>>(num_assoc_segs,
"XXX") : std::nullopt;
154 std::optional<std::vector<std::vector<std::string>>> trkToSegment =
155 m_doTable ? std::make_optional<std::vector<std::vector<std::string>>>(SurfDef::NumSurf * multiply, *segStation)
159 std::array<std::shared_ptr<const Trk::TrackParameters>, 2> trackAtMSEntrance;
162 for (
int i_extrapolations = 0; i_extrapolations < numberOfExtrapolations; ++i_extrapolations) {
166 std::vector<Intersection> intersections;
167 if (i_extrapolations == 0) {
172 trackAtMSEntrance[i_extrapolations] =
pars.uniqueClone();
173 ATH_MSG_DEBUG(
"Got MS entry pos: r " <<
pars.position().perp() <<
" z " <<
pars.position().z() <<
" momentum "
174 <<
pars.momentum().perp() <<
" cov " <<
pars.covariance());
178 intersections.clear();
180 if (!trackAtMSEntrance[i_extrapolations]) {
181 trackAtMSEntrance[i_extrapolations] =
185 if (!trackAtMSEntrance[i_extrapolations]) {
186 ATH_MSG_DEBUG(
"there is no track at MS entrance... not tagging for direction " << i_extrapolations);
191 std::shared_ptr<const Trk::TrackParameters> atSurface{trackAtMSEntrance[i_extrapolations]},
192 nextSurface{trackAtMSEntrance[i_extrapolations]};
193 bool barrel_extp{
false}, endcap_extp{
false};
195 ATH_MSG_DEBUG(
"Start extrapolation " << i_extrapolations <<
" found in total " << num_assoc_segs
196 <<
" associated segments.");
198 for (
auto& stat_pair : assocStat) {
199 const int surface_counter = stat_pair.first;
200 const int extrapolation_counter = i_extrapolations * SurfDef::NumSurf + surface_counter;
201 const std::vector<const Muon::MuonSegment*>& targets = stat_pair.second;
205 if (
m_doTable) (*didExtrapolate)[extrapolation_counter] =
"X";
207 std::optional<std::vector<std::string>> segVsSurf =
208 m_doTable ? std::make_optional<std::vector<std::string>>(num_assoc_segs,
"xxx") : std::nullopt;
211 const bool is_barrel = surface_counter < SurfDef::EIA;
215 if (!intersections.empty()) {
216 const bool is_aside = surface_counter < SurfDef::EIC;
218 Intersection best_intersec;
219 for (
const Intersection&
intersect : intersections) {
225 if (best_intersec.trackParameters) {
226 atSurface = best_intersec.trackParameters;
228 barrel_extp |= is_barrel;
229 endcap_extp |= !is_barrel;
230 ++m_recycledIntersect[surface_counter];
235 if (
m_doTable) (*didExtrapolate)[extrapolation_counter] =
"V";
240 if (!is_barrel && barrel_extp && !endcap_extp) {
241 atSurface = trackAtMSEntrance[i_extrapolations];
247 <<
", " << atSurface->position().z() <<
"), to surface "
248 <<
"(" << surface->globalReferencePoint().perp() <<
","
249 << surface->globalReferencePoint().z() <<
") "
252 nextSurface =
m_MuTagMatchingTool->ExtrapolateTrktoMSSurface(ctx, *surface, *atSurface, surf_dir);
254 ++m_extrapolated[surface_counter];
256 atSurface = nextSurface;
257 barrel_extp |= is_barrel;
258 endcap_extp |= !is_barrel;
260 if (
m_doTable) (*trkToSegment)[extrapolation_counter] = (*segVsSurf);
265 (*didExtrapolate)[extrapolation_counter] =
"S";
267 ++m_goodExtrapolated[surface_counter];
269 std::vector<SegmentExtrCache> seg_extps{};
270 seg_extps.reserve(targets.size());
272 int segmentCount{-1};
275 if (
m_doTable) { (*segStation)[segmentCount] =
" "; }
284 (*segVsSurf)[segmentCount] =
"surface";
287 ATH_MSG_VERBOSE(
"treating track " << trackCount <<
" (extrapolation = " << i_extrapolations <<
") and Segment "
288 << (*segStation)[segmentCount] <<
" (segment " << segmentCount <<
")");
291 (*segVsSurf)[segmentCount] =
"RghPhi";
297 (*segVsSurf)[segmentCount] =
"RghTheta";
302 (*segVsSurf)[segmentCount] =
"RghR";
308 ATH_MSG_DEBUG(
"bypassed roughEta/roughR cut since ID has no eta info!");
317 (*segVsSurf)[segmentCount] =
"posPhi";
319 (*segVsSurf)[segmentCount] =
"pos";
326 std::shared_ptr<const Trk::AtaPlane> atSegSurface;
328 std::vector<SegmentExtrCache>::const_iterator cache_itr = std::find_if(
329 seg_extps.begin(), seg_extps.end(),
330 [seg_ptr](
const SegmentExtrCache& cache) { return cache.segment_surface == &(seg_ptr->associatedSurface()); });
331 if (cache_itr != seg_extps.end()) {
332 atSegSurface = cache_itr->segment_pars;
339 << atSurface->position().z() <<
"), to segment "
340 <<
"(" << seg_ptr->globalPosition().perp() <<
"," << seg_ptr->globalPosition().z() <<
") "
342 atSegSurface =
m_MuTagMatchingTool->ExtrapolateTrktoSegmentSurface(ctx, *seg_ptr, *atSurface, seg_dir);
347 const AmgSymMatrix(5) invCov = atSegSurface->covariance()->inverse();
356 (*segVsSurf)[segmentCount] =
"posPhi";
358 (*segVsSurf)[segmentCount] =
"pos";
367 (*segVsSurf)[segmentCount] =
"dirPhi";
369 (*segVsSurf)[segmentCount] =
"dir";
377 if (
m_doTable) { (*segVsSurf)[segmentCount] =
"dist"; }
383 if (
m_doTable) { (*segVsSurf)[segmentCount] =
"cpull"; }
390 if (
m_doTable) { (*segVsSurf)[segmentCount] =
"ptpull"; }
394 if (
m_doTable) (*segVsSurf)[segmentCount] =
"TAG";
395 matchedSegment =
true;
396 ATH_MSG_DEBUG(
"Tagged the track with Segment " << segmentCount);
398 segmentsInfo.push_back(std::move(
info));
402 if (
m_doTable) (*trkToSegment)[extrapolation_counter] = (*segVsSurf);
409 if (!matchedSegment) {
410 ATH_MSG_DEBUG(
"ID " << std::setw(3) << trackCount <<
" could not be matched with any segment on any abstract surface");
419 if (!segmentsInfo.empty()) {
423 std::vector<MuonCombined::MuonSegmentInfo> segmentsInfoSolved =
425 segmentsInfoSelected.insert(segmentsInfoSelected.end(), std::make_move_iterator(segmentsInfoSolved.begin()),
426 std::make_move_iterator(segmentsInfoSolved.end()));
427 ATH_MSG_DEBUG(
"segmentsInfoSelected size " << segmentsInfoSelected.size());
432 ATH_MSG_DEBUG(
"segmentsInfoSelected size after track loop " << segmentsInfoSelected.size());
433 std::vector<MuonCombined::MuonSegmentInfo> segmentsInfoFinal =
435 ATH_MSG_DEBUG(
"segmentsInfoFinal size " << segmentsInfoFinal.size());
438 for (
unsigned int ns1 = 0; ns1 < segmentsInfoFinal.size(); ++ns1) {
441 else if (segmentsInfoFinal[ns1].
track != segmentsInfoFinal[ns1 - 1].
track)
449 std::vector<MuonCombined::MuonSegmentInfo> segmentsInfoTag;
450 segmentsInfoTag.reserve(segmentsInfoFinal.size());
452 for (
unsigned int ns1 = 0; ns1 < segmentsInfoFinal.size(); ++ns1) {
453 if (segmentsInfoFinal[ns1].
track ==
track && segmentsInfoFinal[ns1].nsegments > 0) {
454 segmentsInfoTag.push_back(segmentsInfoFinal[ns1]);
457 if (segmentsInfoTag.empty())
continue;
465 const std::vector<std::vector<std::string>>& segToSurf)
const {
467 <<
"EX? (o: no extrap, X: extrap failed, V: extrap OK)");
470 for (
unsigned int segment_counter = 0; segment_counter < segStation.size(); ++segment_counter) {
475 unsigned int extrapolation_counter(0);
476 std::string signstr(
"");
482 << didEx[extrapolation_counter];
483 for (
unsigned int segment_counter = 0; segment_counter < segStation.size(); ++segment_counter) {
487 ++extrapolation_counter;
495 << didEx[extrapolation_counter];
496 for (
unsigned int segment_counter = 0; segment_counter < segStation.size(); ++segment_counter) {
500 ++extrapolation_counter;
505 const std::vector<const Muon::MuonSegment*>& segments)
const {
510 std::vector<const Muon::MuonSegment*> FilteredSegmentCollection;
511 FilteredSegmentCollection.reserve(segments.size());
538 if (std::abs(stationEta) != 1) {
549 FilteredSegmentCollection.emplace_back(itSeg);
551 return FilteredSegmentCollection;
554 const std::vector<const Muon::MuonSegment*>& filteredSegments)
const {
560 std::vector<const Muon::MuonSegment*>& surf_vec = sortedSegments[surf_def];
561 if (surf_vec.empty()) surf_vec.reserve(filteredSegments.size());
562 surf_vec.push_back(itSeg);
564 return sortedSegments;
570 bool hasAngleMatch{
false}, hasMatch{
false};
574 const double qID =
track->perigeeParameters()->charge();
575 const double pID = id_mom.mag();
577 if (pID <= 20000. * (qID * id_mom.eta() - 2)) {
return sortedSegments; }
581 const double ThetaID = (ms_entry ? ms_entry->
position() : id_mom).
theta();
583 std::vector<int> id_sectors;
585 auto sector_match = [&,
this](
const Amg::Vector3D& seg_pos) ->
bool {
586 if (!ms_entry)
return std::abs(qID * seg_pos.deltaPhi(id_mom) - qID / pID) < 0.6;
587 std::vector<int> seg_sectors;
589 return std::find_if(id_sectors.begin(), id_sectors.end(), [&seg_sectors](
const int id_sec) {
590 return std::find(seg_sectors.begin(), seg_sectors.end(), id_sec) != seg_sectors.end();
591 }) != id_sectors.end();
594 for (
const auto& key_pair : filteredSegments) {
595 const int surf_def = key_pair.first;
596 const std::vector<const Muon::MuonSegment*>& source_vec = key_pair.second;
597 std::vector<const Muon::MuonSegment*> target_vec;
598 target_vec.reserve(source_vec.size());
601 const double dTheta =
pos.theta() - ThetaID;
602 const bool theta_match = ms_entry ? std::abs(dTheta) < 0.2 : (qID * dTheta < 0.2 && qID * dTheta > -0.6);
607 if (!sector_match(
pos)) {
611 hasAngleMatch =
true;
614 target_vec.push_back(itSeg);
616 if (target_vec.empty())
continue;
617 sortedSegments[surf_def] = std::move(target_vec);
623 sortedSegments.clear();
624 return sortedSegments;