Belle II Software  release-08-01-10
HitInfoExtractor.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 
9 #pragma once
10 #include <tracking/trackFindingVXD/variableExtractors/VariableExtractor.h>
11 #include <tracking/dataobjects/RecoTrack.h>
12 #include <tracking/dataobjects/RecoHitInformation.h>
13 
14 #include <genfit/KalmanFitterInfo.h>
15 #include <genfit/TrackPoint.h>
16 #include <numeric>
17 #include <algorithm>
18 #include <optional>
19 
20 namespace Belle2 {
27  public:
31  explicit HitInfoExtractor(std::vector<Named<float*>>& variableSet) :
33  {
34  addVariable("N_TrackPoints_without_KalmanFitterInfo", variableSet);
35  addVariable("N_Hits_without_TrackPoint", variableSet);
36 
37  initializeStats("weight", variableSet);
38  initializeStats("smoothedChi2", variableSet);
39  }
40 
42  void extractVariables(const RecoTrack& recoTrack)
43  {
44  // get fitting parameters
45  const std::vector<RecoHitInformation*>& recoHitInformations = recoTrack.getRecoHitInformations(true);
46  std::vector<const genfit::KalmanFitterInfo*> kalmanFitterInfos;
47  kalmanFitterInfos.reserve(recoHitInformations.size());
48 
49  int n_no_trackPoint = 0; // number of recoHitInformations without related track points
50  int n_no_KalmanFitterInfo = 0; // number of track points without related KalmanFitterInfo
51  for (const RecoHitInformation* recoHitInformation : recoHitInformations) {
52  const genfit::TrackPoint* trackPoint = recoTrack.getCreatedTrackPoint(recoHitInformation);
53  if (trackPoint) {
54  const genfit::KalmanFitterInfo* kalmanFitterInfo = trackPoint->getKalmanFitterInfo();
55  if (kalmanFitterInfo) {
56  kalmanFitterInfos.push_back(kalmanFitterInfo);
57  } else {
58  n_no_KalmanFitterInfo++;
59  }
60  } else {
61  n_no_trackPoint++;
62  }
63  }
64  m_variables.at("N_Hits_without_TrackPoint") = n_no_trackPoint;
65  m_variables.at("N_TrackPoints_without_KalmanFitterInfo") = n_no_KalmanFitterInfo;
66 
67  // define lambda to which checks if hitinfo has kalman info and is from a specific detector
68  // use that via std::find_if to find first/last fitted hits from that detector
69  const auto hitHasKalmanInfoAndIsFromDetector =
70  [&recoTrack, this](const auto & recoHitInformation,
71  RecoHitInformation::RecoHitDetector trackingDetector) {
72  return (this->getKalmanFitterInfo(recoTrack, recoHitInformation)
73  and (recoHitInformation->getTrackingDetector() == trackingDetector));
74  };
75  const auto hitHasKalmanInfoAndIsFromCDC = std::bind(hitHasKalmanInfoAndIsFromDetector,
76  std::placeholders::_1,
77  RecoHitInformation::c_CDC);
78  const auto hitHasKalmanInfoAndIsFromSVD = std::bind(hitHasKalmanInfoAndIsFromDetector,
79  std::placeholders::_1,
80  RecoHitInformation::c_SVD);
81 
82  // find first CDC hit with Kalman info and extract weight and Chi2
83  const auto firstHitWithCDCKalmanInfoIter = std::find_if(recoHitInformations.begin(),
84  recoHitInformations.end(),
85  hitHasKalmanInfoAndIsFromCDC);
86  std::optional<float> weight_firstCDCHit;
87  std::optional<float> smoothedChi2_firstCDCHit;
88  if (firstHitWithCDCKalmanInfoIter != recoHitInformations.end()) {
89  const genfit::KalmanFitterInfo* kalmanFitterInfo = this->getKalmanFitterInfo(recoTrack, *firstHitWithCDCKalmanInfoIter);
90  weight_firstCDCHit = kalmanFitterInfo->getWeights().front();
91  smoothedChi2_firstCDCHit = this->getSmoothedChi2(kalmanFitterInfo);
92  }
93  m_variables.at("weight_firstCDCHit") = weight_firstCDCHit.value_or(m_valueIfNAN);
94  m_variables.at("smoothedChi2_firstCDCHit") = smoothedChi2_firstCDCHit.value_or(m_valueIfNAN);
95 
96  // find last SVD hit with Kalman info and extract weight and Chi2
97  const auto lastHitWithSVDKalmanInfoIter = std::find_if(recoHitInformations.rbegin(),
98  recoHitInformations.rend(),
99  hitHasKalmanInfoAndIsFromSVD);
100  std::optional<float> weight_lastSVDHit;
101  std::optional<float> smoothedChi2_lastSVDHit;
102  if (lastHitWithSVDKalmanInfoIter != recoHitInformations.rend()) {
103  const genfit::KalmanFitterInfo* kalmanFitterInfo = this->getKalmanFitterInfo(recoTrack, *lastHitWithSVDKalmanInfoIter);
104  weight_lastSVDHit = kalmanFitterInfo->getWeights().front();
105  smoothedChi2_lastSVDHit = this->getSmoothedChi2(kalmanFitterInfo);
106  }
107  m_variables.at("weight_lastSVDHit") = weight_lastSVDHit.value_or(m_valueIfNAN);
108  m_variables.at("smoothedChi2_lastSVDHit") = smoothedChi2_lastSVDHit.value_or(m_valueIfNAN);
109 
110  std::vector<float> fitWeights;
111  std::vector<float> chi2Values;
112  fitWeights.reserve(kalmanFitterInfos.size());
113  chi2Values.reserve(kalmanFitterInfos.size());
114  for (const auto& kalmanFitterInfo : kalmanFitterInfos) {
115  fitWeights.push_back(kalmanFitterInfo->getWeights().front());
116  chi2Values.push_back(this->getSmoothedChi2(kalmanFitterInfo).value_or(m_valueIfNAN));
117  }
118  setStats("weight", fitWeights);
119  setStats("smoothedChi2", chi2Values);
120  }
121 
122  protected:
124  void initializeStats(const std::string& identifier, std::vector<Named<float*>>& variables)
125  {
126  addVariable(identifier + "_max", variables);
127  addVariable(identifier + "_min", variables);
128  addVariable(identifier + "_mean", variables);
129  addVariable(identifier + "_std", variables);
130  addVariable(identifier + "_median", variables);
131  addVariable(identifier + "_n_zeros", variables);
132  addVariable(identifier + "_firstCDCHit", variables);
133  addVariable(identifier + "_lastSVDHit", variables);
134  }
135 
137  void setStats
138  (const std::string& identifier, std::vector<float>& values)
139  {
140  int size = values.size();
141  if (values.size() == 0) {
142  m_variables.at(identifier + "_max") = m_valueIfNAN;
143  m_variables.at(identifier + "_min") = m_valueIfNAN;
144  m_variables.at(identifier + "_mean") = m_valueIfNAN;
145  m_variables.at(identifier + "_std") = m_valueIfNAN;
146  m_variables.at(identifier + "_median") = m_valueIfNAN;
147  m_variables.at(identifier + "_n_zeros") = m_valueIfNAN;
148  m_variables.at(identifier + "_firstCDCHit") = m_valueIfNAN;
149  m_variables.at(identifier + "_lastSVDHit") = m_valueIfNAN;
150  return;
151  }
152 
153  std::sort(values.begin(), values.end());
154 
155  float sum = std::accumulate(values.begin(), values.end(), 0.0);
156  float mean = sum / size;
157  m_variables.at(identifier + "_mean") = mean;
158  float variance = 0.;
159  int n_zeros = 0;
160  for (float value : values) {
161  variance += (value - mean) * (value - mean);
162  if (value == 0)
163  n_zeros++;
164  }
165  m_variables.at(identifier + "_n_zeros") = n_zeros;
166  variance /= size - 1;
167  float stddev = std::sqrt(variance);
168  m_variables.at(identifier + "_std") = stddev;
169  m_variables.at(identifier + "_min") = values.front();
170  m_variables.at(identifier + "_max") = values.back();
171  // only in the case size==0 there would be a negative container index, but that case is handled above. So the suppress for cppcheck:
172  // cppcheck-suppress negativeContainerIndex
173  float median = (size % 2) ? values[size / 2] : 0.5 * (values[size / 2] + values[size / 2 - 1]);
174  m_variables.at(identifier + "_median") = median;
175  }
176 
177  private:
180  const RecoHitInformation* recoHitInformation)
181  {
182  const genfit::TrackPoint* trackPointPtr = recoTrack.getCreatedTrackPoint(recoHitInformation);
183  if (trackPointPtr) {
184  return trackPointPtr->getKalmanFitterInfo();
185  } else {
186  return nullptr;
187  }
188  }
191  std::optional<float> getSmoothedChi2(const genfit::KalmanFitterInfo* kalmanFitterInfo)
192  {
193  try {
194  return kalmanFitterInfo->getSmoothedChi2();
195  } catch (const std::exception& e) {
196  B2WARNING("HitInfoExtractor: Caught exception in kalmanFitterInfos[i]->getSmoothedChi2() \n"
197  << "-->" << e.what());
198  return std::nullopt;
199  }
200  }
201 
206  const float m_valueIfNAN = -1.0;
207  };
209 }
class to extract info from individual clusters and combine for SPTC
genfit::KalmanFitterInfo * getKalmanFitterInfo(const RecoTrack &recoTrack, const RecoHitInformation *recoHitInformation)
Helper function to get Kalman fitter info from RecoHitInformation if available.
const float m_valueIfNAN
Define a default value to use if a variable cannot be calculated.
HitInfoExtractor(std::vector< Named< float * >> &variableSet)
Constructor fills variableSet with variables to be extracted.
std::optional< float > getSmoothedChi2(const genfit::KalmanFitterInfo *kalmanFitterInfo)
Helper function to safely get Chi2 from a KalmanFitterInfo object if available, and if not return nul...
void extractVariables(const RecoTrack &recoTrack)
extract variables from SpacePoints
void setStats(const std::string &identifier, std::vector< float > &values)
calculated statistics and saves them in variable set
void initializeStats(const std::string &identifier, std::vector< Named< float * >> &variables)
initialize statistics subsets of variables from clusters that get combined for SPTC
This class stores additional information to every CDC/SVD/PXD hit stored in a RecoTrack.
RecoHitDetector
The detector this hit comes from (which is of course also visible in the hit type)
This is the Reconstruction Event-Data Model Track.
Definition: RecoTrack.h:79
const genfit::TrackPoint * getCreatedTrackPoint(const RecoHitInformation *recoHitInformation) const
Get a pointer to the TrackPoint that was created from this hit.
Definition: RecoTrack.cc:230
std::vector< RecoHitInformation * > getRecoHitInformations(bool getSorted=false) const
Return a list of all RecoHitInformations associated with the RecoTrack.
Definition: RecoTrack.cc:557
class to extract individual variables
std::unordered_map< std::string, float > m_variables
unordered_map to associate float value with a string name
void addVariable(const std::string &identifier, std::vector< Named< float * >> &variables)
add a variable to the variable set
Collects information needed and produced by a AbsKalmanFitter implementations and is specific to one ...
std::vector< double > getWeights() const
Get weights of measurements.
Object containing AbsMeasurement and AbsFitterInfo objects.
Definition: TrackPoint.h:46
KalmanFitterInfo * getKalmanFitterInfo(const AbsTrackRep *rep=nullptr) const
Helper to avoid casting.
Definition: TrackPoint.cc:180
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Abstract base class for different kinds of events.