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/trackingUtilities/eventdata/segments/CDCSegment2D.h>
13#include <tracking/trackingUtilities/eventdata/segments/CDCFacetSegment.h>
14#include <tracking/trackingUtilities/eventdata/segments/CDCRLWireHitSegment.h>
15#include <tracking/trackingUtilities/eventdata/hits/CDCWireHit.h>
16
17#include <tracking/trackingUtilities/utilities/StringManipulation.h>
18
19#include <framework/core/ModuleParamList.templateDetails.h>
20
21#include <utility>
22
23using namespace Belle2;
24using namespace TrackFindingCDC;
25using namespace TrackingUtilities;
26
27namespace {
28 void swapBetterChi2(CDCSegment2D& segment, CDCSegment2D& aliasSegment)
29 {
30 const CDCTrajectory2D& aliasTrajectory2D = aliasSegment.getTrajectory2D();
31 if (aliasTrajectory2D.isFitted() and
32 aliasTrajectory2D.getChi2() < segment.getTrajectory2D().getChi2()) {
33 aliasSegment.setAliasScore(NAN);
34 std::swap(segment, aliasSegment);
35 }
36 }
37}
38
40{
41 return "Resolves the rl aliasing of segments in various scenarios";
42}
43
44void SegmentAliasResolver::exposeParameters(ModuleParamList* moduleParamList, const std::string& prefix)
45{
46 moduleParamList->addParameter(prefixed(prefix, "investigateAlias"),
48 "Which alias resolutions should be applied. "
49 "Options are trailing_hit, last_hit, full.",
51
52 moduleParamList->addParameter(prefixed(prefix, "reestimateDriftLength"),
54 "Switch to reestimate the drift length in the alias resolver",
56
57 moduleParamList->addParameter(prefixed(prefix, "reestimatePositions"),
59 "Switch to reestimate the reconstructed positions in the alias resolver",
61}
62
64{
66 for (const std::string& investigatedAlias : m_param_investigateAlias) {
67 if (investigatedAlias == "full") {
68 m_fullAlias = true;
69 } else if (investigatedAlias == "cross") {
70 m_crossAliases = true;
71 } else if (investigatedAlias == "borders") {
72 m_borderAliases = true;
73 } else if (investigatedAlias == "middle") {
74 m_middleAliases = true;
75 } else {
76 B2ERROR("Unknown alias to investigate " << investigatedAlias);
77 }
78 }
79}
80
81void SegmentAliasResolver::apply(std::vector<CDCSegment2D>& outputSegments)
82{
83 if (m_fullAlias) {
84 for (CDCSegment2D& segment : outputSegments) {
85 if (segment->hasAliasFlag()) continue; // A full alias has been found in the facet ca.
86 int nRLSwitches = segment.getNRLSwitches();
87 // Sufficiently right left constrained that the alias is already fixed.
88 bool aliasStable = nRLSwitches > 2;
89 if (aliasStable) continue;
90
91 CDCSegment2D aliasSegment = segment.getAlias();
92 refit(aliasSegment, true);
93 swapBetterChi2(segment, aliasSegment);
94 } // end alias loop
95 }
96
97 // Detect whether the segment has a waist and flip the rest of the segment to right
98 if (m_crossAliases) {
99 for (CDCSegment2D& segment : outputSegments) {
100 int nRLSwitches = segment.getNRLSwitches();
101 // Sufficiently right left constrained that the alias is already fixed.
102 bool aliasStable = nRLSwitches > 2;
103 if (aliasStable) continue;
104
105 if (nRLSwitches == 1) {
106 // One RL switch. Try the all left and all right aliases
107 CDCSegment2D rightSegment = segment;
108 CDCSegment2D leftSegment = segment;
109 for (CDCRecoHit2D& recoHit2D : rightSegment) {
110 if (recoHit2D.getRLInfo() == ERightLeft::c_Left) {
111 recoHit2D = recoHit2D.getAlias();
112 }
113 }
114
115 for (CDCRecoHit2D& recoHit2D : leftSegment) {
116 if (recoHit2D.getRLInfo() == ERightLeft::c_Right) {
117 recoHit2D = recoHit2D.getAlias();
118 }
119 }
120 refit(rightSegment, true);
121 refit(leftSegment, true);
122 swapBetterChi2(segment, rightSegment);
123 swapBetterChi2(segment, leftSegment);
124
125 } else if (nRLSwitches == 0) {
126 // No RL switch. Try to introduce one at the smallest drift length
127 CDCSegment2D frontCrossSegment = segment;
128 CDCSegment2D backCrossSegment = segment;
129
130 auto lessDriftLength = [](const CDCRecoHit2D & lhs, const CDCRecoHit2D & rhs) {
131 return lhs.getRefDriftLength() < rhs.getRefDriftLength();
132 };
133
134 // Alias before the minimal drift length
135 {
136 auto itMinLRecoHit2D =
137 std::min_element(frontCrossSegment.begin(), frontCrossSegment.end(), lessDriftLength);
138 for (CDCRecoHit2D& recoHit2D : asRange(frontCrossSegment.begin(), itMinLRecoHit2D)) {
139 recoHit2D = recoHit2D.getAlias();
140 }
141 }
142
143 // Alias after the minimal drift length
144 {
145 auto itMinLRecoHit2D =
146 std::min_element(backCrossSegment.begin(), backCrossSegment.end(), lessDriftLength);
147 for (CDCRecoHit2D& recoHit2D : asRange(itMinLRecoHit2D, backCrossSegment.end())) {
148 recoHit2D = recoHit2D.getAlias();
149 }
150 }
151 refit(frontCrossSegment, true);
152 refit(backCrossSegment, true);
153 swapBetterChi2(segment, frontCrossSegment);
154 swapBetterChi2(segment, backCrossSegment);
155 }
156 }
157 }
158
159 if (m_borderAliases) {
160 for (CDCSegment2D& segment : outputSegments) {
161 // Check aliasing last hit
162 CDCSegment2D aliasSegment = segment;
163 CDCRecoHit2D& aliasHit = aliasSegment.back();
164 aliasHit.reverse();
165 aliasHit.setRecoPos2D(Vector2D(NAN, NAN));
166 if (aliasHit.getRefDriftLength() < 0.2) {
167 refit(aliasSegment, false);
168 Vector2D recoPos2D = aliasSegment.getTrajectory2D().getClosest(aliasHit.getRefPos2D());
169 ERightLeft rlInfo = aliasSegment.getTrajectory2D().isRightOrLeft(aliasHit.getRefPos2D());
170 aliasHit.setRecoPos2D(recoPos2D);
171 aliasHit.setRLInfo(rlInfo);
172 swapBetterChi2(segment, aliasSegment);
173 }
174 }
175
176 for (CDCSegment2D& segment : outputSegments) {
177 // Check aliasing first hit
178 CDCSegment2D aliasSegment = segment;
179 CDCRecoHit2D& aliasHit = aliasSegment.front();
180 aliasHit.reverse();
181 aliasHit.setRecoPos2D(Vector2D(NAN, NAN));
182 if (aliasHit.getRefDriftLength() < 0.2) {
183 refit(aliasSegment, false);
184 Vector2D recoPos2D = aliasSegment.getTrajectory2D().getClosest(aliasHit.getRefPos2D());
185 ERightLeft rlInfo = aliasSegment.getTrajectory2D().isRightOrLeft(aliasHit.getRefPos2D());
186 aliasHit.setRecoPos2D(recoPos2D);
187 aliasHit.setRLInfo(rlInfo);
188 swapBetterChi2(segment, aliasSegment);
189 }
190 }
191 }// end if (m_borderAliases)
192
193 if (m_middleAliases) {
194 for (CDCSegment2D& segment : outputSegments) {
195 // Check aliasing hit with lowest drift length
196 CDCSegment2D aliasSegment = segment;
197
198 // Find hit with minimal drift length
199 double minimalDriftLength = 0.1;
200 CDCRecoHit2D* minimalHit = nullptr;
201 for (CDCRecoHit2D& aliasHit : aliasSegment) {
202 if (aliasHit.getRefDriftLength() < minimalDriftLength) {
203 minimalHit = &aliasHit;
204 minimalDriftLength = aliasHit.getRefDriftLength();
205 }
206 }
207 if (minimalHit) {
208 CDCRecoHit2D& aliasHit = *minimalHit;
209 aliasHit.reverse();
210 aliasHit.setRecoPos2D(Vector2D(NAN, NAN));
211 refit(aliasSegment, false);
212 Vector2D recoPos2D = aliasSegment.getTrajectory2D().getClosest(aliasHit.getRefPos2D());
213 ERightLeft rlInfo = aliasSegment.getTrajectory2D().isRightOrLeft(aliasHit.getRefPos2D());
214 aliasHit.setRecoPos2D(recoPos2D);
215 aliasHit.setRLInfo(rlInfo);
216 swapBetterChi2(segment, aliasSegment);
217 }
218 }
219 }
220
221 std::sort(outputSegments.begin(), outputSegments.end());
222}
223
224void SegmentAliasResolver::refit(CDCSegment2D& segment, bool reestimate)
225{
226 if (reestimate) {
228 CDCRLWireHitSegment rlWireHitSegment = segment.getRLWireHitSegment();
229 // Reset the drift length to the default values.
230 for (CDCRLWireHit& rlWireHit : rlWireHitSegment) {
231 rlWireHit.setRefDriftLength(rlWireHit.getWireHit().getRefDriftLength());
232 }
233 CDCFacetSegment facetSegment = CDCFacetSegment::create(rlWireHitSegment);
234 for (CDCFacet& facet : facetSegment) {
235 facet.adjustFitLine();
237 m_driftLengthEstimator.updateDriftLength(facet);
238 }
239 }
240 CDCSegment2D replacement = CDCSegment2D::condense(facetSegment);
241 segment = replacement;
242 }
243
245 m_driftLengthEstimator.updateDriftLength(segment);
246 }
247 }
248
249 const EFitPos fitPos = EFitPos::c_RecoPos;
250 const EFitVariance fitVariance = EFitVariance::c_Proper;
251 CDCObservations2D observations2D(fitPos, fitVariance);
252 observations2D.appendRange(segment);
253 if (observations2D.size() < 4) {
254 segment.getTrajectory2D().clear();
255 } else {
256 CDCTrajectory2D trajectory2D = m_riemannFitter.fit(observations2D);
257 segment.setTrajectory2D(trajectory2D);
258 }
259
260}
The Module parameter list class.
Class serving as a storage of observed drift circles to present to the Riemann fitter.
std::size_t appendRange(const TrackingUtilities::CDCSegment2D &segment2D)
Appends all reconstructed hits from the two dimensional segment.
std::size_t size() const
Returns the number of observations stored.
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 apply(std::vector< TrackingUtilities::CDCSegment2D > &outputSegments) final
Main algorithm applying the fit to each 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.
void refit(TrackingUtilities::CDCSegment2D &segment, bool reestimate)
Fit the alias segment.
bool m_fullAlias
Switch whether the complete segment should be aliased.
std::string getDescription() final
Short description of the findlet.
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 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 an oriented hit wire including a hypotheses whether the causing track passes left ...
Class representing a two dimensional reconstructed hit in the central drift chamber.
void setRLInfo(ERightLeft &rlInfo)
Setter the right left passage information.
void reverse()
Turns the orientation in place.
double getRefDriftLength() const
Getter for the drift length at the wire reference position.
const ROOT::Math::XYVector & getRefPos2D() const
Getter for the reference position of the wire.
void setRecoPos2D(const Vector2D &recoPos2D)
Setter for the position in the reference plane.
A reconstructed sequence of two dimensional hits in one super layer.
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.
A two dimensional vector which is equipped with functions for correct handling of orientation relate...
Definition Vector2D.h:36
void addParameter(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module list.
Abstract base class for different kinds of events.