Belle II Software  release-08-01-10
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 <tracking/trackFindingCDC/filters/base/ChooseableFilter.h>
14 #include <tracking/ckf/cdc/filters/paths/CDCPathFilterFactory.h>
15 
16 #include <tracking/ckf/cdc/filters/pathPairs/CDCPathPairFilterFactory.h>
17 #include <tracking/trackFindingCDC/filters/base/ChooseableFilter.icc.h>
18 
19 #include <ecl/dataobjects/ECLShower.h>
20 
21 #include <Math/VectorUtil.h>
22 
23 namespace Belle2 {
30  class CDCCKFDuplicateRemover : public TrackFindingCDC::Findlet<CDCCKFResult> {
31  public:
33  {
37  }
38 
40  void exposeParameters(ModuleParamList* moduleParamList, const std::string& prefix) override
41  {
42  m_filter_badTracks.exposeParameters(moduleParamList, TrackFindingCDC::prefixed("badTracks", prefix));
43  m_filter_duplicateTrack.exposeParameters(moduleParamList, TrackFindingCDC::prefixed("duplicateTrack", prefix));
44  m_filter_duplicateSeed.exposeParameters(moduleParamList, TrackFindingCDC::prefixed("duplicateSeed", prefix));
45 
46  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "duplicateSeed_maxPhi"),
48  "Seeds within this dPhi can be considered as duplicates (-1 to neglect)",
50 
51  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "duplicateSeed_maxTheta"),
53  "Seeds within this dTheta can be considered as duplicates (-1 to neglect)",
55  }
56 
58  void apply(std::vector<CDCCKFResult>& results) override
59  {
60  B2DEBUG(29, "CDCCKFDuplicateRemover: " << results.size() << " paths created (might be without any hits)");
61 
62  std::vector<CDCCKFResult> goodResults;
63 
64  // Additional filter (typically check if charge of reconstructed track is equal to charge of seed)
65  TrackFindingCDC::Weight weight;
66  std::unordered_map<double, CDCCKFResult> resultToWeightList;
67  for (const auto& result : results) {
68  weight = m_filter_badTracks(result);
69  if (not std::isnan(weight)) {
70  goodResults.push_back(result);
71  }
72  }
73 
74  int n_goodresults = goodResults.size();
75 
76  B2DEBUG(29, "CDCCKFDuplicateRemover: " << goodResults.size() << " paths created (after filtering)");
77 
78  if (n_goodresults > 1) {
79  for (const auto& result : goodResults) {
80  B2DEBUG(29, "charge = " << result.front().getSeed()->getChargeSeed() << "; "
81  << "theta = " << result.front().getSeed()->getPositionSeed().Theta() * 180. / M_PI << "; "
82  << (result.size() - 1) << " hits (" << result.at(1).getWireHit()->getWire().getICLayer() << "->" <<
83  result.back().getWireHit()->getWire().getICLayer() << "); "
84  << "r/z = " << result.front().getSeed()->getPositionSeed().Rho() << "; " << result.front().getSeed()->getPositionSeed().Z());
85  }
86  }
87 
88  // If both charge assumptions lead to a good track, only pick one to avoid duplicate tracks
89  auto iter = goodResults.begin();
90  while (iter < goodResults.end()) {
91  auto iter2 = iter + 1;
92  bool increaseIter = true;
93  while (iter2 < goodResults.end()) {
94  // find tracks from same seed
95  if (iter2->front().getSeed()->getRelated<ECLShower>() == iter2->front().getSeed()->getRelated<ECLShower>()) {
96  // let filter decide which one to keep
97  bool selectFirst = m_filter_duplicateTrack({&*iter, &*iter2}) > 0;
98  if (selectFirst) {
99  iter2 = goodResults.erase(iter2);
100  } else {
101  iter = goodResults.erase(iter);
102  increaseIter = false;
103  break;
104  }
105  } else {
106  ++iter2;
107  }
108  }
109  if (increaseIter) {
110  ++iter;
111  }
112  }
113 
114  B2DEBUG(29, "CDCCKFDuplicateRemover: " << goodResults.size() << " paths created (after duplicates)");
115 
116  if (n_goodresults > 1) {
117  for (const auto& result : goodResults) {
118  B2DEBUG(29, "charge = " << result.front().getSeed()->getChargeSeed() << "; "
119  << "theta = " << result.front().getSeed()->getPositionSeed().Theta() * 180. / M_PI << "; "
120  << (result.size() - 1) << " hits (" << result.at(1).getWireHit()->getWire().getICLayer() << "->" <<
121  result.back().getWireHit()->getWire().getICLayer() << "); "
122  << "r/z = " << result.front().getSeed()->getPositionSeed().Rho() << "; " << result.front().getSeed()->getPositionSeed().Z());
123  }
124  }
125 
126  // Remove duplicate tracks from Bremsstrahlung
127  // Be careful as this might also remove photon conversions (m_filter_duplicateSeed decides if both should be kept)
128  iter = goodResults.begin();
129  while (iter < goodResults.end()) {
130  double phiClus = iter->front().getSeed()->getPositionSeed().Phi();
131  double thetaClus = iter->front().getSeed()->getPositionSeed().Theta();
132 
133  auto iter2 = iter + 1;
134  bool increaseIter = true;
135  while (iter2 < goodResults.end()) {
136  // find tracks from close-by seeds (use small strip in phi direction as expected from Bremsstrahlung)
137  // to disregard this filter set duplicateSeed_maxPhi and duplicateSeed_maxTheta to negative values
138  if (std::abs(ROOT::Math::VectorUtil::Phi_mpi_pi(iter2->front().getSeed()->getPositionSeed().Phi() - phiClus)) < duplicateSeed_maxPhi
139  && std::abs(iter2->front().getSeed()->getPositionSeed().Theta() - thetaClus) < duplicateSeed_maxTheta) {
140  // let filter decide which one to keep
141  bool isDuplicate = m_filter_duplicateSeed({&*iter, &*iter2}) > 0;
142  if (! isDuplicate) {
143  B2DEBUG(29, "Keeping both tracks");
144  ++iter2;
145  } else {
146  B2DEBUG(29, "Duplicate hits found");
147  bool selectFirst = m_filter_duplicateTrack({&*iter, &*iter2}) > 0;
148  if (selectFirst) {
149  iter2 = goodResults.erase(iter2);
150  } else {
151  iter = goodResults.erase(iter);
152  increaseIter = false;
153  break;
154  }
155  }
156  } else {
157  ++iter2;
158  }
159  }
160  if (increaseIter) {
161  ++iter;
162  }
163  }
164 
165  results = goodResults;
166 
167  B2DEBUG(29, "CDCCKFDuplicateRemover: " << results.size() << " paths created (after merging)");
168 
169  if (n_goodresults > 1) {
170  for (const auto& result : results) {
171  B2DEBUG(29, "charge = " << result.front().getSeed()->getChargeSeed() << "; "
172  << "theta = " << result.front().getSeed()->getPositionSeed().Theta() * 180. / M_PI << "; "
173  << (result.size() - 1) << " hits (" << result.at(1).getWireHit()->getWire().getICLayer() << "->" <<
174  result.back().getWireHit()->getWire().getICLayer() << "); "
175  << "r/z = " << result.front().getSeed()->getPositionSeed().Rho() << "; " << result.front().getSeed()->getPositionSeed().Z());
176  }
177  }
178  }
179 
180  private:
187 
189  double duplicateSeed_maxPhi = 2.;
192 
193  };
195 }
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:30
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.