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