ATLAS Offline Software
Loading...
Searching...
No Matches
TriggerChamberClusterOnTrackCreator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <functional>
8#include <ranges>
9
20
21namespace Muon {
22
24 ATH_CHECK(m_idHelperSvc.retrieve());
25 ATH_CHECK(m_clusterCreator.retrieve());
26 return StatusCode::SUCCESS;
27}
28
29std::unique_ptr<CompetingMuonClustersOnTrack>
31 const std::list<const Trk::PrepRawData*>& prds, const double) const {
32 ATH_MSG_VERBOSE("enter createBroadCluster: number of prds " << prds.size());
33
34 // make some PRD consistency checks
35 if (prds.empty()) {
36 ATH_MSG_WARNING("fails: empty PRD list ");
37 return nullptr;
38 }
39 const Trk::TrkDetElementBase* detectorElement = (*prds.front()).detectorElement();
40 Identifier channelId = (*prds.front()).identify();
41 const bool isRpc = m_idHelperSvc->isRpc(channelId);
42 const bool isTgc = m_idHelperSvc->isTgc(channelId);
43 if (!isRpc && !isTgc) {
44 ATH_MSG_WARNING("fails: PRD must be from rpc or tgc ");
45 return nullptr;
46 }
47
48 const bool measuresPhi = m_idHelperSvc->measuresPhi(channelId);
49 for (const Trk::PrepRawData* prd : prds) {
50 channelId = prd->identify();
51 if (m_idHelperSvc->measuresPhi(channelId) != measuresPhi) {
52 ATH_MSG_WARNING("fails: PRDs must measure same coordinate ");
53 return nullptr;
54 }
55 if (prd->detectorElement() != detectorElement) {
56 ATH_MSG_WARNING("fails: PRDs must be from same detectorElement ");
57 return nullptr;
58 }
59 ATH_MSG_VERBOSE("Create trigger prd from "
60 << m_idHelperSvc->toString(channelId)
61 << ", nDim: " << prd->localCovariance().rows());
62 }
63
64 // create a rot for each prd (which gets weight zero)
65 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>> rots = createPrdRots(prds);
66 auto assocProbs = std::vector<double>(rots.size(), 0.);
67
68 // for each surface, find the first and last rot forming the cluster
69 std::list<int> limitingChannels;
70 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>> limitingRots;
71 makeClustersBySurface(limitingChannels, limitingRots, prds, rots);
72
73 // cluster consistency - discard any surfaces not contributing to the final cluster
74 applyClusterConsistency(limitingChannels, limitingRots);
75
76 // overall localPosition, error matrix and surface
77 Trk::LocalParameters parameters{};
78 Amg::MatrixX errorMatrix{};
79 std::unique_ptr<Trk::Surface> surface{};
80 makeOverallParameters(parameters, errorMatrix, surface, limitingChannels,
81 limitingRots);
82
83 // clear lists
84 limitingChannels.clear();
85
86 // return the competingMuonClusterOnTrack object containing the final parameters,
87 // error matrix, surface, list of rots and weights
88 return std::make_unique<CompetingMuonClustersOnTrack>(
89 std::move(parameters), std::move(errorMatrix), surface.release(),
90 std::move(rots), std::move(assocProbs));
91}
92
94 std::list<int>& limitingChannels,
95 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>>& limitingRots) const {
96 // remove any clusters that will NOT contribute to the final cluster
97 int numClusters = limitingChannels.size() / 2;
98 int sizeMax = 0;
99 int sizeMin = 999;
100 for (std::list<int>::iterator l = limitingChannels.begin();
101 l != limitingChannels.end() &&
102 l != std::prev(limitingChannels.end());) {
103 int end = *l++;
104 int beg = *l++;
105 int size = std::abs(end - beg);
106 sizeMax = std::max(sizeMax, size);
107 sizeMin = std::min(sizeMin, size);
108 }
109
110 std::list<int>::iterator discard = limitingChannels.end();
111 for (std::list<int>::iterator l = limitingChannels.begin();
112 l != limitingChannels.end() &&
113 l != std::prev(limitingChannels.end());) {
114 std::list<int>::iterator first = l;
115 int end = *l++;
116 int beg = *l++;
117 int size = std::abs(end - beg);
118 if (m_chooseBroadestCluster && size < sizeMax) {
119 discard = first;
120 }
121 if (!m_chooseBroadestCluster && size > sizeMin) {
122 discard = first;
123 }
124 }
125 if (discard == limitingChannels.begin()) {
126 ATH_MSG_VERBOSE(" discard cluster #" << 1);
127 limitingRots.erase(limitingRots.begin());
128 limitingRots.erase(limitingRots.begin());
129 limitingChannels.pop_front();
130 limitingChannels.pop_front();
131 } else if (discard != limitingChannels.end()) {
132 ATH_MSG_VERBOSE(" discard cluster #" << numClusters);
133 limitingRots.pop_back();
134 limitingRots.pop_back();
135 limitingChannels.pop_back();
136 limitingChannels.pop_back();
137 }
138}
139
140std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>>
142 const std::list<const Trk::PrepRawData*>& prds) const {
143 // create clusterRot for each PRD
144 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>> rots{};
145 if (prds.empty()) {
146 ATH_MSG_WARNING("empty PRD list ");
147 return rots;
148 }
149 std::optional<int> dim{};
150 for (const Trk::PrepRawData* prd : prds) {
151 Identifier id = prd->identify();
152 const Trk::TrkDetElementBase* detectorElement = prd->detectorElement();
153 const Amg::Vector3D globalPosition = detectorElement->center(id);
154 std::unique_ptr<const Muon::MuonClusterOnTrack> cluster{
155 m_clusterCreator->createRIO_OnTrack(*prd, globalPosition)};
156 if (!cluster) {
157 ATH_MSG_WARNING("Cannot create a ROT from "
158 << m_idHelperSvc->toString(id) << ".");
159 continue;
160 }
161 if (!dim) {
162 dim = cluster->localCovariance().cols();
163 } else if ((*dim) != cluster->localCovariance().cols()) {
164 ATH_MSG_WARNING("The covariance dimension of "<<m_idHelperSvc->toString(id)
165 <<" does not match "<<(*dim));
166 continue;
167 }
168 rots.push_back(std::move(cluster));
169 }
170 return rots;
171}
172
174 std::list<int>& limitingChannels,
175 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>>& limitingRots,
176 const std::list<const Trk::PrepRawData*>& prds,
177 const std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>>& rots) const {
178 if (prds.empty()) {
179 ATH_MSG_WARNING("makeClustersBySurface- empty PRD list ");
180 return;
181 }
182 std::unordered_set<const Trk::PrepRawData*> usedPrd;
183 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>>::const_iterator r = rots.begin();
184 for (std::list<const Trk::PrepRawData*>::const_iterator p = prds.begin();
185 p != prds.end(); ++p, ++r) {
186
187 const Trk::PrepRawData* prd{*p};
188 if (!usedPrd.insert(prd).second) {
189 continue;
190 }
191 int channel = 0;
192 int gasGap = 0;
193 const Identifier channelId = prd->identify();
194 const bool isRpc = m_idHelperSvc->isRpc(channelId);
195 if (isRpc) {
196 gasGap = m_idHelperSvc->rpcIdHelper().gasGap(channelId);
197 channel = m_idHelperSvc->rpcIdHelper().strip(channelId);
198 } else {
199 gasGap = m_idHelperSvc->tgcIdHelper().gasGap(channelId);
200 channel = m_idHelperSvc->tgcIdHelper().channel(channelId);
201 }
202 int channelMax = channel;
203 int channelMin = channel;
204 const Muon::MuonClusterOnTrack *rotMax{r->get()}, *rotMin{r->get()};
205 std::list<const Trk::PrepRawData*>::const_iterator q = p;
206 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>>::const_iterator s = r;
207 for (++q, ++s; q != prds.end(); ++q, ++s) {
208 const Identifier channelId1 = (**q).identify();
209 if ((isRpc && m_idHelperSvc->rpcIdHelper().gasGap(channelId1) != gasGap) ||
210 (!isRpc && m_idHelperSvc->tgcIdHelper().gasGap(channelId1) != gasGap)) {
211 continue;
212 }
213 usedPrd.insert(*q);
214 if (isRpc) {
215 channel = m_idHelperSvc->rpcIdHelper().strip(channelId1);
216 } else {
217 channel = m_idHelperSvc->tgcIdHelper().channel(channelId1);
218 }
219 if (channel > channelMax) {
220 channelMax = channel;
221 rotMax = s->get();
222 }
223 if (channel < channelMin) {
224 channelMin = channel;
225 rotMin = s->get();
226 }
227 }
228 limitingChannels.push_back(channelMin);
229 limitingChannels.push_back(channelMax);
230 limitingRots.emplace_back(rotMin->clone());
231 limitingRots.emplace_back(rotMax->clone());
232 }
233 ATH_MSG_VERBOSE("makeClustersBySurface - " << limitingChannels.size()
234 << ", " << limitingRots.size());
235}
236
238 Trk::LocalParameters& parameters, Amg::MatrixX& errorMatrix,
239 std::unique_ptr<Trk::Surface>& surface, std::list<int>& limitingChannels,
240 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>>& limitingRots) const {
241
242 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>>::const_iterator r = limitingRots.begin();
243 Amg::Vector3D centre = (**r).associatedSurface().center();
244 Amg::MatrixX covariance = (**r).localCovariance();
245 parameters = Trk::LocalParameters{(**r).localParameters()};
246 const bool isRpc = m_idHelperSvc->isRpc((**r).identify());
247
248
249 for (++r;
250 r != limitingRots.end();
251 ++r)
252 {
253 centre += (**r).associatedSurface().center();
254 covariance += (**r).localCovariance();
255 parameters += (**r).localParameters();
256 }
257 const double norm = 1. /static_cast<double>(limitingRots.size());
258 std::list<int>::iterator l = limitingChannels.begin();
259 int firstChannel = *l;
260 double width = static_cast<double>(1 + std::abs(*(++l) - firstChannel));
261 if (limitingRots.size() > 2)
262 {
263 int offset = std::abs(*(++l) - firstChannel);
264 if (!isRpc && offset < 2) {
265 width *= 0.5;
266 } else {
267 width += static_cast<double>(offset);
268 }
269 }
270
271 // get parameter means
272 centre *= norm;
273 covariance *= width*width*norm;
274 parameters *= norm;
275
276 ATH_MSG_VERBOSE("Final parameters "<<m_idHelperSvc->toString((*limitingRots.begin())->identify())<<", centre: "<<Amg::toString(centre)<<", "
277 <<", covariance: "<<covariance<<", parameters: "<<parameters<<" , limiting ROTs: "<<limitingRots.size());
278 // finally create the mean ErrorMatrix and the average Surface
279 // note the cluster surfaces are assumed to have identical orientation and bounds
280 errorMatrix = Amg::MatrixX(covariance);
281 const Trk::Surface& surf = (**limitingRots.begin()).associatedSurface();
282
283 if (const auto* rectbds =
284 dynamic_cast<const Trk::RectangleBounds*>(&surf.bounds())) {
285 surface = std::make_unique<Trk::PlaneSurface>(
286 surf.transform(), std::make_unique<Trk::RectangleBounds>(*rectbds));
287 } else if (const auto* trapbds =
288 dynamic_cast<const Trk::TrapezoidBounds*>(&surf.bounds())) {
289 surface = std::make_unique<Trk::PlaneSurface>(
290 surf.transform(), std::make_unique<Trk::TrapezoidBounds>(*trapbds));
291 } else if (const auto* rottrapbds =
292 dynamic_cast<const Trk::RotatedTrapezoidBounds*>(
293 &surf.bounds())) {
294 surface = std::make_unique<Trk::PlaneSurface>(
295 surf.transform(),
296 std::make_unique<Trk::RotatedTrapezoidBounds>(*rottrapbds));
297 }
298}
299
300} // namespace Muon
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
size_t size() const
Number of registered mappings.
const double width
Base class for Muon cluster RIO_OnTracks.
virtual MuonClusterOnTrack * clone() const override=0
Clone this ROT.
void makeClustersBySurface(std::list< int > &limitingChannels, std::vector< std::unique_ptr< const Muon::MuonClusterOnTrack > > &limitingRots, const std::list< const Trk::PrepRawData * > &prds, const std::vector< std::unique_ptr< const Muon::MuonClusterOnTrack > > &rots) const
std::unique_ptr< CompetingMuonClustersOnTrack > createBroadCluster(const std::list< const Trk::PrepRawData * > &, const double) const
method to create a CompetingMuonClustersOnTrack using the PrepRawData hits and a scaled factor for th...
void makeOverallParameters(Trk::LocalParameters &parameters, Amg::MatrixX &errorMatrix, std::unique_ptr< Trk::Surface > &surface, std::list< int > &limitingChannels, std::vector< std::unique_ptr< const Muon::MuonClusterOnTrack > > &limitingRots) const
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
ToolHandle< Muon::IMuonClusterOnTrackCreator > m_clusterCreator
void applyClusterConsistency(std::list< int > &limitingChannels, std::vector< std::unique_ptr< const Muon::MuonClusterOnTrack > > &limitingRots) const
std::vector< std::unique_ptr< const Muon::MuonClusterOnTrack > > createPrdRots(const std::list< const Trk::PrepRawData * > &prds) const
Identifier identify() const
return the identifier
Bounds for a rectangular, planar surface.
Bounds for a rotated trapezoidal, planar Surface.
Abstract Base Class for tracking surfaces.
Definition Surface.h:79
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
virtual const SurfaceBounds & bounds() const =0
Surface Bounds method.
Bounds for a trapezoidal, planar Surface.
This is the base class for all tracking detector elements with read-out relevant information.
virtual const Amg::Vector3D & center() const =0
Return the center of the element.
int r
Definition globals.cxx:22
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Eigen::Matrix< double, 3, 1 > Vector3D
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.