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 <Math/Vector2D.h>
22
23#include <utility>
24
25using namespace Belle2;
26using namespace TrackFindingCDC;
27using namespace TrackingUtilities;
28
29namespace {
30 void swapBetterChi2(CDCSegment2D& segment, CDCSegment2D& aliasSegment)
31 {
32 const CDCTrajectory2D& aliasTrajectory2D = aliasSegment.getTrajectory2D();
33 if (aliasTrajectory2D.isFitted() and
34 aliasTrajectory2D.getChi2() < segment.getTrajectory2D().getChi2()) {
35 aliasSegment.setAliasScore(NAN);
36 std::swap(segment, aliasSegment);
37 }
38 }
39}
40
42{
43 return "Resolves the rl aliasing of segments in various scenarios";
44}
45
46void SegmentAliasResolver::exposeParameters(ModuleParamList* moduleParamList, const std::string& prefix)
47{
48 moduleParamList->addParameter(prefixed(prefix, "investigateAlias"),
50 "Which alias resolutions should be applied. "
51 "Options are trailing_hit, last_hit, full.",
53
54 moduleParamList->addParameter(prefixed(prefix, "reestimateDriftLength"),
56 "Switch to reestimate the drift length in the alias resolver",
58
59 moduleParamList->addParameter(prefixed(prefix, "reestimatePositions"),
61 "Switch to reestimate the reconstructed positions in the alias resolver",
63}
64
66{
68 for (const std::string& investigatedAlias : m_param_investigateAlias) {
69 if (investigatedAlias == "full") {
70 m_fullAlias = true;
71 } else if (investigatedAlias == "cross") {
72 m_crossAliases = true;
73 } else if (investigatedAlias == "borders") {
74 m_borderAliases = true;
75 } else if (investigatedAlias == "middle") {
76 m_middleAliases = true;
77 } else {
78 B2ERROR("Unknown alias to investigate " << investigatedAlias);
79 }
80 }
81}
82
83void SegmentAliasResolver::apply(std::vector<CDCSegment2D>& outputSegments)
84{
85 if (m_fullAlias) {
86 for (CDCSegment2D& segment : outputSegments) {
87 if (segment->hasAliasFlag()) continue; // A full alias has been found in the facet ca.
88 int nRLSwitches = segment.getNRLSwitches();
89 // Sufficiently right left constrained that the alias is already fixed.
90 bool aliasStable = nRLSwitches > 2;
91 if (aliasStable) continue;
92
93 CDCSegment2D aliasSegment = segment.getAlias();
94 refit(aliasSegment, true);
95 swapBetterChi2(segment, aliasSegment);
96 } // end alias loop
97 }
98
99 // Detect whether the segment has a waist and flip the rest of the segment to right
100 if (m_crossAliases) {
101 for (CDCSegment2D& segment : outputSegments) {
102 int nRLSwitches = segment.getNRLSwitches();
103 // Sufficiently right left constrained that the alias is already fixed.
104 bool aliasStable = nRLSwitches > 2;
105 if (aliasStable) continue;
106
107 if (nRLSwitches == 1) {
108 // One RL switch. Try the all left and all right aliases
109 CDCSegment2D rightSegment = segment;
110 CDCSegment2D leftSegment = segment;
111 for (CDCRecoHit2D& recoHit2D : rightSegment) {
112 if (recoHit2D.getRLInfo() == ERightLeft::c_Left) {
113 recoHit2D = recoHit2D.getAlias();
114 }
115 }
116
117 for (CDCRecoHit2D& recoHit2D : leftSegment) {
118 if (recoHit2D.getRLInfo() == ERightLeft::c_Right) {
119 recoHit2D = recoHit2D.getAlias();
120 }
121 }
122 refit(rightSegment, true);
123 refit(leftSegment, true);
124 swapBetterChi2(segment, rightSegment);
125 swapBetterChi2(segment, leftSegment);
126
127 } else if (nRLSwitches == 0) {
128 // No RL switch. Try to introduce one at the smallest drift length
129 CDCSegment2D frontCrossSegment = segment;
130 CDCSegment2D backCrossSegment = segment;
131
132 auto lessDriftLength = [](const CDCRecoHit2D & lhs, const CDCRecoHit2D & rhs) {
133 return lhs.getRefDriftLength() < rhs.getRefDriftLength();
134 };
135
136 // Alias before the minimal drift length
137 {
138 auto itMinLRecoHit2D =
139 std::min_element(frontCrossSegment.begin(), frontCrossSegment.end(), lessDriftLength);
140 for (CDCRecoHit2D& recoHit2D : asRange(frontCrossSegment.begin(), itMinLRecoHit2D)) {
141 recoHit2D = recoHit2D.getAlias();
142 }
143 }
144
145 // Alias after the minimal drift length
146 {
147 auto itMinLRecoHit2D =
148 std::min_element(backCrossSegment.begin(), backCrossSegment.end(), lessDriftLength);
149 for (CDCRecoHit2D& recoHit2D : asRange(itMinLRecoHit2D, backCrossSegment.end())) {
150 recoHit2D = recoHit2D.getAlias();
151 }
152 }
153 refit(frontCrossSegment, true);
154 refit(backCrossSegment, true);
155 swapBetterChi2(segment, frontCrossSegment);
156 swapBetterChi2(segment, backCrossSegment);
157 }
158 }
159 }
160
161 if (m_borderAliases) {
162 for (CDCSegment2D& segment : outputSegments) {
163 // Check aliasing last hit
164 CDCSegment2D aliasSegment = segment;
165 CDCRecoHit2D& aliasHit = aliasSegment.back();
166 aliasHit.reverse();
167 aliasHit.setRecoPos2D(ROOT::Math::XYVector(NAN, NAN));
168 if (aliasHit.getRefDriftLength() < 0.2) {
169 refit(aliasSegment, false);
170 ROOT::Math::XYVector recoPos2D = aliasSegment.getTrajectory2D().getClosest(aliasHit.getRefPos2D());
171 ERightLeft rlInfo = aliasSegment.getTrajectory2D().isRightOrLeft(aliasHit.getRefPos2D());
172 aliasHit.setRecoPos2D(recoPos2D);
173 aliasHit.setRLInfo(rlInfo);
174 swapBetterChi2(segment, aliasSegment);
175 }
176 }
177
178 for (CDCSegment2D& segment : outputSegments) {
179 // Check aliasing first hit
180 CDCSegment2D aliasSegment = segment;
181 CDCRecoHit2D& aliasHit = aliasSegment.front();
182 aliasHit.reverse();
183 aliasHit.setRecoPos2D(ROOT::Math::XYVector(NAN, NAN));
184 if (aliasHit.getRefDriftLength() < 0.2) {
185 refit(aliasSegment, false);
186 ROOT::Math::XYVector recoPos2D = aliasSegment.getTrajectory2D().getClosest(aliasHit.getRefPos2D());
187 ERightLeft rlInfo = aliasSegment.getTrajectory2D().isRightOrLeft(aliasHit.getRefPos2D());
188 aliasHit.setRecoPos2D(recoPos2D);
189 aliasHit.setRLInfo(rlInfo);
190 swapBetterChi2(segment, aliasSegment);
191 }
192 }
193 }// end if (m_borderAliases)
194
195 if (m_middleAliases) {
196 for (CDCSegment2D& segment : outputSegments) {
197 // Check aliasing hit with lowest drift length
198 CDCSegment2D aliasSegment = segment;
199
200 // Find hit with minimal drift length
201 double minimalDriftLength = 0.1;
202 CDCRecoHit2D* minimalHit = nullptr;
203 for (CDCRecoHit2D& aliasHit : aliasSegment) {
204 if (aliasHit.getRefDriftLength() < minimalDriftLength) {
205 minimalHit = &aliasHit;
206 minimalDriftLength = aliasHit.getRefDriftLength();
207 }
208 }
209 if (minimalHit) {
210 CDCRecoHit2D& aliasHit = *minimalHit;
211 aliasHit.reverse();
212 aliasHit.setRecoPos2D(ROOT::Math::XYVector(NAN, NAN));
213 refit(aliasSegment, false);
214 ROOT::Math::XYVector recoPos2D = aliasSegment.getTrajectory2D().getClosest(aliasHit.getRefPos2D());
215 ERightLeft rlInfo = aliasSegment.getTrajectory2D().isRightOrLeft(aliasHit.getRefPos2D());
216 aliasHit.setRecoPos2D(recoPos2D);
217 aliasHit.setRLInfo(rlInfo);
218 swapBetterChi2(segment, aliasSegment);
219 }
220 }
221 }
222
223 std::sort(outputSegments.begin(), outputSegments.end());
224}
225
226void SegmentAliasResolver::refit(CDCSegment2D& segment, bool reestimate)
227{
228 if (reestimate) {
230 CDCRLWireHitSegment rlWireHitSegment = segment.getRLWireHitSegment();
231 // Reset the drift length to the default values.
232 for (CDCRLWireHit& rlWireHit : rlWireHitSegment) {
233 rlWireHit.setRefDriftLength(rlWireHit.getWireHit().getRefDriftLength());
234 }
235 CDCFacetSegment facetSegment = CDCFacetSegment::create(rlWireHitSegment);
236 for (CDCFacet& facet : facetSegment) {
237 facet.adjustFitLine();
239 m_driftLengthEstimator.updateDriftLength(facet);
240 }
241 }
242 CDCSegment2D replacement = CDCSegment2D::condense(facetSegment);
243 segment = replacement;
244 }
245
247 m_driftLengthEstimator.updateDriftLength(segment);
248 }
249 }
250
251 const EFitPos fitPos = EFitPos::c_RecoPos;
252 const EFitVariance fitVariance = EFitVariance::c_Proper;
253 CDCObservations2D observations2D(fitPos, fitVariance);
254 observations2D.appendRange(segment);
255 if (observations2D.size() < 4) {
256 segment.getTrajectory2D().clear();
257 } else {
258 CDCTrajectory2D trajectory2D = m_riemannFitter.fit(observations2D);
259 segment.setTrajectory2D(trajectory2D);
260 }
261
262}
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:33
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 ROOT::Math::XYVector &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:95
Particle trajectory as it is seen in xy projection represented as a circle.
ROOT::Math::XYVector getClosest(const ROOT::Math::XYVector &point) const
Calculates the closest approach on the trajectory to the given point.
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 ROOT::Math::XYVector &point) const
Checks if the given point is to the right or to the left of the trajectory.
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.