Belle II Software development
BridgingWireHitRelationFilter.cc
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#include <tracking/trackFindingCDC/filters/wireHitRelation/BridgingWireHitRelationFilter.h>
9
10#include <tracking/trackingUtilities/filters/base/RelationFilter.icc.h>
11
12#include <tracking/trackingUtilities/eventdata/hits/CDCWireHit.h>
13
14#include <cdc/topology/CDCWireTopology.h>
15#include <cdc/topology/CDCWire.h>
16
17#include <tracking/trackingUtilities/utilities/Relation.h>
18#include <tracking/trackingUtilities/utilities/VectorRange.h>
19#include <tracking/trackingUtilities/utilities/Functional.h>
20#include <tracking/trackingUtilities/utilities/StringManipulation.h>
21
22#include <framework/core/ModuleParamList.templateDetails.h>
23
24#include <vector>
25#include <string>
26
27using namespace Belle2;
28using namespace CDC;
29using namespace TrackFindingCDC;
30using namespace TrackingUtilities;
31
33
35
37
39 const std::string& prefix)
40{
41 moduleParamList
42 ->addParameter(prefixed(prefix, "missingPrimaryNeighborThresholds"),
44 "Map of o'clock directions to number of missing drift cells "
45 "in the primary neighborhood to trigger the inclusion of secondary neighbors "
46 "in that very o'clock direction",
48}
49
51{
53 for (short oClockDirection = 0; oClockDirection < 12; oClockDirection++) {
54 m_missingPrimaryNeighborThresholds[oClockDirection] = 3;
55 if (m_param_missingPrimaryNeighborThresholdMap.count(oClockDirection)) {
56 m_missingPrimaryNeighborThresholds[oClockDirection] =
58 }
59 }
60
62 for (short oClockDirection : {5, 6, 7, 4, 8, 3, 9, 2, 10, 1, 0, 11}) {
63 if (m_missingPrimaryNeighborThresholds[oClockDirection] < 3) {
64 m_consideredSecondaryNeighbors.push_back(oClockDirection);
65 }
66 }
67}
68
69void BridgingWireHitRelationFilter::prepare(const std::vector<CDCWireHit*>& wireHits)
70{
71 m_preparedWires.clear();
72 m_preparedWires.reserve(wireHits.size());
73 for (const CDCWireHit* wireHit : wireHits) {
74 m_preparedWires.push_back(&wireHit->getWire());
75 }
76 m_preparedWireHitsData = wireHits.data();
77 m_preparedWireHitsSize = wireHits.size();
78}
79
81 CDCWireHit* from,
82 const std::vector<CDCWireHit*>& wireHits) const
83{
84 // Use the wires precomputed by prepare() when called with the prepared vector.
85 // The comparison LessOf<Deref>() used below resolves to operator<(CDCWireHit, CDCWire),
86 // which compares the *address* of the wire of the hit with the address of the wire.
87 // Searching the precomputed wire addresses therefore evaluates exactly the same
88 // predicate on exactly the same values, only without dereferencing the wire hits.
89 const bool prepared =
90 wireHits.data() == m_preparedWireHitsData and wireHits.size() == m_preparedWireHitsSize;
91
92 auto findWireHitRange = [&](const CDCWire * neighborWire) -> ConstVectorRange<CDCWireHit*> {
93 if (prepared)
94 {
95 const auto itRange = std::equal_range(m_preparedWires.begin(), m_preparedWires.end(), neighborWire);
96 return {
97 wireHits.begin() + (itRange.first - m_preparedWires.begin()),
98 wireHits.begin() + (itRange.second - m_preparedWires.begin())};
99 }
100 return ConstVectorRange<CDCWireHit*>{
101 std::equal_range(wireHits.begin(), wireHits.end(), neighborWire, LessOf<Deref>())
102 };
103 };
104
105 // Stack buffer for the wire neighbors - at most 6 primary
106 // respectively 12 secondary neighbors can be collected
107 std::array<std::pair<const CDCWire*, int>, 12> wireNeighbors;
108 int nWireNeighbors = 0;
109
110 std::vector<CDCWireHit*> wireHitNeighbors;
111 wireHitNeighbors.reserve(12);
112
113 std::array<short, 12> missingPrimaryNeighbor = {0};
114
115 const CDCWireTopology& wireTopology = CDCWireTopology::getInstance();
116
117 const CDCWire& wire = from->getWire();
118
119 // Analyse primary neighborhood - sorted such that the wire hits relations are most likely sorted.
120 for (short oClockDirection : {5, 7, 3, 9, 1, 11}) {
121 MayBePtr<const CDCWire> neighborWire = wireTopology.getPrimaryNeighbor(oClockDirection, wire);
122 if (neighborWire) wireNeighbors[nWireNeighbors++] = {neighborWire, oClockDirection};
123 }
124
125 std::sort(wireNeighbors.begin(), wireNeighbors.begin() + nWireNeighbors);
126
127 for (std::pair<const CDCWire*, int> wireAndOClockDirection :
128 asRange(wireNeighbors.begin(), wireNeighbors.begin() + nWireNeighbors)) {
129 const CDCWire* neighborWire = wireAndOClockDirection.first;
130 // cppcheck-suppress variableScope ; declaration kept at this scope for readability
131 int oClockDirection = wireAndOClockDirection.second;
132
133 ConstVectorRange<CDCWireHit*> wireHitRange = findWireHitRange(neighborWire);
134 if (wireHitRange.empty()) {
135 int ccwOClockDirection = oClockDirection - 1;
136 int cwOClockDirection = oClockDirection == 11 ? 0 : oClockDirection + 1;
137 ++missingPrimaryNeighbor[ccwOClockDirection];
138 ++missingPrimaryNeighbor[oClockDirection];
139 ++missingPrimaryNeighbor[cwOClockDirection];
140 }
141 wireHitNeighbors.insert(wireHitNeighbors.end(), wireHitRange.begin(), wireHitRange.end());
142 }
143
144 size_t nPrimaryWireHitNeighbors = wireHitNeighbors.size();
145 nWireNeighbors = 0;
146
147 // Analyse secondary neighborhood
148 for (short oClockDirection : m_consideredSecondaryNeighbors) {
149 MayBePtr<const CDCWire> neighborWire = wireTopology.getSecondaryNeighbor(oClockDirection, wire);
150 if (not neighborWire) continue;
151 if (missingPrimaryNeighbor[oClockDirection] <
152 m_missingPrimaryNeighborThresholds[oClockDirection])
153 continue;
154 wireNeighbors[nWireNeighbors++] = {neighborWire, oClockDirection};
155 }
156
157 std::sort(wireNeighbors.begin(), wireNeighbors.begin() + nWireNeighbors);
158
159 for (std::pair<const CDCWire*, int> wireAndOClockDirection :
160 asRange(wireNeighbors.begin(), wireNeighbors.begin() + nWireNeighbors)) {
161 const CDCWire* neighborWire = wireAndOClockDirection.first;
162 ConstVectorRange<CDCWireHit*> wireHitRange = findWireHitRange(neighborWire);
163 wireHitNeighbors.insert(wireHitNeighbors.end(), wireHitRange.begin(), wireHitRange.end());
164 }
165
167 std::inplace_merge(wireHitNeighbors.begin(),
168 wireHitNeighbors.begin() + nPrimaryWireHitNeighbors,
169 wireHitNeighbors.end(),
170 std::less<CDCWireHit*>());
171
172 return wireHitNeighbors;
173}
Class representing the sense wire arrangement in the whole of the central drift chamber.
TrackingUtilities::MayBePtr< const CDCWire > getSecondaryNeighbor(short oClockDirection, const WireID &wireID) const
Getter for the secondary neighbor of the given wire id.
TrackingUtilities::MayBePtr< const CDCWire > getPrimaryNeighbor(short oClockDirection, const WireID &wireID) const
Getter for the primary neighbor of the given wire id.
static CDCWireTopology & getInstance()
Getter for the singleton instance of the wire topology.
Class representing a sense wire in the central drift chamber.
Definition CDCWire.h:50
The Module parameter list class.
std::map< int, int > m_param_missingPrimaryNeighborThresholdMap
Parameter: A map from o'clock direction to the number of missing primary drift cells.
void prepare(const std::vector< TrackingUtilities::CDCWireHit * > &wireHits)
Precompute the wires of the given wire hits to speed up the searches in the following getPossibleTos ...
~BridgingWireHitRelationFilter() override
Default destructor.
TrackingUtilities::CDCWireHit *const * m_preparedWireHitsData
Data pointer of the prepared wire hit vector used to recognize it in getPossibleTos.
void initialize() override
Receive signal at the begin of the event processing and prepare some parameters.
std::vector< TrackingUtilities::CDCWireHit * > getPossibleTos(TrackingUtilities::CDCWireHit *from, const std::vector< TrackingUtilities::CDCWireHit * > &wireHits) const final
Returns a vector containing the neighboring wire hits of the given wire hit out of the sorted range g...
std::array< short, 12 > m_missingPrimaryNeighborThresholds
Array for the number of primary drift cells to be included for the o'clock position at each index.
std::vector< const CDC::CDCWire * > m_preparedWires
Memory for the wires of the prepared wire hit vector.
void exposeParameters(ModuleParamList *moduleParamList, const std::string &prefix) override
Expose the set of parameters of the filter to the module parameter list.
std::size_t m_preparedWireHitsSize
Size of the prepared wire hit vector used to recognize it in getPossibleTos.
std::vector< short > m_consideredSecondaryNeighbors
Indices of the considered o'clock positions of the secondary neighborhood.
Class representing a hit wire in the central drift chamber.
Definition CDCWireHit.h:56
Iterator begin() const
Begin of the range for range based for.
Definition Range.h:64
Iterator end() const
End of the range for range based for.
Definition Range.h:68
bool empty() const
Checks if the begin equals the end iterator, hence if the range is empty.
Definition Range.h:72
Base class for filtering the neighborhood of objects.
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.