10#include "GaudiKernel/SystemOfUnits.h"
14#include "Acts/Utilities/MathHelpers.hpp"
22 constexpr double kBunchSpacing = 25. * Gaudi::Units::ns;
37 return StatusCode::SUCCESS;
55 unsigned int nCollections{0}, nHitsTotal{0};
58 std::vector<MMT_Hit> ev_hits;
59 double tanStereoAngle{0.};
60 unsigned int nOutOfRange{0}, nNegTime{0}, nInfSlope{0};
63 for (
const MmDigit* digit : *digitCollection) {
69 const int channel = idHelper.
channel(
id);
76 const int firstStrip = readout->
firstStrip(layHash);
77 const int numStrips = readout->
numStrips(layHash);
80 tanStereoAngle = std::max(tanStereoAngle, std::tan(std::abs(design.
stereoAngle())));
81 if (channel < firstStrip || channel >= firstStrip + numStrips) {
84 <<
" allowed [" << firstStrip <<
", " << firstStrip + numStrips - 1 <<
"]");
88 const float stripTime = digit->stripResponseTime();
94 const int BC =
static_cast<int>(std::ceil(stripTime / kBunchSpacing));
95 ev_hits.emplace_back(
id, stripTime, BC,
m_detMgr, *gctx);
97 if (ev_hits.back().infSlope()) {
103 if (!firstHitId.
is_valid()) firstHitId = id;
109 info.stationEta =
h.getStationEta();
110 info.stationPhi =
h.getStationPhi();
111 info.sectorPhi =
h.getSectorPhi();
112 info.sector =
h.getSector();
113 info.plane =
h.getPlane();
114 info.strip =
h.getChannel();
115 info.VMM =
h.getVMM();
116 info.ART =
h.getART();
118 info.time =
h.getTime();
121 info.RZslope =
h.getRZSlope();
122 info.shift =
h.getShift();
126 if (ev_hits.empty() && nOutOfRange == 0)
continue;
128 nHitsTotal += ev_hits.size();
131 <<
": " << ev_hits.size() <<
" hits"
132 <<
" (dropped: out-of-range " << nOutOfRange <<
", negative time " << nNegTime
133 <<
", inf slope " << nInfSlope <<
")");
138 <<
", less than X+UV threshold, skipping digit collection");
142 const bool isLarge = std::ranges::all_of(ev_hits, [](
const auto&
hit) {
return hit.getSector() ==
'L'; });
143 const SideType side = std::ranges::all_of(ev_hits, [](
const auto&
hit) {
return hit.getStationEta() < 0; })
145 const int sectorPhi = ev_hits[0].getSectorPhi();
146 const bool allSectorPhi = std::ranges::all_of(ev_hits,
147 [&](
const auto&
hit) {
return hit.getSectorPhi() == sectorPhi; });
149 ATH_MSG_ERROR(
"Available digits belongs to different sectors IDs, unable to assign an unique ID");
150 return StatusCode::FAILURE;
152 const bool isEta1 = std::ranges::all_of(ev_hits,
153 [](
const auto&
hit) {
return std::abs(
hit.getStationEta()) == 1; });
156 std::vector<MMT_Road> ev_roads;
157 m_diamond->createRoads(ev_roads, isLarge, isEta1);
160 std::vector<slope_t> diamondSlopes;
161 m_diamond->findDiamonds(ev_hits, ev_roads, diamondSlopes, sectorPhi, tanStereoAngle);
162 ATH_MSG_DEBUG(
" -> " << diamondSlopes.size() <<
" coincidence(s) in sector " << sectorPhi << side);
163 if (diamondSlopes.empty())
continue;
164 if (
debug)
debug->nTrig.push_back(diamondSlopes.size());
171 const double sectorCentrePhi = stationEl->
center(*gctx).phi();
173 for (
const slope_t& slope : diamondSlopes) {
178 cand.
eta = slope.eta;
179 cand.
phi = slope.phi;
180 cand.
phiShf = slope.phiShf;
183 cand.
dtheta = slope.dtheta;
184 cand.
lowRes = slope.lowRes;
185 cand.
iX = slope.iRoad;
186 cand.
iU = slope.iRoadu;
187 cand.
iV = slope.iRoadv;
188 cand.
nHits = slope.totalCount;
190 cand.
sector = isLarge ?
'L' :
'S';
191 cand.
xCount = slope.xCount;
192 cand.
uCount = slope.uCount;
193 cand.
age = slope.age;
196 cand.
mxl = slope.mxl;
197 cand.
uavg = slope.uavg;
198 cand.
vavg = slope.vavg;
199 cand.
theta = slope.theta;
204 ATH_MSG_DEBUG(
"MM trigger: " << nHitsTotal <<
" hits in " << nCollections
205 <<
" digit collections -> " << candidates.size() <<
" candidates");
206 return StatusCode::SUCCESS;
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
Handle class for reading from StoreGate.
Header file for AthHistogramAlgorithm.
This is a "hash" representation of an Identifier.
bool is_valid() const
Check if id is in a valid state.
One MM strip hit as seen by the MM trigger processor.
Use IdentifiableContainer with MmDigitCollection.
int channel(const Identifier &id) const override
const StripLayer & stripLayer(const Identifier &measId) const
unsigned int numStrips(const IdentifierHash &layerHash) const
Returns the number of total active strips.
IdentifierHash layerHash(const Identifier &measId) const override final
The layer hash removes the bits from the IdentifierHash corresponding to the measurement's channel nu...
unsigned int firstStrip(const IdentifierHash &layerHash) const
Returns the first active strip.
Amg::Vector3D center(const ActsTrk::GeometryContext &ctx) const
Returns the geometrical center point of the readout element.
double stereoAngle() const
Returns the value of the stereo angle.
const StripDesign & design(bool phiView=false) const
Returns the underlying strip design.
Definitions shared by the classes of the MM trigger processor emulation.
SideType
Detector side. The value is the sign of z, so that it can be used as a sign (e.g. Acts::copySign).
double wrapTwoPi(double phi)
Map any angle to [0, 2pi).
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
One MM trigger candidate (one road that passed the coincidence), before any quantisation into the Run...
double phiGlobal
Global phi in [0, 2pi): sector centre phi from the geometry -/+ local phi.
unsigned int xCount
X hits in the road.
int sectorPhi
Trigger sector 1-16 (Athena MM sector convention).
double dtheta
Angle w.r.t. the infinite-momentum track [rad].
int age
BC of the candidate relative to the start of the processing window.
double vavg
Average R/Z slope of the V hits.
double mx
phi-sensitive slope, from the U and V slopes
double phi
Local phi (relative to the sector centre).
unsigned int uCount
U hits in the road.
bool lowRes
Not all 8 planes in the road (Run 3 flag, not part of the Run 4 word).
int BC
Bunch crossing of the candidate (mode of the hit BCs, as Run 3).
double secCentrePhi
Sector centre phi from the Phase-II geometry.
double phiShf
Global phi as computed in Run 3 (MMT_Diamond::phiShift), for comparison.
double my
Average R/Z slope of the X hits.
double mxl
Local slope, R vs Z fit of the X hits.
unsigned int nHits
Hits in the road (Run 3 slope.totalCount).
double uavg
Average R/Z slope of the U hits.
double eta
Global eta of the segment.
SideType side
A (z>0) or C (z<0).
double theta
Polar angle of the candidate [rad].
Extra information returned by runTrigger on request (used by the validation algorithm).
One MM trigger hit, for the validation ntuple only (MM_* hit branches).
One MM trigger candidate as found by MMT_Diamond::findDiamonds: road indices, hit counts,...