Belle II Software  release-06-00-14
CDCCKFDuplicateRemover.h
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #pragma once
9 
10 #include <tracking/trackFindingCDC/findlets/base/Findlet.h>
11 #include <tracking/ckf/cdc/entities/CDCCKFResult.h>
12 
13 #include <ecl/dataobjects/ECLShower.h>
14 
15 #include <tracking/trackFindingCDC/filters/base/ChooseableFilter.h>
16 #include <tracking/ckf/cdc/filters/paths/CDCPathFilterFactory.h>
17 
18 #include <tracking/ckf/cdc/filters/pathPairs/CDCPathPairFilterFactory.h>
19 #include <tracking/trackFindingCDC/filters/base/ChooseableFilter.icc.h>
20 
21 
22 namespace Belle2 {
29  class CDCCKFDuplicateRemover : public TrackFindingCDC::Findlet<CDCCKFResult> {
30  public:
32  {
36  }
37 
39  void exposeParameters(ModuleParamList* moduleParamList, const std::string& prefix) override
40  {
41  m_filter_badTracks.exposeParameters(moduleParamList, TrackFindingCDC::prefixed("badTracks", prefix));
42  m_filter_duplicateTrack.exposeParameters(moduleParamList, TrackFindingCDC::prefixed("duplicateTrack", prefix));
43  m_filter_duplicateSeed.exposeParameters(moduleParamList, TrackFindingCDC::prefixed("duplicateSeed", prefix));
44 
45  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "duplicateSeed_maxPhi"),
47  "Seeds within this dPhi can be considered as duplicates (-1 to neglect)",
49 
50  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "duplicateSeed_maxTheta"),
52  "Seeds within this dTheta can be considered as duplicates (-1 to neglect)",
54  }
55 
57  void apply(std::vector<CDCCKFResult>& results) override
58  {
59  B2DEBUG(29, "CDCCKFDuplicateRemover: " << results.size() << " paths created (might be without any hits)");
60 
61  std::vector<CDCCKFResult> goodResults;
62 
63  // Additional filter (typically check if charge of reconstructed track is equal to charge of seed)
64  TrackFindingCDC::Weight weight;
65  std::unordered_map<double, CDCCKFResult> resultToWeightList;
66  for (const auto& result : results) {
67  weight = m_filter_badTracks(result);
68  if (not std::isnan(weight)) {
69  goodResults.push_back(result);
70  }
71  }
72 
73  int n_goodresults = goodResults.size();
74 
75  B2DEBUG(29, "CDCCKFDuplicateRemover: " << goodResults.size() << " paths created (after filtering)");
76 
77  if (n_goodresults > 1) {
78  for (const auto& result : goodResults) {
79  B2DEBUG(29, "charge = " << result.front().getSeed()->getChargeSeed() << "; "
80  << "theta = " << result.front().getSeed()->getPositionSeed().Theta() * 180. / M_PI << "; "
81  << (result.size() - 1) << " hits (" << result.at(1).getWireHit()->getWire().getICLayer() << "->" <<
82  result.back().getWireHit()->getWire().getICLayer() << "); "
83  << "r/z = " << result.front().getSeed()->getPositionSeed().Perp() << "; " << result.front().getSeed()->getPositionSeed().Z());
84  }
85  }
86 
87  // If both charge assumptions lead to a good track, only pick one to avoid duplicate tracks
88  auto iter = goodResults.begin();
89  while (iter < goodResults.end()) {
90  auto iter2 = iter + 1;
91  bool increaseIter = true;
92  while (iter2 < goodResults.end()) {
93  // find tracks from same seed
94  if (iter2->front().getSeed()->getRelated<ECLShower>() == iter2->front().getSeed()->getRelated<ECLShower>()) {
95  // let filter decide which one to keep
96  bool selectFirst = m_filter_duplicateTrack({&*iter, &*iter2}) > 0;
97  if (selectFirst) {
98  iter2 = goodResults.erase(iter2);
99  } else {
100  iter = goodResults.erase(iter);
101  increaseIter = false;
102  break;
103  }
104  } else {
105  ++iter2;
106  }
107  }
108  if (increaseIter) {
109  ++iter;
110  }
111  }
112 
113  B2DEBUG(29, "CDCCKFDuplicateRemover: " << goodResults.size() << " paths created (after duplicates)");
114 
115  if (n_goodresults > 1) {
116  for (const auto& result : goodResults) {
117  B2DEBUG(29, "charge = " << result.front().getSeed()->getChargeSeed() << "; "
118  << "theta = " << result.front().getSeed()->getPositionSeed().Theta() * 180. / M_PI << "; "
119  << (result.size() - 1) << " hits (" << result.at(1).getWireHit()->getWire().getICLayer() << "->" <<
120  result.back().getWireHit()->getWire().getICLayer() << "); "
121  << "r/z = " << result.front().getSeed()->getPositionSeed().Perp() << "; " << result.front().getSeed()->getPositionSeed().Z());
122  }
123  }
124 
125  // Remove duplicate tracks from Bremsstrahlung
126  // Be careful as this might also remove photon conversions (m_filter_duplicateSeed decides if both should be kept)
127  iter = goodResults.begin();
128  while (iter < goodResults.end()) {
129  double phiClus = iter->front().getSeed()->getPositionSeed().Phi();
130  double thetaClus = iter->front().getSeed()->getPositionSeed().Theta();
131 
132  auto iter2 = iter + 1;
133  bool increaseIter = true;
134  while (iter2 < goodResults.end()) {
135  // find tracks from close-by seeds (use small strip in phi direction as expected from Bremsstrahlung)
136  // to disregard this filter set duplicateSeed_maxPhi and duplicateSeed_maxTheta to negative values
137  if (std::abs(TVector2::Phi_mpi_pi(iter2->front().getSeed()->getPositionSeed().Phi() - phiClus)) < duplicateSeed_maxPhi
138  && std::abs(iter2->front().getSeed()->getPositionSeed().Theta() - thetaClus) < duplicateSeed_maxTheta) {
139  // let filter decide which one to keep
140  bool isDuplicate = m_filter_duplicateSeed({&*iter, &*iter2}) > 0;
141  if (! isDuplicate) {
142  B2DEBUG(29, "Keeping both tracks");
143  ++iter2;
144  } else {
145  B2DEBUG(29, "Duplicate hits found");
146  bool selectFirst = m_filter_duplicateTrack({&*iter, &*iter2}) > 0;
147  if (selectFirst) {
148  iter2 = goodResults.erase(iter2);
149  } else {
150  iter = goodResults.erase(iter);
151  increaseIter = false;
152  break;
153  }
154  }
155  } else {
156  ++iter2;
157  }
158  }
159  if (increaseIter) {
160  ++iter;
161  }
162  }
163 
164  results = goodResults;
165 
166  B2DEBUG(29, "CDCCKFDuplicateRemover: " << results.size() << " paths created (after merging)");
167 
168  if (n_goodresults > 1) {
169  for (const auto& result : results) {
170  B2DEBUG(29, "charge = " << result.front().getSeed()->getChargeSeed() << "; "
171  << "theta = " << result.front().getSeed()->getPositionSeed().Theta() * 180. / M_PI << "; "
172  << (result.size() - 1) << " hits (" << result.at(1).getWireHit()->getWire().getICLayer() << "->" <<
173  result.back().getWireHit()->getWire().getICLayer() << "); "
174  << "r/z = " << result.front().getSeed()->getPositionSeed().Perp() << "; " << result.front().getSeed()->getPositionSeed().Z());
175  }
176  }
177  }
178 
179  private:
186 
188  double duplicateSeed_maxPhi = 2.;
191 
192  };
194 }
Remove duplicate paths created from ECLShowers These typically come from the seeding with two charge ...
TrackFindingCDC::ChooseableFilter< CDCPathPairFilterFactory > m_filter_duplicateTrack
Filter to remove duplicates from helix extrapolation (2 charge assumptions)
TrackFindingCDC::ChooseableFilter< CDCPathPairFilterFactory > m_filter_duplicateSeed
Merge duplicate paths (mostly seeds from Bremstrahlung)
TrackFindingCDC::ChooseableFilter< CDCPathFilterFactory > m_filter_badTracks
Filter to remove badly reconstructed tracks (e.g. wrongly assigned charge)
double duplicateSeed_maxPhi
Seeds within this dPhi can be considered as duplicates.
void apply(std::vector< CDCCKFResult > &results) override
main method of the findlet, merges and filters paths
double duplicateSeed_maxTheta
Seeds within this dTheta can be considered as duplicates.
void exposeParameters(ModuleParamList *moduleParamList, const std::string &prefix) override
Expose the parameters of the sub findlets.
Class to store ECL Showers.
Definition: ECLShower.h:25
The Module parameter list class.
T * getRelated(const std::string &name="", const std::string &namedRelation="") const
Get the object to or from which this object has a relation.
Convenvience wrapper to setup a Chooseable filter from a specific factory object.
void addProcessingSignalListener(ProcessingSignalListener *psl)
Register a processing signal listener to be notified.
Interface for a minimal algorithm part that wants to expose some parameters to a module.
Definition: Findlet.h:26
void addParameter(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module list.
Abstract base class for different kinds of events.