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