ATLAS Offline Software
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 
12 namespace 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 
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;
92  } else if (overlapResult == CompareMuonSegmentKeys::PartialOverlap && m_removePartialOverlaps) {
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;
292  } else if (overlapResult == CompareMuonSegmentKeys::PartialOverlap && m_removePartialOverlaps) {
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
Muon::MuonSegmentOverlapRemovalTool::initialize
StatusCode initialize() override
AlgTool initilize.
Definition: MuonSegmentOverlapRemovalTool.cxx:19
Muon::MuonSegmentCombination
Definition: MuonSegmentCombination.h:30
Muon::CompareMuonSegmentKeys::PartialOverlap
@ PartialOverlap
Definition: CompareMuonSegmentKeys.h:20
Muon::CompareMuonSegmentKeys::SubSet
@ SubSet
Definition: CompareMuonSegmentKeys.h:18
initialize
void initialize()
Definition: run_EoverP.cxx:894
Muon::MuonSegmentOverlapRemovalTool::MuonSegmentOverlapRemovalTool
MuonSegmentOverlapRemovalTool(const std::string &, const std::string &, const IInterface *)
constructor
Definition: MuonSegmentOverlapRemovalTool.cxx:14
Muon::MuonSegmentCombination::stationSegments
SegmentVec * stationSegments(unsigned int index) const
Access to segments in a given station.
Definition: MuonSegmentCombination.h:114
Muon::MuonSegmentKey
Class to cache the identifiers on a segment in sets that can later be used to perform an overlap remo...
Definition: MuonSegmentKey.h:24
Muon::MuonSegmentOverlapRemovalTool::SegVec
std::vector< MuonSegment * > SegVec
Definition: MuonSegmentOverlapRemovalTool.h:45
Muon::MuonSegmentOverlapRemovalTool::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: MuonSegmentOverlapRemovalTool.h:52
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Muon
This class provides conversion from CSC RDO data to CSC Digits.
Definition: TrackSystemController.h:49
Muon::MuonSegmentOverlapRemovalTool::removeDuplicates
void removeDuplicates(Trk::SegmentCollection &segments) const override
remove duplicates from a vector of segments.
Definition: MuonSegmentOverlapRemovalTool.cxx:27
Muon::CompareMuonSegmentKeys::OverlapResult
OverlapResult
enum for the overlap result
Definition: CompareMuonSegmentKeys.h:16
Muon::CompareMuonSegmentKeys::Identical
@ Identical
Definition: CompareMuonSegmentKeys.h:17
Muon::MuonSegmentOverlapRemovalTool::m_removePartialOverlaps
Gaudi::Property< bool > m_removePartialOverlaps
remove partial overlaps between segments
Definition: MuonSegmentOverlapRemovalTool.h:70
DataModel_detail::iterator
(Non-const) Iterator class for DataVector/DataList.
Definition: DVLIterator.h:184
lumiFormat.i
int i
Definition: lumiFormat.py:92
Identifier
Definition: DetectorDescription/Identifier/Identifier/Identifier.h:32
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Trk::Segment
Definition: TrkEvent/TrkSegment/TrkSegment/Segment.h:56
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Trk::FitQuality
Class to represent and store fit qualities from track reconstruction in terms of and number of degre...
Definition: FitQuality.h:97
xAOD::double
double
Definition: CompositeParticle_v1.cxx:159
DataVector< Trk::Segment >
MuonSegmentOverlapRemovalTool.h
Muon::CompareMuonSegmentKeys::Unknown
@ Unknown
Definition: CompareMuonSegmentKeys.h:22
Muon::MuonSegmentOverlapRemovalTool::m_overlapFractionCut
Gaudi::Property< double > m_overlapFractionCut
cut on overlap fraction for segments
Definition: MuonSegmentOverlapRemovalTool.h:73
Muon::CompareMuonSegmentKeys::NoOverlap
@ NoOverlap
Definition: CompareMuonSegmentKeys.h:21
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Muon::MuonSegmentCombination::SegmentVec
std::vector< std::unique_ptr< MuonSegment > > SegmentVec
Definition: MuonSegmentCombination.h:32
Muon::MuonSegmentOverlapRemovalTool::m_printer
ToolHandle< Muon::MuonEDMPrinterTool > m_printer
EDM printer tool.
Definition: MuonSegmentOverlapRemovalTool.h:64
Trk::FitQuality::chiSquared
double chiSquared() const
returns the of the overall track fit
Definition: FitQuality.h:56
MuonSegment.h
Muon::MuonSegmentOverlapRemovalTool::m_edmHelperSvc
ServiceHandle< Muon::IMuonEDMHelperSvc > m_edmHelperSvc
EDM Helper tool.
Definition: MuonSegmentOverlapRemovalTool.h:57
Muon::MuonSegment
Definition: MuonSpectrometer/MuonReconstruction/MuonRecEvent/MuonSegment/MuonSegment/MuonSegment.h:45
AthAlgTool
Definition: AthAlgTool.h:26
Muon::CompareMuonSegmentKeys::SuperSet
@ SuperSet
Definition: CompareMuonSegmentKeys.h:19
Trk::Segment::fitQuality
const FitQuality * fitQuality() const
return the FitQuality object, returns NULL if no FitQuality is defined
Definition: TrkEvent/TrkSegment/TrkSegment/Segment.h:160
FitQuality.h
Muon::MuonSegmentCombination::numberOfStations
unsigned int numberOfStations() const
Number of stations with segment.
Definition: MuonSegmentCombination.h:108
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
CompareMuonSegmentKeys.h
Muon::CompareMuonSegmentKeys
Definition: CompareMuonSegmentKeys.h:14
MuonSegmentKey.h