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);
70 for (std::size_t stationPosition = 0U; stationPosition < grouped.size();
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;
79 [](
const Hit* lhs,
const Hit* rhs) {
80 if (lhs->channel != rhs->channel) {
81 return lhs->channel < rhs->channel;
83 if (lhs->gasGap != rhs->gasGap) {
84 return lhs->gasGap < rhs->gasGap;
86 if (lhs->stationEta != rhs->stationEta) {
87 return lhs->stationEta < rhs->stationEta;
89 return lhs->stationPhi < rhs->stationPhi;
92 std::vector<const Hit*> cluster;
93 auto flushCluster = [&]() {
94 if (cluster.empty())
return;
96 std::uint32_t channelSum = 0U;
97 std::uint8_t layerMask = 0U;
99 float sinPhiSum = 0.F;
100 float cosPhiSum = 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));
109 sinPhiSum += std::sin(
hit->phi);
110 cosPhiSum += std::cos(
hit->phi);
115 const std::uint8_t observedLayers =
static_cast<std::uint8_t
>(
116 std::popcount(
static_cast<unsigned int>(layerMask)));
117 if (observedLayers == 0U) {
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;
133 if (representativeHit ==
nullptr) {
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,
144 std::atan2(sinPhiSum, cosPhiSum), rSum * scale, zSum * scale);
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);
157 cluster.emplace_back(
hit);
159 previousChannel =
hit->channel;
160 hasPreviousChannel =
true;
167 std::sort(coincidences.begin(), coincidences.end(),
170 if (lhs.key.tie() != rhs.key.tie()) {
171 return lhs.key.tie() < rhs.key.tie();
176 return lhs.observedLayers > rhs.observedLayers;
180 return StatusCode::SUCCESS;