Belle II Software development
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
23using namespace Belle2;
24using namespace TrackFindingCDC;
25
26namespace {
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
43void 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
80void 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
223void 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 reconstructed 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 handling of orientation relate...
Definition: Vector2D.h:32
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.