Belle II Software  release-08-01-10
AxialLegendreLeafProcessor.icc.h
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 #pragma once
9 #include <tracking/trackFindingCDC/hough/perigee/AxialLegendreLeafProcessor.h>
10 
11 #include <tracking/trackFindingCDC/processing/AxialTrackUtil.h>
12 
13 #include <tracking/trackFindingCDC/hough/perigee/StereoHitContained.h>
14 #include <tracking/trackFindingCDC/hough/perigee/OffOrigin.h>
15 #include <tracking/trackFindingCDC/hough/algorithms/InPhi0ImpactCurvBox.h>
16 #include <tracking/trackFindingCDC/hough/baseelements/WithSharedMark.h>
17 
18 #include <tracking/trackFindingCDC/eventdata/trajectories/CDCTrajectory2D.h>
19 #include <tracking/trackFindingCDC/fitting/CDCObservations2D.h>
20 #include <tracking/trackFindingCDC/fitting/CDCKarimakiFitter.h>
21 #include <tracking/trackFindingCDC/geometry/PerigeeCircle.h>
22 
23 #include <tracking/trackFindingCDC/legendre/precisionFunctions/PrecisionUtil.h>
24 
25 #include <tracking/trackFindingCDC/utilities/StringManipulation.h>
26 
27 #include <framework/core/ModuleParamList.templateDetails.h>
28 
29 namespace Belle2 {
34  namespace TrackFindingCDC {
35 
36  template <class ANode>
38  {
39  // Special post processing looking for more hits
40  // Start off by fitting the items of the leaf with a general trajectory
41  // that may have a distinct impact != 0
43  auto fitPos = EFitPos::c_RecoPos;
44  auto fitVariance = EFitVariance::c_DriftLength;
45  // Other combinations of fit information
46  // EFitPos::c_RLDriftCircle x EFitVariance::(c_Nominal, c_Pseudo, c_Proper)
47  // have been tried, but found to be worse, which is
48  // not intutive. Probably the perfect circle trajectory
49  // is not as good of a model on the full CDC volume.
50  CDCObservations2D observations2D(fitPos, fitVariance);
51 
52  CDCKarimakiFitter fitter;
53  // Tested alternative CDCRiemannFitter with only marginal differences;
54 
55  std::vector<WithSharedMark<CDCRLWireHit>> hits(leaf->begin(), leaf->end());
56  std::sort(hits.begin(), hits.end()); // Hits should be naturally sorted
57  observations2D.appendRange(hits);
58  CDCTrajectory2D trajectory2D = fitter.fit(observations2D);
59  {
60  const double curv = trajectory2D.getCurvature();
61  std::array<DiscreteCurv, 2> curvs = leaf->template getBounds<DiscreteCurv>();
62 
63  float lowerCurv = *(curvs[0]);
64  float upperCurv = *(curvs[1]);
65  if (static_cast<double>(ESignUtil::common(lowerCurv, upperCurv)) * curv < 0) {
66  trajectory2D.reverse();
67  }
68  }
69  trajectory2D.setLocalOrigin(Vector2D(0, 0));
70 
71  // Look for more hits near the found trajectory
73  if (m_param_nRoadSearches > 0) {
74  // Acquire all available items in some parent node for the road search
75  // Somewhat bypasses the logic of the tree walk - Must handle with care!
76  ANode* roadNode = leaf;
77  while (roadNode->getParent() and roadNode->getLevel() > m_param_roadLevel) {
78  roadNode = roadNode->getParent();
79  }
80 
81  for (int iRoadSearch = 0; iRoadSearch < m_param_nRoadSearches; ++iRoadSearch) {
82  // Use a road search to find new hits from the trajectory
83  // hits = this->searchRoad(*roadNode, trajectory2D); // In case you only want the road hits
84  // if (hits.size() < 5) return;
85 
86  // Second version always holding on to the originally found hits
87  int nHitsBefore = hits.size();
88  std::vector<WithSharedMark<CDCRLWireHit>> roadHits = this->searchRoad(*roadNode, trajectory2D);
89  std::sort(roadHits.begin(), roadHits.end());
90  hits.insert(hits.end(), roadHits.begin(), roadHits.end());
91  std::inplace_merge(hits.begin(), hits.begin() + nHitsBefore, hits.end());
92  hits.erase(std::unique(hits.begin(), hits.end()), hits.end());
93 
94  // Update the current fit
95  observations2D.clear();
96  observations2D.appendRange(hits);
97  trajectory2D = fitter.fit(observations2D);
98  trajectory2D.setLocalOrigin(Vector2D(0.0, 0.0));
99  }
100  }
101 
102  // Mark found hit as used and safe them with the trajectory
104  std::vector<const CDCWireHit*> foundWireHits;
105  for (CDCRLWireHit& rlWireHit : hits) {
106  foundWireHits.push_back(&rlWireHit.getWireHit());
107  }
108 
109  AxialTrackUtil::addCandidateFromHits(foundWireHits, m_axialWireHits, m_tracks, true);
110 
111  // Sync up the marks with the used hits
112  for (WithSharedMark<CDCRLWireHit>& markableRLWireHit : leaf->getTree()->getTopNode()) {
113  const AutomatonCell& automatonCell = markableRLWireHit.getWireHit().getAutomatonCell();
114  if (automatonCell.hasTakenFlag() or automatonCell.hasMaskedFlag()) {
115  markableRLWireHit.mark();
116  } else {
117  markableRLWireHit.unmark();
118  }
119  }
120  }
121 
122  template <class ANode>
123  std::vector<WithSharedMark<CDCRLWireHit> >
124  AxialLegendreLeafProcessor<ANode>::searchRoad(const ANode& node, const CDCTrajectory2D& trajectory2D)
125  {
126  PerigeeCircle circle = trajectory2D.getGlobalCircle();
127  Vector2D support = trajectory2D.getGlobalPerigee();
128  const float curv = circle.curvature();
129  const float phi0 = circle.phi0();
130 
131  StereoHitContained<OffOrigin<InPhi0ImpactCurvBox> > hitInPhi0CurvBox(m_param_curlCurv);
132  hitInPhi0CurvBox.setLocalOrigin(support);
133  using RoadHoughBox = StereoHitContained<OffOrigin<InPhi0ImpactCurvBox> >::HoughBox;
134 
135  // Determine a precision that we expect to achieve at the fitted momentum
136  // There certainly is some optimizsation potential here.
137  // Spread in the impact parameter is made available here but is not activated yet.
138  const float levelPrecision = 9.0;
139  // Earlier version
140  // const float levelPrecision = 10.5 - 0.24 * exp(-4.13118 * PrecisionUtil::convertRhoToPt(curv) + 2.74);
141  const float phi0Precision = 3.1415 / std::pow(2.0, levelPrecision + 1.0);
142  const float impactPrecision = 0.0 * std::sqrt(CDCWireHit::c_simpleDriftLengthVariance);
143  const float curvPrecision = 0.15 / std::pow(2.0, levelPrecision);
144 
145  DiscreteCurv::Array curvBounds{{curv - curvPrecision, curv + curvPrecision}};
146  ContinuousImpact::Array impactBounds{{ -impactPrecision, impactPrecision}};
147  DiscretePhi0::Array phi0Bounds{{Vector2D::Phi(phi0 - phi0Precision), Vector2D::Phi(phi0 + phi0Precision)}};
148  RoadHoughBox precisionPhi0CurvBox(DiscretePhi0::getRange(phi0Bounds),
149  ContinuousImpact::getRange(impactBounds),
150  DiscreteCurv::getRange(curvBounds));
151 
152  std::vector<WithSharedMark<CDCRLWireHit>> hitsInPrecisionBox;
153 
154  // Explicitly making a copy here to ensure that we do not change the node content
155  for (WithSharedMark<CDCRLWireHit> markableRLWireHit : node) {
156  // Skip marked hits
157  if (markableRLWireHit.isMarked()) continue;
158  Weight weight = hitInPhi0CurvBox(markableRLWireHit, &precisionPhi0CurvBox);
159  if (not std::isnan(weight)) hitsInPrecisionBox.push_back(markableRLWireHit);
160  }
161 
162  return hitsInPrecisionBox;
163  }
164  }
166 }
167 
168 namespace Belle2 {
173  namespace TrackFindingCDC {
174  template <class ANode>
175  std::vector<typename AxialLegendreLeafProcessor<ANode>::Candidate>
177  {
178  std::vector<Candidate> result;
179  for (const CDCTrack& track : m_tracks) {
180  std::vector<CDCRLWireHit> rlWireHits;
181  for (const CDCRecoHit3D& recoHit3D : track) {
182  rlWireHits.push_back(recoHit3D.getRLWireHit());
183  }
184  CDCTrajectory2D trajectory2D = track.getStartTrajectory3D().getTrajectory2D();
185  result.emplace_back(std::move(trajectory2D), std::move(rlWireHits));
186  }
187  return result;
188  }
189 
190  template <class ANode>
192  const std::string& prefix)
193  {
194  moduleParamList->addParameter(prefixed(prefix, "maxLevel"),
195  m_param_maxLevel,
196  "Level of divisions in the hough space at which a leaf is reached",
197  m_param_maxLevel);
198 
199  moduleParamList->addParameter(prefixed(prefix, "minWeight"),
200  m_param_minWeight,
201  "Minimal exceptable weight of a leaf to be considered",
202  m_param_minWeight);
203 
204  moduleParamList->addParameter(prefixed(prefix, "maxCurv"),
205  m_param_maxCurv,
206  "Maximal curvature of a leaf to be considered",
207  m_param_maxCurv);
208 
209  moduleParamList->addParameter(prefixed(prefix, "curlCurv"),
210  m_param_curlCurv,
211  "Curvature below which hits on both arms of the trajectory are allowed",
212  m_param_curlCurv);
213 
214  moduleParamList->addParameter(prefixed(prefix, "nRoadSearches"),
215  m_param_nRoadSearches,
216  "How often the road search should be performed to find new hits",
217  m_param_nRoadSearches);
218 
219  moduleParamList->addParameter(prefixed(prefix, "roadLevel"),
220  m_param_roadLevel,
221  "Level of the read from which additional hits in the road search can be taken",
222  m_param_roadLevel);
223 
224  moduleParamList->addParameter(prefixed(prefix, "curvResolution"),
225  m_param_curvResolution,
226  "The name of the resolution function to be used. "
227  "Valid values are 'none', 'const', 'basic', 'origin', 'nonOrigin'",
228  m_param_curvResolution);
229  }
230 
231  template <class ANode>
233  {
234  // Setup the requested precision function
235  if (m_param_curvResolution == "none") {
236  m_curvResolution = [](double curv __attribute__((unused))) { return NAN; };
237  } else if (m_param_curvResolution == "const") {
238  m_curvResolution = [](double curv __attribute__((unused))) { return 0.0008; };
239  } else if (m_param_curvResolution == "basic") {
240  m_curvResolution = &PrecisionUtil::getBasicCurvPrecision;
241  } else if (m_param_curvResolution == "origin") {
242  m_curvResolution = &PrecisionUtil::getOriginCurvPrecision;
243  } else if (m_param_curvResolution == "nonOrigin") {
244  m_curvResolution = &PrecisionUtil::getNonOriginCurvPrecision;
245  } else {
246  B2WARNING("Unknown curvature resolution function " << m_param_curvResolution);
247  m_curvResolution = [](double curv __attribute__((unused))) { return NAN; };
248  }
249  }
250  }
252 }
The Module parameter list class.
Cell used by the cellular automata.
Definition: AutomatonCell.h:29
bool hasMaskedFlag() const
Gets the current state of the masked marker flag.
bool hasTakenFlag() const
Gets the current state of the taken marker flag.
std::vector< Candidate > getCandidates() const
Getter for the candidates structure still used in some tests.
std::vector< WithSharedMark< CDCRLWireHit > > searchRoad(const ANode &node, const CDCTrajectory2D &trajectory2D)
Look for more hits near a ftted trajectory from hits available in the give node.
void exposeParameters(ModuleParamList *moduleParamList, const std::string &prefix)
Expose the parameters as a module parameter list.
void processLeaf(ANode *leaf)
A valuable leaf has been found in the hough tree walk.
void beginWalk()
Function to notify the leaf processor about changes in parameters before a new walk.
Class implementing the fitter using Karimakis method.
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.
void clear()
Removes all observations stored.
Class representing an oriented hit wire including a hypotheses whether the causing track passes left ...
Definition: CDCRLWireHit.h:41
Class representing a three dimensional reconstructed hit.
Definition: CDCRecoHit3D.h:52
Class representing a sequence of three dimensional reconstructed hits.
Definition: CDCTrack.h:41
Particle trajectory as it is seen in xy projection represented as a circle.
PerigeeCircle getGlobalCircle() const
Getter for the circle in global coordinates.
void reverse()
Reverses the trajectory in place.
double setLocalOrigin(const Vector2D &localOrigin)
Setter for the origin of the local coordinate system.
Vector2D getGlobalPerigee() const
Getter for the closest approach on the trajectory to the global origin.
double getCurvature() const
Getter for the curvature as seen from the xy projection.
static constexpr const double c_simpleDriftLengthVariance
A default value for the drift length variance if no variance from the drift length translation is ava...
Definition: CDCWireHit.h:64
std::array< T, 2 > Array
Mock array type to be a drop in replacement for the discrete values.
static std::array< This, 2 > getRange(const Array &bounds)
Extract the range from an array providing the discrete values.
static std::array< This, 2 > getRange(Array &values)
Extract the range from an array providing the discrete values.
Definition: DiscreteValue.h:59
std::vector< T > Array
The type of the array which contains the underlying values.
Definition: DiscreteValue.h:55
Extension of the generalized circle also caching the perigee coordinates.
Definition: PerigeeCircle.h:36
double phi0() const
Getter for the azimuth angle of the direction of flight at the perigee.
double curvature() const
Getter for the signed curvature.
static double getOriginCurvPrecision(double curv)
Function which estimates desired curvature resolution of quadtree node in the given pt region paramet...
Definition: PrecisionUtil.h:65
static double getNonOriginCurvPrecision(double curv)
Function which estimates desired curvature resolution of quadtree node in the given pt region paramet...
Definition: PrecisionUtil.h:90
static double getBasicCurvPrecision(double curv)
Basic function to estimate the curvature precision Takes a curvature value and returns a width that.
Definition: PrecisionUtil.h:49
Predicate class to check for the containment of axial and stereo hits in some hough space part.
A two dimensional vector which is equipped with functions for correct handeling of orientation relat...
Definition: Vector2D.h:35
static Vector2D Phi(const double phi)
Constucts a unit vector with azimuth angle equal to phi.
Definition: Vector2D.h:71
Mixin class to attach a mark that is shared among many instances.
void addParameter(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module list.
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
static ESign common(ESign n1, ESign n2)
Check if two values have a common sign.
Definition: ESign.h:57
Abstract base class for different kinds of events.
static void addCandidateFromHits(const std::vector< const CDCWireHit * > &foundAxialWireHits, const std::vector< const CDCWireHit * > &allAxialWireHits, std::vector< CDCTrack > &axialTracks, bool withPostprocessing=true)
Create CDCTrack using CDCWireHit hits and store it in the list. Then call the postprocessing on it.