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
16
17#include <functional>
18
19namespace Muon
20{
21
22TriggerChamberClusterOnTrackCreator::TriggerChamberClusterOnTrackCreator(const std::string& type, const std::string& name, const IInterface* parent) :
23 AthAlgTool(type, name, parent),
25{
26 declareInterface<Muon::IMuonCompetingClustersOnTrackCreator>(this);
27 declareProperty("ChooseBroadestCluster", m_chooseBroadestCluster);
28}
29
30StatusCode
32{
33 ATH_CHECK(m_idHelperSvc.retrieve());
34 ATH_CHECK(m_clusterCreator.retrieve());
35 return StatusCode::SUCCESS;
36}
37
38std::unique_ptr<CompetingMuonClustersOnTrack>
39TriggerChamberClusterOnTrackCreator::createBroadCluster(const std::list<const Trk::PrepRawData*>& prds, const double) const {
40 ATH_MSG_VERBOSE("enter createBroadCluster: number of prds " << prds.size() );
41
42 // make some PRD consistency checks
43 if (prds.empty()) {
44 ATH_MSG_WARNING("fails: empty PRD list ");
45 return nullptr;
46 }
47 if (!(*prds.begin())) {
48 ATH_MSG_WARNING("fails: first element of RPD list is nullptr");
49 return nullptr;
50 }
51 const Trk::TrkDetElementBase* detectorElement = (**prds.begin()).detectorElement();
52 Identifier channelId = (**prds.begin()).identify();
53 bool isRpc = m_idHelperSvc->isRpc(channelId);
54 if (!isRpc) {
55 if (!m_idHelperSvc->isTgc(channelId)) {
56 ATH_MSG_WARNING("fails: PRD must be from rpc or tgc ");
57 return nullptr;
58 }
59 }
60
61 bool measuresPhi = isRpc && m_idHelperSvc->rpcIdHelper().measuresPhi(channelId);
62 if (!isRpc) measuresPhi = m_idHelperSvc->tgcIdHelper().isStrip(channelId);
63 for (std::list<const Trk::PrepRawData*>::const_iterator p = prds.begin(); p != prds.end(); ++p) {
64 if (!(*p)) {
65 ATH_MSG_WARNING("fails: current PrepRawData is nullptr, continuing");
66 continue;
67 }
68 channelId = (**p).identify();
69 if ((isRpc && m_idHelperSvc->rpcIdHelper().measuresPhi(channelId) != measuresPhi) || (!isRpc && m_idHelperSvc->tgcIdHelper().isStrip(channelId) != measuresPhi)) {
70 ATH_MSG_WARNING("fails: PRDs must measure same coordinate ");
71 return nullptr;
72 }
73 if ((**p).detectorElement() != detectorElement) {
74 ATH_MSG_WARNING("fails: PRDs must be from same detectorElement ");
75 return nullptr;
76 }
77 }
78
79 // create a rot for each prd (which gets weight zero)
80 std::vector<const Muon::MuonClusterOnTrack*> rots = createPrdRots(prds);
81 auto assocProbs = std::vector<double>(rots.size(), 0.);
82
83
84 // for each surface, find the first and last rot forming the cluster
85 std::list<int> limitingChannels;
86 std::list<const Muon::MuonClusterOnTrack*> limitingRots;
87 makeClustersBySurface(limitingChannels,limitingRots,prds,rots);
88
89 // cluster consistency - discard any surfaces not contributing to the final cluster
90 applyClusterConsistency(limitingChannels,limitingRots);
91
92 // overall localPosition, error matrix and surface
93 Trk::LocalParameters parameters{};
94 Amg::MatrixX errorMatrix{};
95 Trk::Surface* surface = nullptr;
96 makeOverallParameters(parameters,errorMatrix,surface,limitingChannels,limitingRots);
97
98 // clear lists
99 limitingChannels.clear();
100
101 // return the competingMuonClusterOnTrack object containing the final parameters,
102 // error matrix, surface, list of rots and weights
103 return std::make_unique<CompetingMuonClustersOnTrack>(
104 std::move(parameters), std::move(errorMatrix), surface, std::move(rots), std::move(assocProbs));
105}
106
107void
109 std::list<int>& limitingChannels,
110 std::list<const Muon::MuonClusterOnTrack*>& limitingRots) const
111{
112 // remove any clusters that will NOT contribute to the final cluster
113 int numClusters = limitingChannels.size()/2;
114 int sizeMax = 0;
115 int sizeMin = 999;
116 for (std::list<int>::iterator l = limitingChannels.begin();
117 l != limitingChannels.end() && l != std::prev(limitingChannels.end());
118 )
119 {
120 int end = *l++;
121 int beg = *l++;
122 int size = abs(end - beg);
123 if (size > sizeMax) sizeMax = size;
124 if (size < sizeMin) sizeMin = size;
125 }
126
127 std::list<int>::iterator discard = limitingChannels.end();
128 for (std::list<int>::iterator l = limitingChannels.begin();
129 l != limitingChannels.end() && l != std::prev(limitingChannels.end());
130 )
131 {
132 std::list<int>::iterator first = l;
133 int end = *l++;
134 int beg = *l++;
135 int size = abs(end - beg);
136 if (m_chooseBroadestCluster && size < sizeMax) discard = first;
137 if (! m_chooseBroadestCluster && size > sizeMin) discard = first;
138 }
139 if (discard == limitingChannels.begin())
140 {
141 ATH_MSG_VERBOSE(" discard cluster #" << 1 );
142 limitingRots.pop_front();
143 limitingRots.pop_front();
144 limitingChannels.pop_front();
145 limitingChannels.pop_front();
146 }
147 else if (discard != limitingChannels.end())
148 {
149 ATH_MSG_VERBOSE(" discard cluster #" << numClusters );
150 limitingRots.pop_back();
151 limitingRots.pop_back();
152 limitingChannels.pop_back();
153 limitingChannels.pop_back();
154 }
155}
156
157std::vector<const Muon::MuonClusterOnTrack*> TriggerChamberClusterOnTrackCreator::createPrdRots(const std::list<const Trk::PrepRawData*>& prds) const {
158 // create clusterRot for each PRD
159 auto rots = std::vector<const Muon::MuonClusterOnTrack*>();
160 if (prds.empty()) {
161 ATH_MSG_WARNING("empty PRD list ");
162 return rots;
163 }
164 if (!(*prds.begin())) {
165 ATH_MSG_WARNING("first element of RPD list is nullptr");
166 return rots;
167 }
168 for (std::list<const Trk::PrepRawData*>::const_iterator p = prds.begin(); p != prds.end(); ++p) {
169 if (!(*p)) {
170 ATH_MSG_WARNING("current PrepRawData is nullptr, continuing");
171 continue;
172 }
173 Identifier id = (**p).identify();
174 const Trk::TrkDetElementBase* detectorElement = (**p).detectorElement();
175 const Amg::Vector3D globalPosition = detectorElement->center(id);
176 const Muon::MuonClusterOnTrack* cluster = m_clusterCreator->createRIO_OnTrack(**p,globalPosition);
177 rots.push_back(cluster);
178 }
179 return rots;
180}
181
182void
183TriggerChamberClusterOnTrackCreator::makeClustersBySurface(std::list<int>& limitingChannels, std::list<const Muon::MuonClusterOnTrack*>& limitingRots, const std::list<const Trk::PrepRawData*>& prds, const std::vector<const Muon::MuonClusterOnTrack*>& rots) const {
184 if (prds.empty()) {
185 ATH_MSG_WARNING("makeClustersBySurface- empty PRD list ");
186 return;
187 }
188 if (!(*prds.begin())) {
189 ATH_MSG_WARNING("makeClustersBySurface - first element of RPD list is nullptr");
190 return;
191 }
192 std::vector<const Trk::PrepRawData*> usedPrd;
193 std::vector<const Muon::MuonClusterOnTrack*>::const_iterator r = rots.begin();
194 for (std::list<const Trk::PrepRawData*>::const_iterator p = prds.begin(); p != prds.end(); ++p, ++r) {
195 if (!(*p)) {
196 ATH_MSG_WARNING("makeClustersBySurface - current PrepRawData is nullptr, continuing");
197 continue;
198 }
199 if (std::find(usedPrd.begin(),usedPrd.end(),*p) != usedPrd.end()) continue;
200 usedPrd.push_back(*p);
201 int channel = 0;
202 int gasGap = 0;
203 Identifier channelId = (**p).identify();
204 bool isRpc = m_idHelperSvc->isRpc(channelId);
205 if (isRpc)
206 {
207 gasGap = m_idHelperSvc->rpcIdHelper().gasGap(channelId);
208 channel = m_idHelperSvc->rpcIdHelper().strip(channelId);
209 }
210 else
211 {
212 gasGap = m_idHelperSvc->tgcIdHelper().gasGap(channelId);
213 channel = m_idHelperSvc->tgcIdHelper().channel(channelId);
214 }
215 int channelMax = channel;
216 int channelMin = channel;
217 const Muon::MuonClusterOnTrack* rotMax = *r;
218 const Muon::MuonClusterOnTrack* rotMin = *r;
219
220 std::list<const Trk::PrepRawData*>::const_iterator q = p;
221 std::vector<const Muon::MuonClusterOnTrack*>::const_iterator s = r;
222 for (++q, ++s; q != prds.end(); ++q, ++s) {
223 if (!(*q)) {
224 ATH_MSG_WARNING("makeClustersBySurface - current PrepRawData is nullptr, continuing");
225 continue;
226 }
227 channelId = (**q).identify();
228 if (( isRpc && m_idHelperSvc->rpcIdHelper().gasGap(channelId) != gasGap)
229 || (! isRpc && m_idHelperSvc->tgcIdHelper().gasGap(channelId) != gasGap)) continue;
230 usedPrd.push_back(*q);
231 if (isRpc)
232 {
233 channel = m_idHelperSvc->rpcIdHelper().strip(channelId);
234 }
235 else
236 {
237 channel = m_idHelperSvc->tgcIdHelper().channel(channelId);
238 }
239 if (channel > channelMax)
240 {
241 channelMax = channel;
242 rotMax = *s;
243 }
244 if (channel < channelMin)
245 {
246 channelMin = channel;
247 rotMin = *s;
248 }
249
250 }
251 limitingChannels.push_back(channelMin);
252 limitingChannels.push_back(channelMax);
253 limitingRots.push_back(rotMin);
254 limitingRots.push_back(rotMax);
255 }
256
257 // debug
258 if ( msgLvl(MSG::VERBOSE) )
259 {
260 std::list<int>::const_iterator l = limitingChannels.begin();
261 std::list<int>::const_iterator m = limitingChannels.begin();
262 int number = 0;
263 int size = abs(*l - *(++m));
264 for (std::vector<const Trk::PrepRawData*>::const_iterator q = usedPrd.begin();
265 q != usedPrd.end();
266 ++q, --size)
267 {
268 Identifier channelId = (**q).identify();
269 bool isRpc = m_idHelperSvc->isRpc(channelId);
270 if (isRpc)
271 {
272 int stationIndex = m_idHelperSvc->rpcIdHelper().stationName(channelId);
273 ATH_MSG_VERBOSE(" rpc "
274 << std::setiosflags(std::ios::fixed)
275 << " localPosition "
276 << std::setw(8) << std::setprecision(1) << (**q).localPosition()[Trk::locX]
277 << std::setw(8) << std::setprecision(1) << (**q).localPosition()[Trk::locY]
278 << " doublet z/phi"
279 << std::setw(2) << m_idHelperSvc->rpcIdHelper().doubletZ(channelId)
280 << std::setw(2) << m_idHelperSvc->rpcIdHelper().doubletPhi(channelId)
281 << " gasGap" << std::setw(2) << m_idHelperSvc->rpcIdHelper().gasGap(channelId)
282 << " strip" << std::setw(3) << m_idHelperSvc->rpcIdHelper().strip(channelId)
283 << " station " << m_idHelperSvc->rpcIdHelper().stationNameString(stationIndex)
284 << " " << m_idHelperSvc->rpcIdHelper().show_to_string(channelId) );
285 }
286 else
287 {
288 int stationIndex = m_idHelperSvc->tgcIdHelper().stationName(channelId);
289 ATH_MSG_VERBOSE(" tgc "
290 << std::setiosflags(std::ios::fixed)
291 << " localPosition "
292 << std::setw(8) << std::setprecision(1) << (**q).localPosition()[Trk::locX]
293 << std::setw(8) << std::setprecision(1) << (**q).localPosition()[Trk::locY]
294 << " gasGap" << std::setw(2) << m_idHelperSvc->tgcIdHelper().gasGap(channelId)
295 << " channel" << std::setw(3) << m_idHelperSvc->tgcIdHelper().channel(channelId)
296 << " station " << m_idHelperSvc->tgcIdHelper().stationNameString(stationIndex)
297 << " " << m_idHelperSvc->tgcIdHelper().show_to_string(channelId) );
298 }
299 if (size == 0)
300 {
301 ATH_MSG_VERBOSE(" cluster " << ++number
302 << " between channels " << *l << " and " << *m );
303 if (++m != limitingChannels.end())
304 {
305 ++l;
306 size = 1 + abs(*(++l) - *(++m));
307 }
308 }
309 }
310 }
311}
312
313void
315 Trk::LocalParameters& parameters,
316 Amg::MatrixX& errorMatrix,
317 Trk::Surface*& surface,
318 std::list<int>& limitingChannels,
319 std::list<const Muon::MuonClusterOnTrack*>& limitingRots) const
320{
321 // surfaces, overall localPosition and error matrix
322 //std::list<const Trk::Surface*> surfaces;
323 std::list<const Muon::MuonClusterOnTrack*>::const_iterator r = limitingRots.begin();
324 Amg::Vector3D centre = (**r).associatedSurface().center();
325 Amg::MatrixX covariance = (**r).localCovariance();
326 parameters = Trk::LocalParameters((**r).localParameters());
327 Identifier channelId = (**r).identify();
328 bool isRpc = m_idHelperSvc->isRpc(channelId);
329
330 int pair = 1;
331 for (++r;
332 r != limitingRots.end();
333 ++r, ++pair)
334 {
335 centre += (**r).associatedSurface().center();
336 covariance += (**r).localCovariance();
337 parameters += (**r).localParameters();
338 }
339 double norm = 1.;
340 norm /= static_cast<double>(limitingRots.size());
341 std::list<int>::iterator l = limitingChannels.begin();
342 int firstChannel = *l;
343 double width = static_cast<double>(1 + abs(*(++l) - firstChannel));
344 if (limitingRots.size() > 2)
345 {
346 int offset = abs(*(++l) - firstChannel);
347 if (!isRpc && offset < 2) {
348 width *= 0.5;
349 } else {
350 width += static_cast<double>(offset);
351 }
352 }
353
354 // get parameter means
355 centre *= norm;
356 covariance *= width*width*norm;
357 parameters *= norm;
358
359 // finally create the mean ErrorMatrix and the average Surface
360 // note the cluster surfaces are assumed to have identical orientation and bounds
361 errorMatrix = Amg::MatrixX(covariance);
362 const Trk::Surface& surf = (**limitingRots.begin()).associatedSurface();
363 Amg::Transform3D rotation = surf.transform();
364 std::string shape = "";
365
366 const Trk::RectangleBounds* rectbds = dynamic_cast<const Trk::RectangleBounds*>(&surf.bounds());
367 const Trk::TrapezoidBounds* trapbds = dynamic_cast<const Trk::TrapezoidBounds*>(&surf.bounds());
368 const Trk::RotatedTrapezoidBounds* rottrapbds = dynamic_cast<const Trk::RotatedTrapezoidBounds*>(&surf.bounds());
369
370 if (rectbds)
371 {
372 shape = " RPC rectangle ";
373 surface = new Trk::PlaneSurface(Amg::Transform3D(rotation),
374 std::shared_ptr<Trk::RectangleBounds>(rectbds->clone()));
375 }
376 else if (trapbds)
377 {
378 shape = " TGC trapezoid ";
379 surface = new Trk::PlaneSurface(
380 Amg::Transform3D(rotation),
381 std::shared_ptr<Trk::TrapezoidBounds>(trapbds->clone()));
382 }
383 else if (rottrapbds)
384 {
385 shape = " TGC rotatedTrapezoid ";
386 surface = new Trk::PlaneSurface(
387 Amg::Transform3D(rotation),
388 std::shared_ptr<Trk::RotatedTrapezoidBounds>(rottrapbds->clone()));
389 }
390
391 // debug
392 if ( msgLvl(MSG::DEBUG) )
393 {
394 ATH_MSG_DEBUG(shape << " width " << width << " localParameters " << (parameters)[Trk::locX]);
395 if (covariance.cols() > 1) ATH_MSG_DEBUG(" " << (parameters)[Trk::locY]);
396 ATH_MSG_DEBUG(" covariance " << std::sqrt(covariance(Trk::locX,Trk::locX)));
397 if (covariance.cols() > 1) ATH_MSG_DEBUG(" " << std::sqrt(covariance(Trk::locY,Trk::locY)));
398 ATH_MSG_DEBUG(" channel range (cluster) ");
399 pair = 2;
400 for (std::list<int>::iterator i = limitingChannels.begin();
401 i != limitingChannels.end();
402 ++i, ++pair)
403 {
404 ATH_MSG_DEBUG( *i << " ");
405 if (pair%2) ATH_MSG_DEBUG("(" << pair/2 << ") ");
406 }
407 }
408}
409
410} // end of namespace
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
const double width
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
bool msgLvl(const MSG::Level lvl) const
Base class for Muon cluster RIO_OnTracks.
void makeOverallParameters(Trk::LocalParameters &parameters, Amg::MatrixX &errorMatrix, Trk::Surface *&surface, std::list< int > &limitingChannels, std::list< const Muon::MuonClusterOnTrack * > &limitingRots) const
void applyClusterConsistency(std::list< int > &limitingChannels, std::list< const Muon::MuonClusterOnTrack * > &limitingRots) const
TriggerChamberClusterOnTrackCreator(const std::string &type, const std::string &name, const IInterface *parent)
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...
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
ToolHandle< Muon::IMuonClusterOnTrackCreator > m_clusterCreator
std::vector< const Muon::MuonClusterOnTrack * > createPrdRots(const std::list< const Trk::PrepRawData * > &prds) const
void makeClustersBySurface(std::list< int > &limitingChannels, std::list< const Muon::MuonClusterOnTrack * > &limitingRots, const std::list< const Trk::PrepRawData * > &prds, const std::vector< const Muon::MuonClusterOnTrack * > &rots) const
Class for a planaer rectangular or trapezoidal surface in the ATLAS detector.
Bounds for a rectangular, planar surface.
virtual RectangleBounds * clone() const override
Virtual constructor.
Bounds for a rotated trapezoidal, planar Surface.
virtual RotatedTrapezoidBounds * clone() const override
Virtual constructor.
Abstract Base Class for tracking surfaces.
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.
virtual TrapezoidBounds * clone() const override
Virtual constructor.
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.
STL class.
int r
Definition globals.cxx:22
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
@ locY
local cartesian
Definition ParamDefs.h:38
@ locX
Definition ParamDefs.h:37
std::string number(const double &d, const std::string &s)
Definition utils.cxx:186