Belle II Software development
SegmentCreatorFacetAutomaton.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/findlets/minimal/SegmentCreatorFacetAutomaton.h>
9
10#include <tracking/trackFindingCDC/eventdata/segments/CDCSegment2D.h>
11#include <tracking/trackFindingCDC/eventdata/segments/CDCFacetSegment.h>
12#include <tracking/trackFindingCDC/eventdata/segments/CDCRLWireHitSegment.h>
13
14#include <tracking/trackFindingCDC/eventdata/hits/CDCFacet.h>
15
16#include <tracking/trackFindingCDC/topology/CDCWire.h>
17
18#include <tracking/trackFindingCDC/utilities/WeightedRelation.h>
19#include <tracking/trackFindingCDC/utilities/Functional.h>
20#include <tracking/trackFindingCDC/utilities/VectorRange.h>
21#include <tracking/trackFindingCDC/utilities/StringManipulation.h>
22#include <tracking/trackFindingCDC/utilities/Algorithms.h>
23
24#include <framework/core/ModuleParamList.templateDetails.h>
25
26#include <algorithm>
27#include <functional>
28
29using namespace Belle2;
30using namespace TrackFindingCDC;
31
32namespace {
33 void setRLWireHit(CDCRLWireHitTriple& rlWireHitTriple, int iRLWireHit, const CDCRLWireHit& rlWireHit)
34 {
35 if (iRLWireHit == 0) {
36 rlWireHitTriple.setStartRLWireHit(rlWireHit);
37 } else if (iRLWireHit == 1) {
38 rlWireHitTriple.setMiddleRLWireHit(rlWireHit);
39 } else if (iRLWireHit == 2) {
40 rlWireHitTriple.setEndRLWireHit(rlWireHit);
41 } else {
42 B2ASSERT("", false);
43 }
44 }
45}
46
48{
49 return "Constructs segments by extraction of facet paths in a cellular automaton.";
50}
51
52void SegmentCreatorFacetAutomaton::exposeParameters(ModuleParamList* moduleParamList, const std::string& prefix)
53{
54 moduleParamList->addParameter(prefixed(prefix, "searchReversed"),
56 "Switch to construct the reversed segment if it is available in the facet graph as well.",
58
59 moduleParamList->addParameter(prefixed(prefix, "searchAlias"),
61 "Switch to construct the alias segment if it is available in the facet graph as well.",
63
64 moduleParamList->addParameter(prefixed(prefix, "relaxSingleLayerSearch"),
66 "Switch to relax the alias and reverse search for segments contained in a single layer.",
68
69 moduleParamList->addParameter(prefixed(prefix, "allSingleAliases"),
71 "Switch to activate the write out of all available orientations of single facet segments.",
73}
74
76 const std::vector<CDCFacet>& inputFacets,
77 const std::vector<WeightedRelation<const CDCFacet>>& inputFacetRelations,
78 std::vector<CDCSegment2D>& outputSegments)
79{
80 std::vector<ConstVectorRange<CDCFacet>> facetsByICluster =
81 adjacent_groupby(inputFacets.begin(), inputFacets.end(), std::mem_fn(&CDCFacet::getICluster));
82
83 for (const ConstVectorRange<CDCFacet>& facetsInCluster : facetsByICluster) {
84 if (facetsInCluster.empty()) continue;
85
86 B2ASSERT("Expect the facets to be sorted",
87 std::is_sorted(std::begin(facetsInCluster), std::end(facetsInCluster)));
88
89 // Obtain the facets as pointers
90 std::vector<const CDCFacet*> facetPtrsInCluster = as_pointers<const CDCFacet>(facetsInCluster);
91
92 // Cut out the chunk of relevant facet relations
93 const CDCFacet& firstFacet = facetsInCluster.front();
94 auto beginFacetRelationInCluster =
95 std::lower_bound(inputFacetRelations.begin(), inputFacetRelations.end(), &firstFacet);
96
97 const CDCFacet& lastFacet = facetsInCluster.back();
98 auto endFacetRelationInCluster =
99 std::upper_bound(inputFacetRelations.begin(), inputFacetRelations.end(), &lastFacet);
100
101 const int iCluster = firstFacet.getICluster();
102
103 std::vector<WeightedRelation<const CDCFacet>>
104 facetRelationsInCluster(beginFacetRelationInCluster,
105 endFacetRelationInCluster);
106
107 // Apply the cellular automaton in a multipass manner
108 m_facetPaths.clear();
109 m_cellularPathFinder.apply(facetPtrsInCluster, facetRelationsInCluster, m_facetPaths);
110
111 // Helper function to check if a given reverse or alias segment is
112 // also present in the graph of facets. Used in the search for
113 // aliasing segments.
114 auto getFacetPath = [&facetsInCluster,
115 &facetRelationsInCluster,
116 &iCluster](const CDCSegment2D & segment, bool checkRelations = true) {
117 CDCRLWireHitSegment rlWireHitSegment = segment.getRLWireHitSegment();
118 CDCFacetSegment aliasFacetSegment = CDCFacetSegment::create(rlWireHitSegment);
119 std::vector<const CDCFacet*> facetPath;
120 for (CDCRLWireHitTriple& rlWireHitTriple : aliasFacetSegment) {
121 // Do not forget to set the cluster id as it is a sorting criterion
122 rlWireHitTriple.setICluster(iCluster);
123
124 // Check whether the facet is a node in the graph
125 auto itFacet = std::lower_bound(facetsInCluster.begin(), facetsInCluster.end(), rlWireHitTriple);
126 if (itFacet == facetsInCluster.end()) break;
127 if (not(*itFacet == rlWireHitTriple)) break;
128 const CDCFacet* facet = &*itFacet;
129
130 // Check whether there is a relation to this new facet
131 if (not facetPath.empty() and checkRelations) {
132 const CDCFacet* fromFacet = facetPath.back();
133 auto relationsFromFacet = std::equal_range(facetRelationsInCluster.begin(),
134 facetRelationsInCluster.end(),
135 fromFacet);
136 if (std::count_if(relationsFromFacet.first, relationsFromFacet.second, Second() == facet) == 0) break;
137 }
138 facetPath.push_back(facet);
139 }
140 return facetPath;
141 };
142
143 // Reserve enough space to prevent reallocation and invalidated references
144 size_t additionalSpace = m_facetPaths.size();
145 if (m_param_searchReversed) additionalSpace *= 2;
146 if (m_param_searchAlias) additionalSpace *= 2;
147 outputSegments.reserve(outputSegments.size() + additionalSpace);
148
149 for (const std::vector<const CDCFacet*>& facetPath : m_facetPaths) {
150 // If path is only a single facet long - forward all viable orientations if requested
151 if (m_param_allSingleAliases and facetPath.size() == 1) {
152 const CDCFacet& originalSingleFacet = *facetPath.front();
153
154 int nSingleFacets = 0;
155
156 // Helper object to construct other single facet paths
157 std::vector<const CDCFacet*> singleFacetPath;
158 singleFacetPath.reserve(1);
159
160 std::array<int, 3> permIndices{0, 1, 2};
161 CDCRLWireHitTriple rlWireHitTriple = originalSingleFacet;
162
163 for (int iPerm = 0; iPerm < 6; ++iPerm) {
164 setRLWireHit(rlWireHitTriple, permIndices[0], originalSingleFacet.getStartRLWireHit());
165 setRLWireHit(rlWireHitTriple, permIndices[1], originalSingleFacet.getMiddleRLWireHit());
166 setRLWireHit(rlWireHitTriple, permIndices[2], originalSingleFacet.getEndRLWireHit());
167 std::next_permutation(permIndices.begin(), permIndices.end()); // Prepare for next round
168
169 for (ERightLeft startRLInfo : {ERightLeft::c_Left, ERightLeft::c_Right}) {
170 rlWireHitTriple.setStartRLInfo(startRLInfo);
171 for (ERightLeft middleRLInfo : {ERightLeft::c_Left, ERightLeft::c_Right}) {
172 rlWireHitTriple.setMiddleRLInfo(middleRLInfo);
173 for (ERightLeft endRLInfo : {ERightLeft::c_Left, ERightLeft::c_Right}) {
174 rlWireHitTriple.setEndRLInfo(endRLInfo);
175
176 auto itFacet = std::lower_bound(facetsInCluster.begin(),
177 facetsInCluster.end(),
178 rlWireHitTriple);
179
180 if (itFacet == facetsInCluster.end())continue;
181 if (not(*itFacet == rlWireHitTriple)) continue;
182
183 const CDCFacet* singleFacet = &*itFacet;
184 singleFacetPath.clear();
185 singleFacetPath.push_back(singleFacet);
186 outputSegments.push_back(CDCSegment2D::condense(singleFacetPath));
187 outputSegments.back()->setReverseFlag();
188 outputSegments.back()->setAliasFlag();
189 ++nSingleFacets;
190 }
191 }
192 }
193 }
194 B2ASSERT("At least one single facet added", nSingleFacets > 0);
195
196 // Skip the reset of the alias searches
197 continue;
198 }
199
200 outputSegments.reserve(outputSegments.size() + 4);
201 outputSegments.push_back(CDCSegment2D::condense(facetPath));
202 const CDCSegment2D* segment = &outputSegments.back();
203
204
205 // Check for the special situation where the segment is confined to one layer
206 // Relax the alias search a bit to better capture the situation
207 bool checkRelations = true;
209 auto differentILayer = [](const CDCRecoHit2D & lhs, const CDCRecoHit2D & rhs) {
210 return lhs.getWire().getILayer() != rhs.getWire().getILayer();
211 };
212 auto itLayerSwitch = std::adjacent_find(segment->begin(), segment->end(), differentILayer);
213 const bool onlyOneLayer = itLayerSwitch == segment->end();
214 checkRelations = not onlyOneLayer;
215 }
216
217 const CDCSegment2D* reverseSegment = nullptr;
219 std::vector<const CDCFacet*> reverseFacetPath = getFacetPath(segment->reversed(), checkRelations);
220 if (reverseFacetPath.size() == facetPath.size()) {
221 B2DEBUG(25, "Successful constructed REVERSE");
222 outputSegments.push_back(CDCSegment2D::condense(reverseFacetPath));
223 reverseSegment = &outputSegments.back();
224
225 (*segment)->setReverseFlag(true);
226 (*reverseSegment)->setReverseFlag(true);
227 }
228 }
229
230 if (not m_param_searchAlias) continue;
231
232 // Search for aliasing segment in the facet graph
233 int nRLSwitches = segment->getNRLSwitches();
234 if (nRLSwitches > 2) continue; // Segment is stable against aliases
235
236 const CDCSegment2D* aliasSegment = nullptr;
237 std::vector<const CDCFacet*> aliasFacetPath = getFacetPath(segment->getAlias(), checkRelations);
238 if (aliasFacetPath.size() == facetPath.size()) {
239 B2DEBUG(25, "Successful constructed alias");
240 outputSegments.push_back(CDCSegment2D::condense(aliasFacetPath));
241 aliasSegment = &outputSegments.back();
242
243 (*segment)->setAliasFlag(true);
244 (*aliasSegment)->setAliasFlag(true);
245 }
246
247 const CDCSegment2D* reverseAliasSegment = nullptr;
249 std::vector<const CDCFacet*> reverseAliasFacetPath =
250 getFacetPath(segment->reversed().getAlias(), checkRelations);
251 if (reverseAliasFacetPath.size() == facetPath.size()) {
252 B2DEBUG(25, "Successful constructed REVERSE alias");
253 outputSegments.push_back(CDCSegment2D::condense(reverseAliasFacetPath));
254 reverseAliasSegment = &outputSegments.back();
255 if (aliasSegment != nullptr) {
256 (*aliasSegment)->setReverseFlag(true);
257 (*reverseAliasSegment)->setReverseFlag(true);
258 }
259 }
260 }
261
262 if (reverseSegment != nullptr and reverseAliasSegment != nullptr) {
263 (*reverseSegment)->setAliasFlag(true);
264 (*reverseAliasSegment)->setAliasFlag(true);
265 }
266 }
267 }
268}
The Module parameter list class.
void setAliasFlag(bool setTo=true)
Sets the alias flag to the given value. Default value true.
void setReverseFlag(bool setTo=true)
Sets the reverse flag to the given value. Default value true.
A segment consisting of adjacent facets.
static CDCFacetSegment create(const CDCRLWireHitSegment &rlWireHitSegment)
Construct a train of facets from the given oriented wire hits.
Class representing a triple of neighboring oriented wire with additional trajectory information.
Definition: CDCFacet.h:32
A segment consisting of two dimensional reconstructed hits.
Class representing a triple of neighboring wire hits.
void setICluster(int iCluster)
Setter for the cluster id.
void setEndRLInfo(const ERightLeft endRLInfo)
Setter for the right left passage information of the third oriented wire hit.
void setEndRLWireHit(const CDCRLWireHit &endRLWireHit)
Setter for the third oriented wire hit.
CDCRLWireHit & getStartRLWireHit()
Getter for the first oriented wire hit.
void setMiddleRLInfo(const ERightLeft middleRLInfo)
Setter for the right left passage information of the second oriented wire hit.
void setMiddleRLWireHit(const CDCRLWireHit &middleRLWireHit)
Setter for the second oriented wire hit.
int getICluster() const
Getter for the cluster id.
CDCRLWireHit & getEndRLWireHit()
Getter for the third oriented wire hit.
CDCRLWireHit & getMiddleRLWireHit()
Getter for the second oriented wire hit.
void setStartRLInfo(const ERightLeft startRLInfo)
Setter for the right left passage information of the first oriented wire hit.
void setStartRLWireHit(const CDCRLWireHit &startRLWireHit)
Setter for the first oriented wire hit.
Class representing an oriented hit wire including a hypotheses whether the causing track passes left ...
Definition: CDCRLWireHit.h:41
Class representing a two dimensional reconstructed hit in the central drift chamber.
Definition: CDCRecoHit2D.h:47
const CDCWire & getWire() const
Getter for the wire the reconstructed hit associated to.
Definition: CDCRecoHit2D.h:175
A reconstructed sequence of two dimensional hits in one super layer.
Definition: CDCSegment2D.h:39
static CDCSegment2D condense(const CDCTangentSegment &tangentSegment)
Averages the reconstructed positions from hits that overlap in adjacent tangents in the given tangent...
ILayer getILayer() const
Getter for the layer id within its superlayer Gives the layer id within its superlayer ranging from ...
Definition: CDCWire.h:159
A pair of iterators usable with the range base for loop.
Definition: Range.h:25
bool m_param_relaxSingleLayerSearch
Parameter : Switch to relax the alias and reverse search for segments contained in a single layer.
bool m_param_allSingleAliases
Paraneter : Switch to activate the write out of all available orientations of single facet segments.
bool m_param_searchReversed
Parameter : Switch to construct the reversed segment if it is available in the facet graph as well.
std::string getDescription() final
Short description of the findlet.
bool m_param_searchAlias
Parameter : Switch to construct the alias segment if it is available in the facet graph as well.
void exposeParameters(ModuleParamList *moduleParamList, const std::string &prefix) final
Expose the parameters to a module.
MultipassCellularPathFinder< const CDCFacet > m_cellularPathFinder
Instance of the cellular automaton path finder.
std::vector< Path< const CDCFacet > > m_facetPaths
Memory for the facet paths generated from the graph.
void apply(const std::vector< CDCFacet > &inputFacets, const std::vector< WeightedRelation< const CDCFacet > > &inputFacetRelations, std::vector< CDCSegment2D > &outputSegments) final
Main function of the segment finding by the cellular automaton.
Type for two related objects with a weight.
void addParameter(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module list.
ERightLeft
Enumeration to represent the distinct possibilities of the right left passage.
Definition: ERightLeft.h:25
Abstract base class for different kinds of events.
Functor to get the I part (as of std::get<I>) from an arbitrary objects.
Definition: Functional.h:275