Belle II Software  release-08-01-10
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 
29 using namespace Belle2;
30 using namespace TrackFindingCDC;
31 
32 namespace {
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 
52 void 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 reconsturcted 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.
void setMiddleRLInfo(const ERightLeft middleRLInfo)
Setter for the right left passage information of the second oriented wire hit.
CDCRLWireHit & getEndRLWireHit()
Getter for the third oriented wire hit.
void setMiddleRLWireHit(const CDCRLWireHit &middleRLWireHit)
Setter for the second oriented wire hit.
CDCRLWireHit & getMiddleRLWireHit()
Getter for the second oriented wire hit.
int getICluster() const
Getter for the cluster id.
CDCRLWireHit & getStartRLWireHit()
Getter for the first 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 assoziated 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 abitrary objects.
Definition: Functional.h:275