ATLAS Offline Software
Loading...
Searching...
No Matches
MuonSegmentOverlapRemovalTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
3*/
4
6
11
12namespace Muon {
13
14 MuonSegmentOverlapRemovalTool::MuonSegmentOverlapRemovalTool(const std::string& ty, const std::string& na, const IInterface* pa) :
15 AthAlgTool(ty, na, pa) {
16 declareInterface<IMuonSegmentOverlapRemovalTool>(this);
17 }
18
20 ATH_CHECK(AlgTool::initialize());
21 ATH_CHECK(m_edmHelperSvc.retrieve());
22 ATH_CHECK(m_printer.retrieve());
23 ATH_CHECK(m_idHelperSvc.retrieve());
24 return StatusCode::SUCCESS;
25 }
26
28 ATH_MSG_DEBUG(" working on segment vector of size " << segments.size());
29
30 CompareMuonSegmentKeys compareSegmentKeys{};
31
32 // create a vector with pairs of MuonSegmentKey and a pointer to the corresponding segment to resolve ambiguities
33 std::vector<std::pair<MuonSegmentKey, MuonSegment*>> goodSegments;
34 goodSegments.reserve(segments.size());
35 std::vector<MuonSegment*> segmentsToErase;
36
37 // loop over new segments, copy them into collection
38 for (Trk::Segment* tseg : segments) {
39 // create segment key object
40 MuonSegment* seg = dynamic_cast<MuonSegment*>(tseg);
41 if (!seg) {
42 ATH_MSG_WARNING("segment is not MuonSegment");
43 continue;
44 }
45 MuonSegmentKey sk{*seg};
46 Identifier chId = m_edmHelperSvc->chamberId(*seg);
47 bool isCsc = m_idHelperSvc->isCsc(chId);
48
49 // should this segment be inserted?
50 bool insertAsGood = true;
51
52 // loop over already accepted segments and compare the current segment with the good ones
53 for (std::pair<MuonSegmentKey, MuonSegment*>& good_seg : goodSegments) {
54 CompareMuonSegmentKeys::OverlapResult overlapResult = compareSegmentKeys(good_seg.first, sk);
55 if (overlapResult == CompareMuonSegmentKeys::Identical) {
56 // for now keep the one with the best chi2
57 const Trk::FitQuality* fq1 = good_seg.second->fitQuality();
58 const Trk::FitQuality* fq2 = seg->fitQuality();
59 double chi2good = fq1 ? fq1->chiSquared() : 1e10;
60 double chi2current = fq2 ? fq2->chiSquared() : 1e10;
61 // we should not insert this segment
62 if (chi2good > chi2current) {
63 ATH_MSG_VERBOSE(" replacing (chi2) " << m_printer->print(*good_seg.second) << std::endl
64 << " with " << m_printer->print(*seg));
65
66 // good segment of worse quality, replace it
67 segmentsToErase.push_back(good_seg.second);
68 good_seg.first = sk;
69 good_seg.second = seg;
70
71 } else {
72 ATH_MSG_VERBOSE(" discarding (chi2) " << m_printer->print(*seg));
73 segmentsToErase.push_back(seg);
74 }
75 insertAsGood = false;
76 break;
77 } else if (overlapResult == CompareMuonSegmentKeys::SuperSet) {
78 // good segment of better quality, keep it and discard current segment
79 ATH_MSG_VERBOSE(" discarding (subset) " << m_printer->print(*seg));
80 segmentsToErase.push_back(seg);
81 insertAsGood = false;
82 break;
83 } else if (overlapResult == CompareMuonSegmentKeys::SubSet) {
84 // good segment of worse quality, replace it
85 ATH_MSG_VERBOSE(" replacing (superset) " << m_printer->print(*good_seg.second) << std::endl
86 << " with " << m_printer->print(*seg));
87 segmentsToErase.push_back(good_seg.second);
88 good_seg.first = sk;
89 good_seg.second = seg;
90 insertAsGood = false;
91 break;
93 // keep CSC segments with partial overlap
94 if (isCsc) continue;
95
96 // partial overlap, for now keep the one most hits
97 if (compareSegmentKeys.segment1Size < compareSegmentKeys.segment2Size) {
98 ATH_MSG_VERBOSE(" replacing (mdt hits) " << m_printer->print(*good_seg.second) << std::endl
99 << " with " << m_printer->print(*seg));
100
101 // good segment of worse quality, replace it
102 segmentsToErase.push_back(good_seg.second);
103 good_seg.first = sk;
104 good_seg.second = seg;
105 insertAsGood = false;
106 break;
107 } else if (compareSegmentKeys.segment1Size == compareSegmentKeys.segment2Size) {
108 // same size
109
110 // if the original entry has more trigger hits discard current segment
111 if (compareSegmentKeys.segment1SizeTrigger > compareSegmentKeys.segment2SizeTrigger) {
112 ATH_MSG_VERBOSE(" discarding (trigger hits) " << m_printer->print(*seg));
113 segmentsToErase.push_back(seg);
114 insertAsGood = false;
115 break;
116 } else if (compareSegmentKeys.segment1SizeTrigger < compareSegmentKeys.segment2SizeTrigger) {
117 // good segment of worse quality, replace it
118 ATH_MSG_VERBOSE(" replacing (trigger hits) " << m_printer->print(*good_seg.second) << std::endl
119 << " with " << m_printer->print(*seg));
120 segmentsToErase.push_back(good_seg.second);
121 good_seg.first = sk;
122 good_seg.second = seg;
123 insertAsGood = false;
124 break;
125 } else if (compareSegmentKeys.segment1SizeTrigger == compareSegmentKeys.segment2SizeTrigger) {
126 // for now look at the overlap fraction
127 }
128 // calculate the overlap fraction
129 double overlapFraction = (double)compareSegmentKeys.intersectionSize / (double)compareSegmentKeys.segment1Size;
130 if (overlapFraction > m_overlapFractionCut) {
131 ATH_MSG_VERBOSE(" discarding (overlap fraction) " << m_printer->print(*seg));
132 segmentsToErase.push_back(seg);
133 insertAsGood = false;
134 break;
135 }
136
137 continue;
138 } else {
139 ATH_MSG_VERBOSE(" discarding " << m_printer->print(*seg));
140 segmentsToErase.push_back(seg);
141 }
142 insertAsGood = false;
143 break;
144 } else if (overlapResult == CompareMuonSegmentKeys::NoOverlap) {
145 // no overlap, move on to next segment
146 continue;
147 } else if (overlapResult == CompareMuonSegmentKeys::Unknown) {
148 ATH_MSG_WARNING(" Got invalid return argument comparing segments: " << compareSegmentKeys.print(overlapResult));
149 continue;
150 }
151 }
152
153 // add segment if needed
154 if (insertAsGood) {
155 ATH_MSG_VERBOSE(" no overlap " << m_printer->print(*seg));
156 goodSegments.emplace_back(std::move(sk), seg);
157 }
158 }
159
160 // erase rejected segments
161 for (MuonSegment* to_erase : segmentsToErase) {
162 for (Trk::SegmentCollection::iterator sit = segments.begin(); sit != segments.end(); ++sit) {
163 // remove bad segments from collection, then delete them
164 Trk::Segment* tseg = *sit;
165 if (to_erase == dynamic_cast<MuonSegment*>(tseg)) {
166 segments.erase(sit);
167 break;
168 }
169 }
170 }
171 }
172
173 std::unique_ptr<MuonSegmentCombination> MuonSegmentOverlapRemovalTool::removeDuplicates(const MuonSegmentCombination& combi) const {
174 // store pointers to segments that should be kept
175 std::set<MuonSegment*> segmentsToBeKept;
176 unsigned int nsegments = 0; // total number of segments
177
178 unsigned int nstations = combi.numberOfStations();
179
180 ATH_MSG_DEBUG(" removing duplicate from MuonSegmentCombination with " << nstations << " stations");
181
182 // loop over segments, add them to the chamber layers
183 // loop over chambers in combi and extract segments
184 for (unsigned int i = 0; i < nstations; ++i) {
185 // loop over segments in station
187
188 // check if not empty
189 if (!stationSegs || stationSegs->empty()) continue;
190
191 nsegments += stationSegs->size();
192
193 // clean segments
194 SegVec cleanedSegments = removeDuplicates(*stationSegs);
195 segmentsToBeKept.insert(cleanedSegments.begin(), cleanedSegments.end());
196 }
197
198 // check whether all segments were kept
199 if (nsegments == segmentsToBeKept.size()) {
200 ATH_MSG_DEBUG(" no segments removed ");
201 return nullptr;
202 }
203
204 std::unique_ptr<MuonSegmentCombination> newCombi = std::make_unique<MuonSegmentCombination>();
205
206 // create a new combination removing segments that overlap
207 for (unsigned int i = 0; i < nstations; ++i) {
208 // loop over segments in station
210
211 // check if not empty
212 if (!stationSegs || stationSegs->empty()) continue;
213
214 std::unique_ptr<std::vector<std::unique_ptr<MuonSegment>>> segVec =
215 std::make_unique<std::vector<std::unique_ptr<MuonSegment>>>();
216 segVec->reserve(stationSegs->size());
217
218 // loop over segments and add them if they are in the keep set
219 for (const std::unique_ptr<MuonSegment>& seg : *stationSegs) {
220 if (!segmentsToBeKept.count(seg.get())) {
221 continue;
222 } else {
223 segVec->emplace_back(seg->clone());
224 }
225 }
226 // if not empty add segments
227 if (!segVec->empty()) newCombi->addSegments(std::move(segVec));
228 }
229
230 ATH_MSG_DEBUG(" removed " << nsegments - segmentsToBeKept.size() << " duplicates, new size " << segmentsToBeKept.size());
231
232 return newCombi;
233 }
234
235 // this applies only to the case of cleaning MuonSegmentCombinations, above
236 // currently not used, maybe it can be removed entirely?
238 MuonSegmentCombination::SegmentVec& segments) const {
239 ATH_MSG_DEBUG(" working on segment vector of size " << segments.size());
240
241 CompareMuonSegmentKeys compareSegmentKeys{};
242
243 // create a vector with pairs of MuonSegmentKey and a pointer to the corresponding segment to resolve ambiguities
244 std::vector<std::pair<MuonSegmentKey, MuonSegment*>> goodSegments;
245 goodSegments.reserve(segments.size());
246
247 // loop over new segments, copy them into collection
248 for (const std::unique_ptr<MuonSegment>& seg : segments) {
249 // create segment key object
250 MuonSegmentKey sk(*seg);
251 Identifier chId = m_edmHelperSvc->chamberId(*seg);
252 bool isCsc = m_idHelperSvc->isCsc(chId);
253
254 // should this segment be inserted?
255 bool insertAsGood(true);
256
257 // loop over already accepted segments and compare the current segment with the good ones
258 for (std::pair<MuonSegmentKey, MuonSegment*>& good_seg : goodSegments) {
259 CompareMuonSegmentKeys::OverlapResult overlapResult = compareSegmentKeys(good_seg.first, sk);
260 if (overlapResult == CompareMuonSegmentKeys::Identical) {
261 // for now keep the one with the best chi2
262 const Trk::FitQuality* fq1 = good_seg.second->fitQuality();
263 const Trk::FitQuality* fq2 = seg->fitQuality();
264 double chi2good = fq1 ? fq1->chiSquared() : 1e10;
265 double chi2current = fq2 ? fq2->chiSquared() : 1e10;
266 // we should not insert this segment
267 if (chi2good > chi2current) {
268 ATH_MSG_VERBOSE(" replacing (chi2) " << m_printer->print(*good_seg.second) << std::endl
269 << " with " << m_printer->print(*seg));
270
271 // good segment of worse quality, replace it
272 good_seg.first = sk;
273 good_seg.second = seg.get();
274 } else {
275 ATH_MSG_VERBOSE(" discarding (chi2) " << m_printer->print(*seg));
276 }
277 insertAsGood = false;
278 break;
279 } else if (overlapResult == CompareMuonSegmentKeys::SuperSet) {
280 // good segment of better quality, keep it and discard current segment
281 ATH_MSG_VERBOSE(" discarding (subset) " << m_printer->print(*seg));
282 insertAsGood = false;
283 break;
284 } else if (overlapResult == CompareMuonSegmentKeys::SubSet) {
285 // good segment of worse quality, replace it
286 ATH_MSG_VERBOSE(" replacing (superset) " << m_printer->print(*good_seg.second) << std::endl
287 << " with " << m_printer->print(*seg));
288 good_seg.first = sk;
289 good_seg.second = seg.get();
290 insertAsGood = false;
291 break;
293 // keep CSC segments with partial overlap
294 if (isCsc) continue;
295
296 // partial overlap, for now keep the one most hits
297 if (compareSegmentKeys.segment1Size < compareSegmentKeys.segment2Size) {
298 ATH_MSG_VERBOSE(" replacing (mdt hits) " << m_printer->print(*good_seg.second) << std::endl
299 << " with " << m_printer->print(*seg));
300
301 // good segment of worse quality, replace it
302 good_seg.first = sk;
303 good_seg.second = seg.get();
304 } else if (compareSegmentKeys.segment1Size == compareSegmentKeys.segment2Size) {
305 // same size
306
307 // if the original entry has more trigger hits discard current segment
308 if (compareSegmentKeys.segment1SizeTrigger > compareSegmentKeys.segment2SizeTrigger) {
309 ATH_MSG_VERBOSE(" discarding (trigger hits) " << m_printer->print(*seg));
310 insertAsGood = false;
311 break;
312 } else if (compareSegmentKeys.segment1SizeTrigger < compareSegmentKeys.segment2SizeTrigger) {
313 // good segment of worse quality, replace it
314 ATH_MSG_VERBOSE(" replacing (trigger hits) " << m_printer->print(*good_seg.second) << std::endl
315 << " with " << m_printer->print(*seg));
316 good_seg.first = sk;
317 good_seg.second = seg.get();
318 insertAsGood = false;
319 break;
320 } else if (compareSegmentKeys.segment1SizeTrigger == compareSegmentKeys.segment2SizeTrigger) {
321 // for now look at the overlap fraction
322 }
323 // calculate the overlap fraction
324 double overlapFraction = (double)compareSegmentKeys.intersectionSize / (double)compareSegmentKeys.segment1Size;
325 if (overlapFraction > m_overlapFractionCut) {
326 ATH_MSG_VERBOSE(" discarding (overlap fraction) " << m_printer->print(*seg));
327 insertAsGood = false;
328 break;
329 }
330
331 continue;
332 } else {
333 ATH_MSG_VERBOSE(" discarding " << m_printer->print(*seg));
334 }
335 insertAsGood = false;
336 break;
337 } else if (overlapResult == CompareMuonSegmentKeys::NoOverlap) {
338 // no overlap, move on to next segment
339 continue;
340 } else if (overlapResult == CompareMuonSegmentKeys::Unknown) {
341 ATH_MSG_WARNING(" Got invalid return argument comparing segments: " << compareSegmentKeys.print(overlapResult));
342 continue;
343 }
344 }
345
346 // add segment if needed
347 if (insertAsGood) {
348 ATH_MSG_VERBOSE(" no overlap " << m_printer->print(*seg));
349 goodSegments.emplace_back(sk, seg.get());
350 }
351 }
352
353 SegVec cleanedSegments;
354 for (const std::pair<MuonSegmentKey, MuonSegment*>& good_seg : goodSegments) { cleanedSegments.push_back(good_seg.second); }
355 ATH_MSG_DEBUG(" Segments after removal " << cleanedSegments.size() << " total number of removed segments "
356 << segments.size() - cleanedSegments.size());
357
358 return cleanedSegments;
359 }
360
361} // namespace Muon
#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)
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
DataModel_detail::iterator< DataVector > iterator
Definition DataVector.h:842
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
iterator erase(iterator position)
Remove element at a given position.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
Class to hold a set of MuonSegments belonging together.
std::vector< std::unique_ptr< MuonSegment > > SegmentVec
SegmentVec * stationSegments(unsigned int index) const
Access to segments in a given station.
unsigned int numberOfStations() const
Number of stations with segment.
Class to cache the identifiers on a segment in sets that can later be used to perform an overlap remo...
MuonSegmentOverlapRemovalTool(const std::string &, const std::string &, const IInterface *)
constructor
Gaudi::Property< double > m_overlapFractionCut
cut on overlap fraction for segments
ServiceHandle< Muon::IMuonEDMHelperSvc > m_edmHelperSvc
EDM Helper tool.
void removeDuplicates(Trk::SegmentCollection &segments) const override
remove duplicates from a vector of segments.
PublicToolHandle< Muon::MuonEDMPrinterTool > m_printer
EDM printer tool.
Gaudi::Property< bool > m_removePartialOverlaps
remove partial overlaps between segments
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
StatusCode initialize() override
AlgTool initilize.
This is the common class for 3D segments used in the muon spectrometer.
Class to represent and store fit qualities from track reconstruction in terms of and number of degre...
Definition FitQuality.h:97
double chiSquared() const
returns the of the overall track fit
Definition FitQuality.h:56
Base class for all TrackSegment implementations, extends the common MeasurementBase.
const FitQuality * fitQuality() const
return the FitQuality object, returns NULL if no FitQuality is defined
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
DataVector< Trk::Segment > SegmentCollection
std::string print(const OverlapResult &result) const
print result to string
OverlapResult
enum for the overlap result