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#include <cassert>
27
28using namespace Belle2;
29using namespace CDC;
30using namespace TrackFindingCDC;
31using namespace TrackingUtilities;
32
34
36
38
40 const std::string& prefix)
41{
42 moduleParamList
43 ->addParameter(prefixed(prefix, "missingPrimaryNeighborThresholds"),
45 "Map of o'clock directions to number of missing drift cells "
46 "in the primary neighborhood to trigger the inclusion of secondary neighbors "
47 "in that very o'clock direction",
49}
50
52{
54 for (short oClockDirection = 0; oClockDirection < 12; oClockDirection++) {
55 m_missingPrimaryNeighborThresholds[oClockDirection] = 3;
56 if (m_param_missingPrimaryNeighborThresholdMap.count(oClockDirection)) {
57 m_missingPrimaryNeighborThresholds[oClockDirection] =
59 }
60 }
61
63 for (short oClockDirection : {5, 6, 7, 4, 8, 3, 9, 2, 10, 1, 0, 11}) {
64 if (m_missingPrimaryNeighborThresholds[oClockDirection] < 3) {
65 m_consideredSecondaryNeighbors.push_back(oClockDirection);
66 }
67 }
68}
69
70void BridgingWireHitRelationFilter::prepare(const std::vector<CDCWireHit*>& wireHits)
71{
72 m_preparedWires.clear();
73 m_preparedWires.reserve(wireHits.size());
74 for (const CDCWireHit* wireHit : wireHits) {
75 m_preparedWires.push_back(&wireHit->getWire());
76 }
77 m_preparedWireHitsData = wireHits.data();
78 m_preparedWireHitsSize = wireHits.size();
79}
80
82 CDCWireHit* from,
83 const std::vector<CDCWireHit*>& wireHits) const
84{
85 assert(std::is_sorted(wireHits.begin(), wireHits.end(), LessOf<Deref>()) &&
86 "Expected wire hits to be sorted");
87
88 // Use the wires precomputed by prepare() when called with the prepared vector.
89 // The wire hits are sorted by the address of their wire such that a search in the
90 // contiguous wire array gives the same ranges without dereferencing the wire hits.
91 const bool prepared =
92 wireHits.data() == m_preparedWireHitsData and wireHits.size() == m_preparedWireHitsSize;
93
94 auto findWireHitRange = [&](const CDCWire * neighborWire) -> ConstVectorRange<CDCWireHit*> {
95 if (prepared)
96 {
97 const auto itRange = std::equal_range(m_preparedWires.begin(), m_preparedWires.end(), neighborWire);
98 return {
99 wireHits.begin() + (itRange.first - m_preparedWires.begin()),
100 wireHits.begin() + (itRange.second - m_preparedWires.begin())};
101 }
102 return ConstVectorRange<CDCWireHit*>{
103 std::equal_range(wireHits.begin(), wireHits.end(), neighborWire, LessOf<Deref>())
104 };
105 };
106
107 // Stack buffer for the wire neighbors - at most 6 primary
108 // respectively 12 secondary neighbors can be collected
109 std::array<std::pair<const CDCWire*, int>, 12> wireNeighbors;
110 int nWireNeighbors = 0;
111
112 std::vector<CDCWireHit*> wireHitNeighbors;
113 wireHitNeighbors.reserve(12);
114
115 std::array<short, 12> missingPrimaryNeighbor = {0};
116
117 const CDCWireTopology& wireTopology = CDCWireTopology::getInstance();
118
119 const CDCWire& wire = from->getWire();
120
121 // Analyse primary neighborhood - sorted such that the wire hits relations are most likely sorted.
122 for (short oClockDirection : {5, 7, 3, 9, 1, 11}) {
123 MayBePtr<const CDCWire> neighborWire = wireTopology.getPrimaryNeighbor(oClockDirection, wire);
124 if (neighborWire) wireNeighbors[nWireNeighbors++] = {neighborWire, oClockDirection};
125 }
126
127 std::sort(wireNeighbors.begin(), wireNeighbors.begin() + nWireNeighbors);
128
129 for (std::pair<const CDCWire*, int> wireAndOClockDirection :
130 asRange(wireNeighbors.begin(), wireNeighbors.begin() + nWireNeighbors)) {
131 const CDCWire* neighborWire = wireAndOClockDirection.first;
132 // cppcheck-suppress variableScope ; declaration kept at this scope for readability
133 int oClockDirection = wireAndOClockDirection.second;
134
135 ConstVectorRange<CDCWireHit*> wireHitRange = findWireHitRange(neighborWire);
136 if (wireHitRange.empty()) {
137 int ccwOClockDirection = oClockDirection - 1;
138 int cwOClockDirection = oClockDirection == 11 ? 0 : oClockDirection + 1;
139 ++missingPrimaryNeighbor[ccwOClockDirection];
140 ++missingPrimaryNeighbor[oClockDirection];
141 ++missingPrimaryNeighbor[cwOClockDirection];
142 }
143 wireHitNeighbors.insert(wireHitNeighbors.end(), wireHitRange.begin(), wireHitRange.end());
144 }
145
146 size_t nPrimaryWireHitNeighbors = wireHitNeighbors.size();
147 nWireNeighbors = 0;
148
149 // Analyse secondary neighborhood
150 for (short oClockDirection : m_consideredSecondaryNeighbors) {
151 MayBePtr<const CDCWire> neighborWire = wireTopology.getSecondaryNeighbor(oClockDirection, wire);
152 if (not neighborWire) continue;
153 if (missingPrimaryNeighbor[oClockDirection] <
154 m_missingPrimaryNeighborThresholds[oClockDirection])
155 continue;
156 wireNeighbors[nWireNeighbors++] = {neighborWire, oClockDirection};
157 }
158
159 std::sort(wireNeighbors.begin(), wireNeighbors.begin() + nWireNeighbors);
160
161 for (std::pair<const CDCWire*, int> wireAndOClockDirection :
162 asRange(wireNeighbors.begin(), wireNeighbors.begin() + nWireNeighbors)) {
163 const CDCWire* neighborWire = wireAndOClockDirection.first;
164 ConstVectorRange<CDCWireHit*> wireHitRange = findWireHitRange(neighborWire);
165 wireHitNeighbors.insert(wireHitNeighbors.end(), wireHitRange.begin(), wireHitRange.end());
166 }
167
169 std::inplace_merge(wireHitNeighbors.begin(),
170 wireHitNeighbors.begin() + nPrimaryWireHitNeighbors,
171 wireHitNeighbors.end(),
172 std::less<CDCWireHit*>());
173
174 return wireHitNeighbors;
175}
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.