ATLAS Offline Software
Loading...
Searching...
No Matches
L1Muon::L1TGC::FloatingStationCoincidenceBuilder Class Reference

Build station representative points from layer-level TGC hits. More...

#include <FloatingStationCoincidenceBuilder.h>

Collaboration diagram for L1Muon::L1TGC::FloatingStationCoincidenceBuilder:

Public Member Functions

StatusCode build (const FloatingHitGroups &hitGroups, FloatingStationCoincidenceContainer &coincidences) const

Static Private Member Functions

static std::uint8_t nominalLayers (FloatingStation station, bool isStrip)

Detailed Description

Build station representative points from layer-level TGC hits.

Definition at line 13 of file FloatingStationCoincidenceBuilder.h.

Member Function Documentation

◆ build()

StatusCode L1Muon::L1TGC::FloatingStationCoincidenceBuilder::build ( const FloatingHitGroups & hitGroups,
FloatingStationCoincidenceContainer & coincidences ) const

Definition at line 58 of file FloatingStationCoincidenceBuilder.cxx.

60 {
61 coincidences.clear();
62
63 for (const auto& [key, groupHits] : hitGroups) {
64 std::array<std::array<std::vector<const Hit*>, 2>, 3> grouped{};
65 for (const Hit& hit : groupHits) {
66 if (!isBigWheelStation(hit.station)) continue;
67 grouped[stationIndex(hit.station)][hit.isStrip ? 1U : 0U].emplace_back(&hit);
68 }
69
70 for (std::size_t stationPosition = 0U; stationPosition < grouped.size();
71 ++stationPosition) {
72 const Station hitStation = static_cast<Station>(stationPosition);
73 for (std::size_t projection = 0U; projection < 2U; ++projection) {
74 const bool isStrip = projection == 1U;
75 std::vector<const Hit*>& hits = grouped[stationPosition][projection];
76 if (hits.empty()) continue;
77
78 std::sort(hits.begin(), hits.end(),
79 [](const Hit* lhs, const Hit* rhs) {
80 if (lhs->channel != rhs->channel) {
81 return lhs->channel < rhs->channel;
82 }
83 if (lhs->gasGap != rhs->gasGap) {
84 return lhs->gasGap < rhs->gasGap;
85 }
86 if (lhs->stationEta != rhs->stationEta) {
87 return lhs->stationEta < rhs->stationEta;
88 }
89 return lhs->stationPhi < rhs->stationPhi;
90 });
91
92 std::vector<const Hit*> cluster;
93 auto flushCluster = [&]() {
94 if (cluster.empty()) return;
95
96 std::uint32_t channelSum = 0U;
97 std::uint8_t layerMask = 0U;
98 float etaSum = 0.F;
99 float sinPhiSum = 0.F;
100 float cosPhiSum = 0.F;
101 float rSum = 0.F;
102 float zSum = 0.F;
103 for (const Hit* hit : cluster) {
104 channelSum += hit->channel;
105 if (hit->gasGap > 0U && hit->gasGap <= 3U) {
106 layerMask |= static_cast<std::uint8_t>(1U << (hit->gasGap - 1U));
107 }
108 etaSum += hit->eta;
109 sinPhiSum += std::sin(hit->phi);
110 cosPhiSum += std::cos(hit->phi);
111 rSum += hit->r;
112 zSum += hit->z;
113 }
114
115 const std::uint8_t observedLayers = static_cast<std::uint8_t>(
116 std::popcount(static_cast<unsigned int>(layerMask)));
117 if (observedLayers == 0U) {
118 cluster.clear();
119 return;
120 }
121
122 const std::uint16_t representativeChannel =
123 static_cast<std::uint16_t>(std::lround(
124 static_cast<double>(channelSum) /
125 static_cast<double>(cluster.size())));
126 const Hit* representativeHit = nullptr;
127 for (const Hit* hit : cluster) {
128 if (betterRepresentativeHit(hit, representativeHit,
129 representativeChannel)) {
130 representativeHit = hit;
131 }
132 }
133 if (representativeHit == nullptr) {
134 cluster.clear();
135 return;
136 }
137
138 const float scale = 1.F / static_cast<float>(cluster.size());
139 coincidences.emplace_back(
140 key, hitStation, isStrip, representativeHit->detectorSector,
141 representativeHit->stationEta, representativeHit->stationPhi,
142 representativeChannel, layerMask, observedLayers,
143 nominalLayers(hitStation, isStrip), etaSum * scale,
144 std::atan2(sinPhiSum, cosPhiSum), rSum * scale, zSum * scale);
145 cluster.clear();
146 };
147
148 std::uint16_t previousChannel = 0U;
149 bool hasPreviousChannel = false;
150 for (const Hit* hit : hits) {
151 if (!hasPreviousChannel ||
152 std::abs(static_cast<int>(hit->channel) -
153 static_cast<int>(previousChannel)) <= 1) {
154 cluster.emplace_back(hit);
155 } else {
156 flushCluster();
157 cluster.emplace_back(hit);
158 }
159 previousChannel = hit->channel;
160 hasPreviousChannel = true;
161 }
162 flushCluster();
163 }
164 }
165 }
166
167 std::sort(coincidences.begin(), coincidences.end(),
168 [](const FloatingStationCoincidence& lhs,
169 const FloatingStationCoincidence& rhs) {
170 if (lhs.key.tie() != rhs.key.tie()) {
171 return lhs.key.tie() < rhs.key.tie();
172 }
173 if (lhs.station != rhs.station) return lhs.station < rhs.station;
174 if (lhs.isStrip != rhs.isStrip) return lhs.isStrip < rhs.isStrip;
175 if (lhs.observedLayers != rhs.observedLayers) {
176 return lhs.observedLayers > rhs.observedLayers;
177 }
178 return lhs.channel < rhs.channel;
179 });
180 return StatusCode::SUCCESS;
181}
bool hit(const Container &ids, int pdgId)
if(pathvar)
static std::uint8_t nominalLayers(FloatingStation station, bool isStrip)
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.

◆ nominalLayers()

std::uint8_t L1Muon::L1TGC::FloatingStationCoincidenceBuilder::nominalLayers ( FloatingStation station,
bool isStrip )
staticprivate

Definition at line 48 of file FloatingStationCoincidenceBuilder.cxx.

49 {
50 if (station == Station::M1 && !isStrip) return 3U;
51 if (station == Station::M1 || station == Station::M2 ||
52 station == Station::M3) {
53 return 2U;
54 }
55 return 0U;
56}

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