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/ckf/cdc/filters/paths/CDCPathFilterFactory.h>
14
15#include <tracking/ckf/cdc/filters/pathPairs/CDCPathPairFilterFactory.h>
16#include <tracking/trackFindingCDC/filters/base/ChooseableFilter.icc.h>
17
18#include <ecl/dataobjects/ECLShower.h>
19
20#include <Math/VectorUtil.h>
21
22namespace Belle2 {
29 class CDCCKFDuplicateRemover : public TrackFindingCDC::Findlet<CDCCKFResult> {
30 public:
31 CDCCKFDuplicateRemover()
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().Rho() << "; " << 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(std::pair(&*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().Rho() << "; " << 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(ROOT::Math::VectorUtil::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(std::pair(&*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(std::pair(&*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().Rho() << "; " << result.front().getSeed()->getPositionSeed().Z());
175 }
176 }
177 }
178
179 private:
186
191
192 };
193
194}
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.
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.