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*>& prdList, const double) const {
32 ATH_MSG_VERBOSE("enter createBroadCluster: number of prds " << prdList.size());
33
34 // make some PRD consistency checks
35 if (prdList.empty()) {
36 ATH_MSG_WARNING("fails: empty PRD list ");
37 return nullptr;
38 }
39 std::vector<const Trk::PrepRawData*> prds{prdList.begin(), prdList.end()};
40 const Trk::TrkDetElementBase* detectorElement = prds.front()->detectorElement();
41 Identifier channelId = (*prds.front()).identify();
42 const bool isRpc = m_idHelperSvc->isRpc(channelId);
43 const bool isTgc = m_idHelperSvc->isTgc(channelId);
44 if (!isRpc && !isTgc) {
45 ATH_MSG_WARNING("fails: PRD must be from rpc or tgc ");
46 return nullptr;
47 }
48
49 const bool measuresPhi = m_idHelperSvc->measuresPhi(channelId);
50 for (const Trk::PrepRawData* prd : prds) {
51 channelId = prd->identify();
52 if (m_idHelperSvc->measuresPhi(channelId) != measuresPhi) {
53 ATH_MSG_WARNING("fails: PRDs must measure same coordinate ");
54 return nullptr;
55 }
56 if (prd->detectorElement() != detectorElement) {
57 ATH_MSG_WARNING("fails: PRDs must be from same detectorElement ");
58 return nullptr;
59 }
60 ATH_MSG_VERBOSE("Create trigger prd from "
61 << m_idHelperSvc->toString(channelId)
62 << ", nDim: " << prd->localCovariance().rows());
63 }
64
65 // create a rot for each prd (which gets weight zero)
66 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>> rots = createPrdRots(prds);
67 auto assocProbs = std::vector<double>(rots.size(), 0.);
68
69 // for each surface, find the first and last rot forming the cluster
70 std::list<int> limitingChannels;
71 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>> limitingRots;
72 makeClustersBySurface(limitingChannels, limitingRots, prds, rots);
73
74 // cluster consistency - discard any surfaces not contributing to the final cluster
75 applyClusterConsistency(limitingChannels, limitingRots);
76
77 // overall localPosition, error matrix and surface
78 Trk::LocalParameters parameters{};
79 Amg::MatrixX errorMatrix{};
80 std::unique_ptr<Trk::Surface> surface{};
81 makeOverallParameters(parameters, errorMatrix, surface, limitingChannels,
82 limitingRots);
83
84 // clear lists
85 limitingChannels.clear();
86
87 // return the competingMuonClusterOnTrack object containing the final parameters,
88 // error matrix, surface, list of rots and weights
89 return std::make_unique<CompetingMuonClustersOnTrack>(
90 std::move(parameters), std::move(errorMatrix), surface.release(),
91 std::move(rots), std::move(assocProbs));
92}
93
95 std::list<int>& limitingChannels,
96 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>>& limitingRots) const {
97 // remove any clusters that will NOT contribute to the final cluster
98 int numClusters = limitingChannels.size() / 2;
99 int sizeMax = 0;
100 int sizeMin = 999;
101 for (std::list<int>::iterator l = limitingChannels.begin();
102 l != limitingChannels.end() &&
103 l != std::prev(limitingChannels.end());) {
104 int end = *l++;
105 int beg = *l++;
106 int size = std::abs(end - beg);
107 sizeMax = std::max(sizeMax, size);
108 sizeMin = std::min(sizeMin, size);
109 }
110
111 std::list<int>::iterator discard = limitingChannels.end();
112 for (std::list<int>::iterator l = limitingChannels.begin();
113 l != limitingChannels.end() &&
114 l != std::prev(limitingChannels.end());) {
115 std::list<int>::iterator first = l;
116 int end = *l++;
117 int beg = *l++;
118 int size = std::abs(end - beg);
119 if (m_chooseBroadestCluster && size < sizeMax) {
120 discard = first;
121 }
122 if (!m_chooseBroadestCluster && size > sizeMin) {
123 discard = first;
124 }
125 }
126 if (discard == limitingChannels.begin()) {
127 ATH_MSG_VERBOSE(" discard cluster #" << 1);
128 limitingRots.erase(limitingRots.begin());
129 limitingRots.erase(limitingRots.begin());
130 limitingChannels.pop_front();
131 limitingChannels.pop_front();
132 } else if (discard != limitingChannels.end()) {
133 ATH_MSG_VERBOSE(" discard cluster #" << numClusters);
134 limitingRots.pop_back();
135 limitingRots.pop_back();
136 limitingChannels.pop_back();
137 limitingChannels.pop_back();
138 }
139}
140
141std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>>
143 std::vector<const Trk::PrepRawData*>& prds) const {
144 // create clusterRot for each PRD
145 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>> rots{};
146 if (prds.empty()) {
147 ATH_MSG_WARNING("empty PRD list ");
148 return rots;
149 }
150 std::optional<int> dim{};
151 for (const Trk::PrepRawData* prd : prds) {
152 Identifier id = prd->identify();
153 const Trk::TrkDetElementBase* detectorElement = prd->detectorElement();
154 const Amg::Vector3D globalPosition = detectorElement->center(id);
155 std::unique_ptr<const Muon::MuonClusterOnTrack> cluster{
156 m_clusterCreator->createRIO_OnTrack(*prd, globalPosition)};
157 if (!cluster) {
158 ATH_MSG_WARNING("Cannot create a ROT from "
159 << m_idHelperSvc->toString(id) << ".");
160 continue;
161 }
162 if (!dim) {
163 dim = cluster->localCovariance().cols();
164 } else if ((*dim) != cluster->localCovariance().cols()) {
165 ATH_MSG_WARNING("The covariance dimension of "<<m_idHelperSvc->toString(id)
166 <<" does not match "<<(*dim));
167 continue;
168 }
169 rots.push_back(std::move(cluster));
170 }
171 if (rots.size() != prds.size()) {
172 auto [begin, end] = std::ranges::remove_if(prds, [&](const Trk::PrepRawData* prd){
173 return std::ranges::none_of(rots, [prd](const std::unique_ptr<const Muon::MuonClusterOnTrack>& rot){
174 return rot->identify() == prd->identify();
175 });
176 });
177 prds.erase(begin, end);
178 }
179 return rots;
180}
181
183 std::list<int>& limitingChannels,
184 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>>& limitingRots,
185 const std::vector<const Trk::PrepRawData*>& prds,
186 const std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>>& rots) const {
187 if (prds.empty()) {
188 ATH_MSG_WARNING("makeClustersBySurface- empty PRD list ");
189 return;
190 }
191 std::unordered_set<const Trk::PrepRawData*> usedPrd;
192 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>>::const_iterator r = rots.begin();
193 for (std::vector<const Trk::PrepRawData*>::const_iterator p = prds.begin();
194 p != prds.end(); ++p, ++r) {
195
196 const Trk::PrepRawData* prd{*p};
197 if (!usedPrd.insert(prd).second) {
198 continue;
199 }
200 int channel = 0;
201 int gasGap = 0;
202 const Identifier channelId = prd->identify();
203 const bool isRpc = m_idHelperSvc->isRpc(channelId);
204 if (isRpc) {
205 gasGap = m_idHelperSvc->rpcIdHelper().gasGap(channelId);
206 channel = m_idHelperSvc->rpcIdHelper().strip(channelId);
207 } else {
208 gasGap = m_idHelperSvc->tgcIdHelper().gasGap(channelId);
209 channel = m_idHelperSvc->tgcIdHelper().channel(channelId);
210 }
211 int channelMax = channel;
212 int channelMin = channel;
213 const Muon::MuonClusterOnTrack *rotMax{r->get()}, *rotMin{r->get()};
214 std::vector<const Trk::PrepRawData*>::const_iterator q = p;
215 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>>::const_iterator s = r;
216 for (++q, ++s; q != prds.end(); ++q, ++s) {
217 const Identifier channelId1 = (**q).identify();
218 if ((isRpc && m_idHelperSvc->rpcIdHelper().gasGap(channelId1) != gasGap) ||
219 (!isRpc && m_idHelperSvc->tgcIdHelper().gasGap(channelId1) != gasGap)) {
220 continue;
221 }
222 usedPrd.insert(*q);
223 if (isRpc) {
224 channel = m_idHelperSvc->rpcIdHelper().strip(channelId1);
225 } else {
226 channel = m_idHelperSvc->tgcIdHelper().channel(channelId1);
227 }
228 if (channel > channelMax) {
229 channelMax = channel;
230 rotMax = s->get();
231 }
232 if (channel < channelMin) {
233 channelMin = channel;
234 rotMin = s->get();
235 }
236 }
237 limitingChannels.push_back(channelMin);
238 limitingChannels.push_back(channelMax);
239 limitingRots.emplace_back(rotMin->clone());
240 limitingRots.emplace_back(rotMax->clone());
241 }
242 ATH_MSG_VERBOSE("makeClustersBySurface - " << limitingChannels.size()
243 << ", " << limitingRots.size());
244}
245
247 Trk::LocalParameters& parameters, Amg::MatrixX& errorMatrix,
248 std::unique_ptr<Trk::Surface>& surface, std::list<int>& limitingChannels,
249 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>>& limitingRots) const {
250
251 std::vector<std::unique_ptr<const Muon::MuonClusterOnTrack>>::const_iterator r = limitingRots.begin();
252 Amg::Vector3D centre = (**r).associatedSurface().center();
253 Amg::MatrixX covariance = (**r).localCovariance();
254 parameters = Trk::LocalParameters{(**r).localParameters()};
255 const bool isRpc = m_idHelperSvc->isRpc((**r).identify());
256
257
258 for (++r;
259 r != limitingRots.end();
260 ++r)
261 {
262 centre += (**r).associatedSurface().center();
263 covariance += (**r).localCovariance();
264 parameters += (**r).localParameters();
265 }
266 const double norm = 1. /static_cast<double>(limitingRots.size());
267 std::list<int>::iterator l = limitingChannels.begin();
268 int firstChannel = *l;
269 double width = static_cast<double>(1 + std::abs(*(++l) - firstChannel));
270 if (limitingRots.size() > 2)
271 {
272 int offset = std::abs(*(++l) - firstChannel);
273 if (!isRpc && offset < 2) {
274 width *= 0.5;
275 } else {
276 width += static_cast<double>(offset);
277 }
278 }
279
280 // get parameter means
281 centre *= norm;
282 covariance *= width*width*norm;
283 parameters *= norm;
284
285 ATH_MSG_VERBOSE("Final parameters "<<m_idHelperSvc->toString((*limitingRots.begin())->identify())<<", centre: "<<Amg::toString(centre)<<", "
286 <<", covariance: "<<covariance<<", parameters: "<<parameters<<" , limiting ROTs: "<<limitingRots.size());
287 // finally create the mean ErrorMatrix and the average Surface
288 // note the cluster surfaces are assumed to have identical orientation and bounds
289 errorMatrix = Amg::MatrixX(covariance);
290 const Trk::Surface& surf = (**limitingRots.begin()).associatedSurface();
291
292 if (const auto* rectbds =
293 dynamic_cast<const Trk::RectangleBounds*>(&surf.bounds())) {
294 surface = std::make_unique<Trk::PlaneSurface>(
295 surf.transform(), std::make_unique<Trk::RectangleBounds>(*rectbds));
296 } else if (const auto* trapbds =
297 dynamic_cast<const Trk::TrapezoidBounds*>(&surf.bounds())) {
298 surface = std::make_unique<Trk::PlaneSurface>(
299 surf.transform(), std::make_unique<Trk::TrapezoidBounds>(*trapbds));
300 } else if (const auto* rottrapbds =
301 dynamic_cast<const Trk::RotatedTrapezoidBounds*>(
302 &surf.bounds())) {
303 surface = std::make_unique<Trk::PlaneSurface>(
304 surf.transform(),
305 std::make_unique<Trk::RotatedTrapezoidBounds>(*rottrapbds));
306 }
307}
308
309} // 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::vector< const Trk::PrepRawData * > &prds, const std::vector< std::unique_ptr< const Muon::MuonClusterOnTrack > > &rots) const
std::vector< std::unique_ptr< const Muon::MuonClusterOnTrack > > createPrdRots(std::vector< const Trk::PrepRawData * > &prds) 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
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.