Belle II Software  release-08-01-10
SegmentAliasResolver.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/SegmentAliasResolver.h>
9 
10 #include <tracking/trackFindingCDC/fitting/CDCObservations2D.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 #include <tracking/trackFindingCDC/eventdata/hits/CDCWireHit.h>
16 
17 #include <tracking/trackFindingCDC/utilities/StringManipulation.h>
18 
19 #include <framework/core/ModuleParamList.templateDetails.h>
20 
21 #include <utility>
22 
23 using namespace Belle2;
24 using namespace TrackFindingCDC;
25 
26 namespace {
27  void swapBetterChi2(CDCSegment2D& segment, CDCSegment2D& aliasSegment)
28  {
29  const CDCTrajectory2D& aliasTrajectory2D = aliasSegment.getTrajectory2D();
30  if (aliasTrajectory2D.isFitted() and
31  aliasTrajectory2D.getChi2() < segment.getTrajectory2D().getChi2()) {
32  aliasSegment.setAliasScore(NAN);
33  std::swap(segment, aliasSegment);
34  }
35  }
36 }
37 
39 {
40  return "Resolves the rl aliasing of segments in various scenarios";
41 }
42 
43 void SegmentAliasResolver::exposeParameters(ModuleParamList* moduleParamList, const std::string& prefix)
44 {
45  moduleParamList->addParameter(prefixed(prefix, "investigateAlias"),
47  "Which alias resolutions should be applied. "
48  "Options are trailing_hit, last_hit, full.",
50 
51  moduleParamList->addParameter(prefixed(prefix, "reestimateDriftLength"),
53  "Switch to reestimate the drift length in the alias resolver",
55 
56  moduleParamList->addParameter(prefixed(prefix, "reestimatePositions"),
58  "Switch to reestimate the reconstructed positions in the alias resolver",
60 }
61 
63 {
65  for (const std::string& investigatedAlias : m_param_investigateAlias) {
66  if (investigatedAlias == "full") {
67  m_fullAlias = true;
68  } else if (investigatedAlias == "cross") {
69  m_crossAliases = true;
70  } else if (investigatedAlias == "borders") {
71  m_borderAliases = true;
72  } else if (investigatedAlias == "middle") {
73  m_middleAliases = true;
74  } else {
75  B2ERROR("Unknown alias to investigate " << investigatedAlias);
76  }
77  }
78 }
79 
80 void SegmentAliasResolver::apply(std::vector<CDCSegment2D>& outputSegments)
81 {
82  if (m_fullAlias) {
83  for (CDCSegment2D& segment : outputSegments) {
84  if (segment->hasAliasFlag()) continue; // A full alias has been found in the facet ca.
85  int nRLSwitches = segment.getNRLSwitches();
86  // Sufficiently right left constrained that the alias is already fixed.
87  bool aliasStable = nRLSwitches > 2;
88  if (aliasStable) continue;
89 
90  CDCSegment2D aliasSegment = segment.getAlias();
91  refit(aliasSegment, true);
92  swapBetterChi2(segment, aliasSegment);
93  } // end alias loop
94  }
95 
96  // Detect whether the segment has a waist and flip the rest of the segment to right
97  if (m_crossAliases) {
98  for (CDCSegment2D& segment : outputSegments) {
99  int nRLSwitches = segment.getNRLSwitches();
100  // Sufficiently right left constrained that the alias is already fixed.
101  bool aliasStable = nRLSwitches > 2;
102  if (aliasStable) continue;
103 
104  if (nRLSwitches == 1) {
105  // One RL switch. Try the all left and all right aliases
106  CDCSegment2D rightSegment = segment;
107  CDCSegment2D leftSegment = segment;
108  for (CDCRecoHit2D& recoHit2D : rightSegment) {
109  if (recoHit2D.getRLInfo() == ERightLeft::c_Left) {
110  recoHit2D = recoHit2D.getAlias();
111  }
112  }
113 
114  for (CDCRecoHit2D& recoHit2D : leftSegment) {
115  if (recoHit2D.getRLInfo() == ERightLeft::c_Right) {
116  recoHit2D = recoHit2D.getAlias();
117  }
118  }
119  refit(rightSegment, true);
120  refit(leftSegment, true);
121  swapBetterChi2(segment, rightSegment);
122  swapBetterChi2(segment, leftSegment);
123 
124  } else if (nRLSwitches == 0) {
125  // No RL switch. Try to introduce one at the smallest drift length
126  CDCSegment2D frontCrossSegment = segment;
127  CDCSegment2D backCrossSegment = segment;
128 
129  auto lessDriftLength = [](const CDCRecoHit2D & lhs, const CDCRecoHit2D & rhs) {
130  return lhs.getRefDriftLength() < rhs.getRefDriftLength();
131  };
132 
133  // Alias before the minimal drift length
134  {
135  auto itMinLRecoHit2D =
136  std::min_element(frontCrossSegment.begin(), frontCrossSegment.end(), lessDriftLength);
137  for (CDCRecoHit2D& recoHit2D : asRange(frontCrossSegment.begin(), itMinLRecoHit2D)) {
138  recoHit2D = recoHit2D.getAlias();
139  }
140  }
141 
142  // Alias after the minimal drift length
143  {
144  auto itMinLRecoHit2D =
145  std::min_element(backCrossSegment.begin(), backCrossSegment.end(), lessDriftLength);
146  for (CDCRecoHit2D& recoHit2D : asRange(itMinLRecoHit2D, backCrossSegment.end())) {
147  recoHit2D = recoHit2D.getAlias();
148  }
149  }
150  refit(frontCrossSegment, true);
151  refit(backCrossSegment, true);
152  swapBetterChi2(segment, frontCrossSegment);
153  swapBetterChi2(segment, backCrossSegment);
154  }
155  }
156  }
157 
158  if (m_borderAliases) {
159  for (CDCSegment2D& segment : outputSegments) {
160  // Check aliasing last hit
161  CDCSegment2D aliasSegment = segment;
162  CDCRecoHit2D& aliasHit = aliasSegment.back();
163  aliasHit.reverse();
164  aliasHit.setRecoPos2D(Vector2D(NAN, NAN));
165  if (aliasHit.getRefDriftLength() < 0.2) {
166  refit(aliasSegment, false);
167  Vector2D recoPos2D = aliasSegment.getTrajectory2D().getClosest(aliasHit.getRefPos2D());
168  ERightLeft rlInfo = aliasSegment.getTrajectory2D().isRightOrLeft(aliasHit.getRefPos2D());
169  aliasHit.setRecoPos2D(recoPos2D);
170  aliasHit.setRLInfo(rlInfo);
171  swapBetterChi2(segment, aliasSegment);
172  }
173  }
174 
175  for (CDCSegment2D& segment : outputSegments) {
176  // Check aliasing first hit
177  CDCSegment2D aliasSegment = segment;
178  CDCRecoHit2D& aliasHit = aliasSegment.front();
179  aliasHit.reverse();
180  aliasHit.setRecoPos2D(Vector2D(NAN, NAN));
181  if (aliasHit.getRefDriftLength() < 0.2) {
182  refit(aliasSegment, false);
183  Vector2D recoPos2D = aliasSegment.getTrajectory2D().getClosest(aliasHit.getRefPos2D());
184  ERightLeft rlInfo = aliasSegment.getTrajectory2D().isRightOrLeft(aliasHit.getRefPos2D());
185  aliasHit.setRecoPos2D(recoPos2D);
186  aliasHit.setRLInfo(rlInfo);
187  swapBetterChi2(segment, aliasSegment);
188  }
189  }
190  }// end if (m_borderAliases)
191 
192  if (m_middleAliases) {
193  for (CDCSegment2D& segment : outputSegments) {
194  // Check aliasing hit with lowest drift length
195  CDCSegment2D aliasSegment = segment;
196 
197  // Find hit with minimal drift length
198  double minimalDriftLength = 0.1;
199  CDCRecoHit2D* minimalHit = nullptr;
200  for (CDCRecoHit2D& aliasHit : aliasSegment) {
201  if (aliasHit.getRefDriftLength() < minimalDriftLength) {
202  minimalHit = &aliasHit;
203  minimalDriftLength = aliasHit.getRefDriftLength();
204  }
205  }
206  if (minimalHit) {
207  CDCRecoHit2D& aliasHit = *minimalHit;
208  aliasHit.reverse();
209  aliasHit.setRecoPos2D(Vector2D(NAN, NAN));
210  refit(aliasSegment, false);
211  Vector2D recoPos2D = aliasSegment.getTrajectory2D().getClosest(aliasHit.getRefPos2D());
212  ERightLeft rlInfo = aliasSegment.getTrajectory2D().isRightOrLeft(aliasHit.getRefPos2D());
213  aliasHit.setRecoPos2D(recoPos2D);
214  aliasHit.setRLInfo(rlInfo);
215  swapBetterChi2(segment, aliasSegment);
216  }
217  }
218  }
219 
220  std::sort(outputSegments.begin(), outputSegments.end());
221 }
222 
223 void SegmentAliasResolver::refit(CDCSegment2D& segment, bool reestimate)
224 {
225  if (reestimate) {
227  CDCRLWireHitSegment rlWireHitSegment = segment.getRLWireHitSegment();
228  // Reset the drift length to the default values.
229  for (CDCRLWireHit& rlWireHit : rlWireHitSegment) {
230  rlWireHit.setRefDriftLength(rlWireHit.getWireHit().getRefDriftLength());
231  }
232  CDCFacetSegment facetSegment = CDCFacetSegment::create(rlWireHitSegment);
233  for (CDCFacet& facet : facetSegment) {
234  facet.adjustFitLine();
237  }
238  }
239  CDCSegment2D replacement = CDCSegment2D::condense(facetSegment);
240  segment = replacement;
241  }
242 
245  }
246  }
247 
248  const EFitPos fitPos = EFitPos::c_RecoPos;
249  const EFitVariance fitVariance = EFitVariance::c_Proper;
250  CDCObservations2D observations2D(fitPos, fitVariance);
251  observations2D.appendRange(segment);
252  if (observations2D.size() < 4) {
253  segment.getTrajectory2D().clear();
254  } else {
255  CDCTrajectory2D trajectory2D = m_riemannFitter.fit(observations2D);
256  segment.setTrajectory2D(trajectory2D);
257  }
258 
259 }
The Module parameter list class.
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
CDCTrajectory2D fit(const CDCObservations2D &observations2D) const
Fits a collection of observation drift circles.
Class serving as a storage of observed drift circles to present to the Riemann fitter.
std::size_t appendRange(const CDCSegment2D &segment2D)
Appends all reconstructed hits from the two dimensional segment.
std::size_t size() const
Returns the number of observations stored.
A segment consisting of two dimensional reconsturcted hits.
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
void setRLInfo(ERightLeft &rlInfo)
Setter the right left passage information.
Definition: CDCRecoHit2D.h:211
void reverse()
Turns the orientation in place.
Definition: CDCRecoHit2D.cc:93
double getRefDriftLength() const
Getter for the drift length at the wire reference position.
Definition: CDCRecoHit2D.h:217
const Vector2D & getRefPos2D() const
Getter for the reference position of the wire.
Definition: CDCRecoHit2D.h:181
void setRecoPos2D(const Vector2D &recoPos2D)
Setter for the position in the reference plane.
Definition: CDCRecoHit2D.h:244
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...
CDCTrajectory2D & getTrajectory2D() const
Getter for the two dimensional trajectory fitted to the segment.
Definition: CDCSegment.h:69
void setAliasScore(double aliasScore)
Setter for the flag that this segment may have an aliased version.
Definition: CDCSegment.h:96
Particle trajectory as it is seen in xy projection represented as a circle.
double getChi2() const
Getter for the chi2 value of the circle fit.
bool isFitted() const
Checks if the circle is already set to a valid value.
ERightLeft isRightOrLeft(const Vector2D &point) const
Checks if the given point is to the right or to the left of the trajectory.
Vector2D getClosest(const Vector2D &point) const
Calculates the closest approach on the trajectory to the given point.
void initialize() override
Receive and dispatch signal before the start of the event processing.
DriftLengthEstimator m_driftLengthEstimator
Instance of the drift length estimator to be used.
bool m_middleAliases
Switch whether the hits in the middle with lowest drift radius should be aliased.
void refit(CDCSegment2D &segment, bool reestimate)
Fit the alias segment.
void initialize() final
Signals the beginning of the event processing.
bool m_param_reestimatePositions
Parameter : Switch to restimate the reconstructed positions with a pass of facets.
std::vector< std::string > m_param_investigateAlias
Parameter : Which alias resolutions should be applied.
bool m_param_reestimateDriftLength
Parameter : Switch to reestimate the drift length before each fit.
bool m_fullAlias
Switch whether the complete segment should be aliased.
std::string getDescription() final
Short description of the findlet.
void apply(std::vector< CDCSegment2D > &outputSegments) final
Main algorithm applying the fit to each segment.
bool m_borderAliases
Switch whether the border hits at the beginning and the end should be aliased.
void exposeParameters(ModuleParamList *moduleParamList, const std::string &prefix) final
Expose the parameters to a module.
CDCRiemannFitter m_riemannFitter
Instance of the riemann fitter to be used.
bool m_crossAliases
Switch whether the segment should be aliased at the waist where an rl side switch was missed.
A two dimensional vector which is equipped with functions for correct handeling of orientation relat...
Definition: Vector2D.h:35
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.
double updateDriftLength(CDCRecoHit2D &recoHit2D)
Update the drift length of the reconstructed hit in place.