CMS 3D CMS Logo

L1TrackQuality.cc
Go to the documentation of this file.
1 /*
2 Track Quality Body file
3 
4 C.Brown & C.Savard 07/2020
5 */
6 
9 
10 //Constructors
11 
13 
15  std::string AlgorithmString = qualityParams.getParameter<std::string>("qualityAlgorithm");
16  // Unpacks EDM parameter set itself to save unecessary processing within TrackProducers
17  if (AlgorithmString == "Cut") {
18  setCutParameters(AlgorithmString,
19  (float)qualityParams.getParameter<double>("maxZ0"),
20  (float)qualityParams.getParameter<double>("maxEta"),
21  (float)qualityParams.getParameter<double>("chi2dofMax"),
22  (float)qualityParams.getParameter<double>("bendchi2Max"),
23  (float)qualityParams.getParameter<double>("minPt"),
24  qualityParams.getParameter<int>("nStubsmin"));
25  }
26 
27  else {
28  setONNXModel(AlgorithmString,
29  qualityParams.getParameter<edm::FileInPath>("ONNXmodel"),
30  qualityParams.getParameter<std::string>("ONNXInputName"),
31  qualityParams.getParameter<std::vector<std::string>>("featureNames"));
32  ONNXInvRScaling_ = qualityParams.getParameter<double>("ONNXInvRScale");
33  }
34 }
35 
37  std::vector<std::string> const& featureNames) {
38  // List input features for MVA in proper order below, the features options are
39  // {"log_chi2","log_chi2rphi","log_chi2rz","log_bendchi2","nstubs","lay1_hits","lay2_hits",
40  // "lay3_hits","lay4_hits","lay5_hits","lay6_hits","disk1_hits","disk2_hits","disk3_hits",
41  // "disk4_hits","disk5_hits","rinv","tanl","z0","dtot","ltot","chi2","chi2rz","chi2rphi",
42  // "bendchi2","pt","eta","nlaymiss_interior","phi","bendchi2_bin","chi2rz_bin","chi2rphi_bin"}
43 
44  std::vector<float> transformedFeatures;
45 
46  // Define feature map, filled as features are generated
47  std::map<std::string, float> feature_map;
48 
49  // The following converts the 7 bit hitmask in the TTTrackword to an expected
50  // 11 bit hitmask based on the eta of the track
51  std::vector<int> hitpattern_binary = {0, 0, 0, 0, 0, 0, 0};
52  std::vector<int> hitpattern_expanded_binary = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
53  std::vector<float> eta_bins = {0.0, 0.2, 0.41, 0.62, 0.9, 1.26, 1.68, 2.08, 2.4};
54 
55  // Expected hitmap table, each row corresponds to an eta bin, each value corresponds to
56  // the expected layer in the expanded hit pattern. The expanded hit pattern should be
57  // 11 bits but contains a 12th element so this hitmap table is symmetric
58  int hitmap[8][7] = {{0, 1, 2, 3, 4, 5, 11},
59  {0, 1, 2, 3, 4, 5, 11},
60  {0, 1, 2, 3, 4, 5, 11},
61  {0, 1, 2, 3, 4, 5, 11},
62  {0, 1, 2, 3, 4, 5, 11},
63  {0, 1, 2, 6, 7, 8, 9},
64  {0, 1, 7, 8, 9, 10, 11},
65  {0, 6, 7, 8, 9, 10, 11}};
66 
67  // iterate through bits of the hitpattern and compare to 1 filling the hitpattern binary vector
68  int tmp_trk_hitpattern = aTrack.hitPattern();
69  for (int i = 6; i >= 0; i--) {
70  int k = tmp_trk_hitpattern >> i;
71  if (k & 1)
72  hitpattern_binary[i] = 1;
73  }
74 
75  // calculate number of missed interior layers from hitpattern
76  int nbits = floor(log2(tmp_trk_hitpattern)) + 1;
77  int lay_i = 0;
78  int tmp_trk_nlaymiss_interior = 0;
79  bool seq = false;
80  for (int i = 0; i < nbits; i++) {
81  lay_i = ((1 << i) & tmp_trk_hitpattern) >> i; //0 or 1 in ith bit (right to left)
82 
83  if (lay_i && !seq)
84  seq = true; //sequence starts when first 1 found
85  if (!lay_i && seq)
86  tmp_trk_nlaymiss_interior++;
87  }
88 
89  float eta = abs(aTrack.eta());
90  int eta_size = static_cast<int>(eta_bins.size());
91  // First iterate through eta bins
92 
93  for (int j = 1; j < eta_size; j++) {
94  if (eta < eta_bins[j] && eta >= eta_bins[j - 1]) // if track in eta bin
95  {
96  // Iterate through hitpattern binary
97  for (int k = 0; k <= 6; k++)
98  // Fill expanded binary entries using the expected hitmap table positions
99  hitpattern_expanded_binary[hitmap[j - 1][k]] = hitpattern_binary[k];
100  break;
101  }
102  }
103 
104  int tmp_trk_ltot = 0;
105  //calculate number of layer hits
106  for (int i = 0; i < 6; ++i) {
107  tmp_trk_ltot += hitpattern_expanded_binary[i];
108  }
109 
110  int tmp_trk_dtot = 0;
111  //calculate number of disk hits
112  for (int i = 6; i < 11; ++i) {
113  tmp_trk_dtot += hitpattern_expanded_binary[i];
114  }
115 
116  // bin bendchi2 variable (bins from https://twiki.cern.ch/twiki/bin/viewauth/CMS/HybridDataFormat#Fitted_Tracks_written_by_KalmanF)
117  float tmp_trk_bendchi2 = aTrack.stubPtConsistency();
118  std::array<float, 8> bendchi2_bins{{0, 0.5, 1.25, 2, 3, 5, 10, 50}};
119  int n_bendchi2 = static_cast<int>(bendchi2_bins.size());
120  float tmp_trk_bendchi2_bin = -1;
121  for (int i = 0; i < (n_bendchi2 - 1); i++) {
122  if (tmp_trk_bendchi2 >= bendchi2_bins[i] && tmp_trk_bendchi2 < bendchi2_bins[i + 1]) {
123  tmp_trk_bendchi2_bin = i;
124  break;
125  }
126  }
127  if (tmp_trk_bendchi2_bin < 0)
128  tmp_trk_bendchi2_bin = n_bendchi2;
129 
130  // bin chi2rphi variable (bins from https://twiki.cern.ch/twiki/bin/viewauth/CMS/HybridDataFormat#Fitted_Tracks_written_by_KalmanF)
131  float tmp_trk_chi2rphi = aTrack.chi2XY();
132  std::array<float, 16> chi2rphi_bins{{0, 0.25, 0.5, 1, 2, 3, 5, 7, 10, 20, 40, 100, 200, 500, 1000, 3000}};
133  int n_chi2rphi = static_cast<int>(chi2rphi_bins.size());
134  float tmp_trk_chi2rphi_bin = -1;
135  for (int i = 0; i < (n_chi2rphi - 1); i++) {
136  if (tmp_trk_chi2rphi >= chi2rphi_bins[i] && tmp_trk_chi2rphi < chi2rphi_bins[i + 1]) {
137  tmp_trk_chi2rphi_bin = i;
138  break;
139  }
140  }
141  if (tmp_trk_chi2rphi_bin < 0)
142  tmp_trk_chi2rphi_bin = n_chi2rphi;
143 
144  // bin chi2rz variable (bins from https://twiki.cern.ch/twiki/bin/viewauth/CMS/HybridDataFormat#Fitted_Tracks_written_by_KalmanF)
145  float tmp_trk_chi2rz = aTrack.chi2Z();
146  std::array<float, 16> chi2rz_bins{{0, 0.25, 0.5, 1, 2, 3, 5, 7, 10, 20, 40, 100, 200, 500, 1000, 3000}};
147  int n_chi2rz = static_cast<int>(chi2rz_bins.size());
148  float tmp_trk_chi2rz_bin = -1;
149  for (int i = 0; i < (n_chi2rz - 1); i++) {
150  if (tmp_trk_chi2rz >= chi2rz_bins[i] && tmp_trk_chi2rz < chi2rz_bins[i + 1]) {
151  tmp_trk_chi2rz_bin = i;
152  break;
153  }
154  }
155  if (tmp_trk_chi2rz_bin < 0)
156  tmp_trk_chi2rz_bin = n_chi2rz;
157 
158  // get the nstub
159  std::vector<edm::Ref<edmNew::DetSetVector<TTStub<Ref_Phase2TrackerDigi_>>, TTStub<Ref_Phase2TrackerDigi_>>> stubRefs =
160  aTrack.getStubRefs();
161 
162  // fill the feature map
163  feature_map["nstub"] = stubRefs.size();
164  feature_map["rinv"] = ONNXInvRScaling_ * abs(aTrack.rInv());
165  feature_map["tanl"] = abs(aTrack.tanL());
166  feature_map["z0"] = aTrack.z0();
167  feature_map["phi"] = aTrack.phi();
168  feature_map["pt"] = aTrack.momentum().perp();
169  feature_map["eta"] = aTrack.eta();
170 
171  float tmp_trk_chi2 = aTrack.chi2();
172  feature_map["chi2"] = tmp_trk_chi2;
173  feature_map["log_chi2"] = log(tmp_trk_chi2);
174 
175  feature_map["chi2rphi"] = tmp_trk_chi2rphi;
176  feature_map["log_chi2rphi"] = log(tmp_trk_chi2rphi);
177 
178  feature_map["chi2rz"] = tmp_trk_chi2rz;
179  feature_map["log_chi2rz"] = log(tmp_trk_chi2rz);
180 
181  feature_map["chi2rz"] = tmp_trk_chi2rz;
182  feature_map["log_chi2rz"] = log(tmp_trk_chi2rz);
183 
184  feature_map["bendchi2"] = tmp_trk_bendchi2;
185  feature_map["log_bendchi2"] = log(tmp_trk_bendchi2);
186 
187  feature_map["lay1_hits"] = float(hitpattern_expanded_binary[0]);
188  feature_map["lay2_hits"] = float(hitpattern_expanded_binary[1]);
189  feature_map["lay3_hits"] = float(hitpattern_expanded_binary[2]);
190  feature_map["lay4_hits"] = float(hitpattern_expanded_binary[3]);
191  feature_map["lay5_hits"] = float(hitpattern_expanded_binary[4]);
192  feature_map["lay6_hits"] = float(hitpattern_expanded_binary[5]);
193  feature_map["disk1_hits"] = float(hitpattern_expanded_binary[6]);
194  feature_map["disk2_hits"] = float(hitpattern_expanded_binary[7]);
195  feature_map["disk3_hits"] = float(hitpattern_expanded_binary[8]);
196  feature_map["disk4_hits"] = float(hitpattern_expanded_binary[9]);
197  feature_map["disk5_hits"] = float(hitpattern_expanded_binary[10]);
198 
199  feature_map["dtot"] = float(tmp_trk_dtot);
200  feature_map["ltot"] = float(tmp_trk_ltot);
201 
202  feature_map["nlaymiss_interior"] = float(tmp_trk_nlaymiss_interior);
203  feature_map["bendchi2_bin"] = tmp_trk_bendchi2_bin;
204  feature_map["chi2rphi_bin"] = tmp_trk_chi2rphi_bin;
205  feature_map["chi2rz_bin"] = tmp_trk_chi2rz_bin;
206 
207  // fill tensor with track params
208  transformedFeatures.reserve(featureNames.size());
209  for (const std::string& feature : featureNames)
210  transformedFeatures.push_back(feature_map[feature]);
211 
212  return transformedFeatures;
213 }
214 
217  // Get Track parameters
218  float trk_pt = aTrack.momentum().perp();
219  float trk_bend_chi2 = aTrack.stubPtConsistency();
220  float trk_z0 = aTrack.z0();
221  float trk_eta = aTrack.momentum().eta();
222  float trk_chi2 = aTrack.chi2();
223  const auto& stubRefs = aTrack.getStubRefs();
224  int nStubs = stubRefs.size();
225 
226  float classification = 0.0; // Default classification is 0
227 
228  if (trk_pt >= this->minPt_ && abs(trk_z0) < this->maxZ0_ && abs(trk_eta) < this->maxEta_ &&
229  trk_chi2 < this->chi2dofMax_ && trk_bend_chi2 < this->bendchi2Max_ && nStubs >= this->nStubsmin_)
230  classification = 1.0;
231  // Classification updated to 1 if conditions are met
232 
233  aTrack.settrkMVA1(classification);
234  }
235 
237  // Setup ONNX input and output names and arrays
238  std::vector<std::string> ortinput_names;
239  std::vector<std::string> ortoutput_names;
240 
241  cms::Ort::FloatArrays ortinput;
242  cms::Ort::FloatArrays ortoutputs;
243 
244  std::vector<float> Transformed_features = featureTransform(aTrack, this->featureNames_);
245  cms::Ort::ONNXRuntime Runtime(this->ONNXmodel_.fullPath()); //Setup ONNX runtime
246 
247  ortinput_names.push_back(this->ONNXInputName_);
248  ortoutput_names = Runtime.getOutputNames();
249 
250  //ONNX runtime recieves a vector of vectors of floats so push back the input
251  // vector of float to create a 1,1,21 ortinput
252  ortinput.push_back(Transformed_features);
253 
254  // batch_size 1 as only one set of transformed features is being processed
255  int batch_size = 1;
256  // Run classification
257  ortoutputs = Runtime.run(ortinput_names, ortinput, {}, ortoutput_names, batch_size);
258 
260  aTrack.settrkMVA1(ortoutputs[0][0]);
261  }
262 
263  else if (this->qualityAlgorithm_ == QualityAlgorithm::GBDT) {
264  aTrack.settrkMVA1(ortoutputs[1][1]);
265  }
266  // Slight differences in the ONNX models of the GBDTs and NNs mean different
267  // indices of the ortoutput need to be accessed
268  }
269 
270  else {
271  aTrack.settrkMVA1(-999);
272  }
273 }
274 
275 void L1TrackQuality::setCutParameters(std::string const& AlgorithmString,
276  float maxZ0,
277  float maxEta,
278  float chi2dofMax,
279  float bendchi2Max,
280  float minPt,
281  int nStubmin) {
283  maxZ0_ = maxZ0;
284  maxEta_ = maxEta;
287  minPt_ = minPt;
288  nStubsmin_ = nStubmin;
289 }
290 
291 void L1TrackQuality::setONNXModel(std::string const& AlgorithmString,
292  edm::FileInPath const& ONNXmodel,
293  std::string const& ONNXInputName,
294  std::vector<std::string> const& featureNames) {
295  //Convert algorithm string to Enum class for track by track comparison
296  if (AlgorithmString == "NN") {
298  } else if (AlgorithmString == "GBDT") {
300  } else {
302  }
306 }
float ONNXInvRScaling_
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
T perp() const
Definition: PV3DBase.h:69
double eta() const
Track eta.
Definition: TTTrack.h:310
std::string fullPath() const
Definition: FileInPath.cc:161
void setL1TrackQuality(TTTrack< Ref_Phase2TrackerDigi_ > &aTrack)
void setCutParameters(std::string const &AlgorithmString, float maxZ0, float maxEta, float chi2dofMax, float bendchi2Max, float minPt, int nStubmin)
T eta() const
Definition: PV3DBase.h:73
double phi() const
Track phi.
Definition: TTTrack.h:315
double tanL() const
Track tanL.
Definition: TTTrack.h:305
double maxEta
unsigned int hitPattern() const
Hit Pattern.
Definition: TTTrack.h:423
double chi2Z() const
Chi2Z.
Definition: TTTrack.h:347
GlobalVector momentum() const
Track momentum.
Definition: TTTrack.h:295
std::vector< std::vector< float > > FloatArrays
Definition: ONNXRuntime.h:23
const std::vector< std::string > & getOutputNames() const
Definition: ONNXRuntime.cc:167
void setONNXModel(std::string const &AlgorithmString, edm::FileInPath const &ONNXmodel, std::string const &ONNXInputName, std::vector< std::string > const &featureNames)
void settrkMVA1(double atrkMVA1)
Definition: TTTrack.h:381
QualityAlgorithm qualityAlgorithm_
double chi2() const
Chi2.
Definition: TTTrack.h:341
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double rInv() const
Track curvature.
Definition: TTTrack.h:300
double chi2XY() const
Chi2XY.
Definition: TTTrack.h:353
Class to store the L1 Track Trigger stubs.
Definition: TTStub.h:22
std::vector< edm::Ref< edmNew::DetSetVector< TTStub< T > >, TTStub< T > > > getStubRefs() const
Track components.
Definition: TTTrack.h:93
std::vector< float > featureTransform(TTTrack< Ref_Phase2TrackerDigi_ > &aTrack, std::vector< std::string > const &featureNames)
Class to store the L1 Track Trigger tracks.
Definition: TTTrack.h:29
double stubPtConsistency() const
StubPtConsistency.
Definition: TTTrack.h:417
std::vector< std::string > featureNames_
edm::FileInPath ONNXmodel_
double z0() const
Track z0.
Definition: TTTrack.h:330
std::string ONNXInputName_