12 inline std::vector<std::shared_ptr<unsigned>> matchCountVec(
unsigned int n) {
13 std::vector<std::shared_ptr<unsigned>>
out{};
15 for (
unsigned int p = 0;
p <
n ;++
p) {
16 out.emplace_back(std::make_shared<unsigned>(0));
25 return static_cast<int>(
techIdx) <
static_cast<int>(
other.techIdx);
28 return static_cast<int>(
stIdx) <
static_cast<int>(
other.stIdx);
33 return measEta + measPhi + measEtaPhi;
39 std::lock_guard guard{m_mutex};
46 if (sp.measuresEta() && sp.measuresPhi()) {
49 stats.measEta += sp.measuresEta();
50 stats.measPhi += sp.measuresPhi();
55 using KeyVal = std::pair<FieldKey, StatField>;
56 std::vector<KeyVal> sortedstats{};
57 sortedstats.reserve(m_map.size());
59 for (
const auto & [
key,
stats] : m_map){
60 sortedstats.emplace_back(std::make_pair(
key,
stats));
62 std::stable_sort(sortedstats.begin(), sortedstats.end(), [](
const KeyVal&
a,
const KeyVal&
b) {
63 return a.second.allHits() > b.second.allHits();
65 msg<<
MSG::ALWAYS<<
"###########################################################################"<<
endmsg;
66 for (
const auto & [
key,
stats] : sortedstats) {
69 <<
" "<<std::abs(
key.eta)<<(
key.eta < 0 ?
"A" :
"C")
70 <<
" "<<std::setw(8)<<
stats.measEtaPhi
71 <<
" "<<std::setw(8)<<
stats.measEta
74 msg<<
MSG::ALWAYS<<
"###########################################################################"<<
endmsg;
85 m_statCounter->dumpStatisics(msgStream());
87 return StatusCode::SUCCESS;
99 return StatusCode::SUCCESS;
104 const std::vector<const xAOD::TgcStrip*>& phiHits)
const {
105 if (etaHits.empty() || phiHits.empty()) {
110 return ((1.*etaHits.size()) / ((1.*
re->numChannels(etaHits[0]->measurementHash())))) <
m_maxOccTgcEta &&
111 ((1.*phiHits.size()) / ((1.*
re->numChannels(phiHits[0]->measurementHash())))) <
m_maxOccTgcPhi;
115 const std::vector<const xAOD::RpcMeasurement*>& phiHits)
const {
116 if (etaHits.empty() || phiHits.empty()) {
127 const std::vector<const xAOD::sTgcMeasurement*>& phiHits)
const {
128 if (etaHits.empty() || phiHits.empty()) {
132 return ((1.*etaHits.size()) / (1.*
re->numStrips(etaHits[0]->gasGap()))) <
m_maxOccStgcEta &&
133 ((1.*phiHits.size()) / (1.*
re->numWireGroups(phiHits[0]->gasGap()))) <
m_maxOccStgcPhi;
136 template <
class ContType>
141 ATH_MSG_DEBUG(
"Key "<<
typeid(ContType).
name()<<
" not set. Do not fill anything");
142 return StatusCode::SUCCESS;
146 if (readHandle->empty()){
148 return StatusCode::SUCCESS;
153 using PrdType =
typename ContType::const_value_type;
154 using PrdVec = std::vector<PrdType>;
160 if constexpr( std::is_same_v<ContType, xAOD::MdtDriftCircleContainer> ||
161 std::is_same_v<ContType, xAOD::MMClusterContainer>) {
163 pointsInChamb.
etaHits.reserve(pointsInChamb.
etaHits.capacity() + viewer.size());
164 for (
const PrdType prd: viewer) {
166 <<
", hash: "<<prd->identifierHash());
167 pointsInChamb.
etaHits.emplace_back(*gctx, prd,
nullptr);
171 using EtaPhiHits = std::array<PrdVec, 2>;
172 std::vector<EtaPhiHits> hitsPerGasGap{};
173 for (
const PrdType prd : viewer) {
176 unsigned int gapIdx = prd->gasGap() -1;
177 if constexpr (std::is_same_v<ContType, xAOD::RpcMeasurementContainer>) {
178 gapIdx = prd->readoutElement()->createHash(0, prd->gasGap(), prd->doubletPhi(),
false);
182 if constexpr(std::is_same_v<ContType, xAOD::sTgcMeasContainer>) {
184 if (prd->channelType() == sTgcIdHelper::sTgcChannelTypes::Pad) {
185 pointsInChamb.
etaHits.emplace_back(*gctx, prd,
nullptr);
189 measPhi = prd->channelType() == sTgcIdHelper::sTgcChannelTypes::Wire;
192 measPhi = prd->measuresPhi();
195 if (hitsPerGasGap.size() <= gapIdx) {
196 hitsPerGasGap.resize(gapIdx + 1);
199 PrdVec& toPush = hitsPerGasGap[gapIdx][measPhi];
200 if (toPush.capacity() == toPush.size()) {
203 toPush.push_back(prd);
206 for (
auto& [etaHits, phiHits] : hitsPerGasGap) {
208 ATH_MSG_VERBOSE(
"Occupancy cut not passed "<<etaHits.size()<<
", "<<phiHits.size());
209 pointsInChamb.
etaHits.reserve(pointsInChamb.
etaHits.size() + etaHits.size());
210 pointsInChamb.
phiHits.reserve(pointsInChamb.
phiHits.size() + phiHits.size());
211 for (
const PrdType etaPrd : etaHits) {
212 pointsInChamb.
etaHits.emplace_back(*gctx, etaPrd);
217 for (
const PrdType phiPrd : phiHits) {
218 pointsInChamb.
phiHits.emplace_back(*gctx, phiPrd);
224 std::vector<std::shared_ptr<unsigned>> etaCounts{matchCountVec(etaHits.size())},
225 phiCounts{matchCountVec(phiHits.size())};
226 pointsInChamb.
etaHits.reserve(etaHits.size()*phiHits.size());
228 for (
unsigned int etaP = 0; etaP < etaHits.size(); ++etaP) {
230 for (
unsigned int phiP = 0; phiP < phiHits.size(); ++ phiP) {
233 if (!(etaHits[etaP]->bcBitMap() & phiHits[phiP]->bcBitMap())){
237 SpacePoint& spacePoint{pointsInChamb.
etaHits.emplace_back(*gctx, etaHits[etaP], phiHits[phiP])};
240 spacePoint.setInstanceCounts(etaCounts[etaP], phiCounts[phiP]);
242 if (!(*etaCounts[etaP])) {
243 pointsInChamb.
etaHits.emplace_back(*gctx, etaHits[etaP]);
249 for (
unsigned int phiP = 0; phiP < phiHits.size(); ++ phiP){
250 if (!(*phiCounts[phiP])) {
251 pointsInChamb.
phiHits.emplace_back(*gctx, phiHits[phiP]);
256 }
while (viewer.next());
257 return StatusCode::SUCCESS;
268 std::unique_ptr<SpacePointContainer> outContainer = std::make_unique<SpacePointContainer>();
270 for (
auto &[
chamber, hitsPerChamber] : preSortedContainer){
275 ATH_CHECK(writeHandle.record(std::move(outContainer)));
276 return StatusCode::SUCCESS;
283 splittedHits.emplace_back();
285 m_statCounter->addToStat(hitsPerChamber.etaHits);
286 m_statCounter->addToStat(hitsPerChamber.phiHits);
293 if (bucket.size() > 1)
294 finalContainer.
push_back(std::make_unique<SpacePointBucket>(std::move(bucket)));
299 std::vector<SpacePoint>&& spacePoints,
302 if (spacePoints.empty())
return;
304 const bool defineBuckets = splittedHits[0].empty();
305 const bool hasEtaMeas{spacePoints[0].measuresEta()};
307 auto pointPos = [hasEtaMeas, defineBuckets] (
const SpacePoint&
p) {
308 return hasEtaMeas || !defineBuckets ?
p.positionInChamber().y() :
p.positionInChamber().x();
312 auto channelDir = [hasEtaMeas, defineBuckets, &gctx](
const SpacePoint &
p) {
314 return std::abs(hasEtaMeas || !defineBuckets ?
d.y() :
d.z());
317 std::sort(spacePoints.begin(), spacePoints.end(),
319 return pointPos(a) < pointPos(b);
323 double lastPoint = pointPos(spacePoints[0]);
325 auto newBucket = [
this, &lastPoint, &splittedHits, &pointPos, &channelDir] (
const double currPos) {
326 splittedHits.emplace_back();
327 splittedHits.back().setBucketId(splittedHits.size() -1);
331 for (
const std::shared_ptr<SpacePoint>& pointInBucket : overlap) {
332 const double overlapPos = pointPos(*pointInBucket) + pointInBucket->uncertainty()[1] * channelDir(*pointInBucket);
334 newContainer.push_back(pointInBucket);
337 lastPoint = newContainer.empty() ? currPos : pointPos(**newContainer.begin());
338 overlap.setCoveredRange(pointPos(**overlap.begin()), pointPos(**overlap.rbegin()));
339 overlap.populateChamberLocations();
343 const double currPoint = pointPos(toSort);
345 if (!defineBuckets) {
346 std::shared_ptr<SpacePoint> madePoint = std::make_shared<SpacePoint>(std::move(toSort));
348 const double measDir = channelDir(toSort);
349 const double posMin = currPoint - toSort.uncertainty()[1] * measDir;
350 const double posMax = currPoint + toSort.uncertainty()[1] * measDir;
352 if (posMax >= bucket.coveredMin() && bucket.coveredMax() >= posMin) {
353 bucket.push_back(madePoint);
359 if (currPoint - lastPoint >
m_maxBucketLength || (!splittedHits.empty() && !splittedHits.back().empty() && currPoint - pointPos(*splittedHits.back().back()) >
m_spacePointWindow )) {
360 newBucket(currPoint);
362 std::shared_ptr<SpacePoint> spacePoint = std::make_shared<SpacePoint>(std::move(toSort));
363 splittedHits.back().emplace_back(spacePoint);
364 if (splittedHits.size() > 1) {
366 const double overlapPos = currPoint - spacePoint->uncertainty()[1] * channelDir(*spacePoint);
368 overlap.push_back(spacePoint);
374 newBucket(pointPos(*lastBucket.back()));
376 splittedHits.pop_back();