Belle II Software development
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
23namespace 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(std::pair(&*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(std::pair(&*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(std::pair(&*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
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.