Belle II Software development
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
20namespace 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
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:
179 genfit::KalmanFitterInfo* getKalmanFitterInfo(const RecoTrack& recoTrack,
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
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.
void initializeStats(const std::string &identifier, std::vector< Named< float * > > &variables)
initialize statistics subsets of variables from clusters that get combined for SPTC
void extractVariables(const RecoTrack &recoTrack)
extract variables from SpacePoints
genfit::KalmanFitterInfo * getKalmanFitterInfo(const RecoTrack &recoTrack, const RecoHitInformation *recoHitInformation)
Helper function to get Kalman fitter info from RecoHitInformation if available.
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 setStats(const std::string &identifier, std::vector< float > &values)
calculated statistics and saves them in variable set
A mixin class to attach a name to an object. Based on class with same name in CDC package.
Definition: Named.h:21
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
void addVariable(const std::string &identifier, std::vector< Named< float * > > &variables)
add a variable to the variable set
std::unordered_map< std::string, float > m_variables
unordered_map to associate float value with a string name
Abstract base class for different kinds of events.