Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HFTriggerMVA.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file HFTriggerMVA.cc
1 #include "HFTriggerMVA.h"
2 
3 /*
4  * Basic heavy flavor software trigger
5  * Used in study of hardware trigger
6  * Cameron Dean
7  * 01/02/2021
8  */
9 std::map<std::string, bool> triggerDecisionsMVA =
10 {
11  {"cuts", false}
12 , {"cutsWithoutCalo", false}
13 , {"MVAWithCalo", false}
14 , {"MVAWithoutCalo", false}
15 , {"MVAWithoutCaloAndMinTrack", false}
16 };
17 /*
18 namespace HFTriggerMVARequirement
19 {
20  float meanMult = 12; //Set min num. INTT hits
21  float asymmMult = 0.1; //Set asymm between INTT layers (fraction)
22  float trackVertex3DDCA = 0.05; //Min. 3D DCA of a track with any vertex in cm
23  float trackVertex2DDCA = 0.05; //Max. 2D DCA of a track with any vertex in cm
24  float trackTrackDCA = 0.05; //Max. DCA of a track with other tracks in cm
25  float minEMCalEnergy = 0.5;
26  float MVA_wCaloResponse = -0.05;
27  float MVA_woutCaloResponse = -0.05;
28  float MVA_woutCaloOrMinTrackResponse = -0.05;
29 }
30 */
32  : SubsysReco("HFTRIGGER")
33  , m_useCutsTrigger(true)
34  , m_useCutswoutTrigger(true)
35  , m_useMVAwCaloTrigger(true)
36  , m_useMVAwoutCaloTrigger(true)
37  , m_useMVAwoutCaloAndMinTrackTrigger(true)
38 {
39 }
40 
42  : SubsysReco(name)
43  , m_useCutsTrigger(true)
44  , m_useCutswoutTrigger(true)
45  , m_useMVAwCaloTrigger(true)
46  , m_useMVAwoutCaloTrigger(true)
47  , m_useMVAwoutCaloAndMinTrackTrigger(true)
48 {
49 }
50 
52 {
53  std::cout << "--Cut parameters--" << std::endl;
54  std::cout << "meanMult: " << meanMult << std::endl;
55  std::cout << "trackVertex3DDCA: " << trackVertex3DDCA << std::endl;
56  std::cout << "trackVertex2DDCA: " << trackVertex2DDCA << std::endl;
57  std::cout << "trackTrackDCA: " << trackTrackDCA << std::endl;
58  std::cout << "minEMCalEnergy: " << minEMCalEnergy << std::endl;
59  std::cout << "MVA_wCaloResponse: " << MVA_wCaloResponse << std::endl;
60  std::cout << "MVA_woutCaloResponse: " << MVA_woutCaloResponse << std::endl;
61  std::cout << "MVA_woutCaloOrMinTrackResponse: " << MVA_woutCaloOrMinTrackResponse << std::endl;
62  std::cout << "-----------------" << std::endl;
63 
65  {
66  std::string algorithmFile = path + "wCalo/TMVAClassification_" + mvaType + ".weights.xml";
67  std::tie(wCaloReader, wCaloFloats) = initMVA(varListwCalo, mvaType, algorithmFile);
68  }
70  {
71  std::string algorithmFile = path + "woutCalo/TMVAClassification_" + mvaType + ".weights.xml";
72  std::tie(woutCaloReader, woutCaloFloats) = initMVA(varListwoutCalo, mvaType, algorithmFile);
73  }
75  {
76  std::string algorithmFile = path + "woutCaloAndMinTrack/TMVAClassification_" + mvaType + ".weights.xml";
78  }
79 
80  return 0;
81 }
82 
84 {
85  bool successfulTrigger = runTrigger(topNode);
86 
87  if (Verbosity() >= VERBOSITY_MORE)
88  {
89  if (successfulTrigger) std::cout << "One of the heavy flavor triggers fired" << std::endl;
90  else std::cout << "No heavy flavor triggers fired" << std::endl;
91  }
92 
93  if (triggerDecisionsMVA.find("cuts")->second && triggerDecisionsMVA.find("MVAWithCalo")->second) m_cuts_and_mva_wcalo_counter += 1;
94  if (!triggerDecisionsMVA.find("cuts")->second && triggerDecisionsMVA.find("MVAWithCalo")->second) m_no_cuts_and_mva_wcalo_counter += 1;
95  if (triggerDecisionsMVA.find("cuts")->second && !triggerDecisionsMVA.find("MVAWithCalo")->second) m_cuts_and_no_mva_wcalo_counter += 1;
96  if (!triggerDecisionsMVA.find("cuts")->second && !triggerDecisionsMVA.find("MVAWithCalo")->second) m_no_cuts_and_no_mva_wcalo_counter += 1;
97 
98  if (triggerDecisionsMVA.find("cutsWithoutCalo")->second && triggerDecisionsMVA.find("MVAWithoutCalo")->second) m_cuts_and_mva_woutcalo_counter += 1;
99  if (!triggerDecisionsMVA.find("cutsWithoutCalo")->second && triggerDecisionsMVA.find("MVAWithoutCalo")->second) m_no_cuts_and_mva_woutcalo_counter += 1;
100  if (triggerDecisionsMVA.find("cutsWithoutCalo")->second && !triggerDecisionsMVA.find("MVAWithoutCalo")->second) m_cuts_and_no_mva_woutcalo_counter += 1;
101  if (!triggerDecisionsMVA.find("cutsWithoutCalo")->second && !triggerDecisionsMVA.find("MVAWithoutCalo")->second) m_no_cuts_and_no_mva_woutcalo_counter += 1;
102 
103  if (triggerDecisionsMVA.find("cutsWithoutCalo")->second && triggerDecisionsMVA.find("MVAWithoutCaloAndMinTrack")->second) m_cuts_and_mva_woutcalo_and_mintracks_counter += 1;
104  if (!triggerDecisionsMVA.find("cutsWithoutCalo")->second && triggerDecisionsMVA.find("MVAWithoutCaloAndMinTrack")->second) m_no_cuts_and_mva_woutcalo_and_mintracks_counter += 1;
105  if (triggerDecisionsMVA.find("cutsWithoutCalo")->second && !triggerDecisionsMVA.find("MVAWithoutCaloAndMinTrack")->second) m_cuts_and_no_mva_woutcalo_and_mintracks_counter += 1;
106  if (!triggerDecisionsMVA.find("cutsWithoutCalo")->second && !triggerDecisionsMVA.find("MVAWithoutCaloAndMinTrack")->second) m_no_cuts_and_no_mva_woutcalo_and_mintracks_counter += 1;
107 
108  m_events += 1;
109  if (successfulTrigger) m_counter += 1;
110  if (!successfulTrigger) m_no_trigger += 1;
111 
112  triggerDecisionsMVA.find("cuts")->second = false;
113  triggerDecisionsMVA.find("cutsWithoutCalo")->second = false;
114  triggerDecisionsMVA.find("MVAWithCalo")->second = false;
115  triggerDecisionsMVA.find("MVAWithoutCalo")->second = false;
116  triggerDecisionsMVA.find("MVAWithoutCaloAndMinTrack")->second = false;
117 
119 }
120 
122 {
124  return 0;
125 }
126 
128 {
129  bool anyTriggerFired = false;
130 
131  std::vector<Track> allTracks = makeAllTracks(topNode);
132  std::vector<Vertex> allVertices = makeAllPrimaryVertices(topNode);
133 
134  float min_TrackVertex_3D_DCA = 0;
135  float min_TrackVertex_2D_DCA = 0;
136  float max_TrackVertex_3D_DCA = 0;
137  float max_TrackVertex_2D_DCA = 0;
138  float min_TrackTrack_3D_DCA = 0;
139 
140  float meanMult = 0;
141  float asymmMult = 0;
142  calculateMultiplicity(topNode, meanMult, asymmMult);
143 
144  float maxEMCalEnergy = getMaxEMCalEnergy(topNode);
145 
146  for (unsigned int k = 0; k < allVertices.size(); k++)
147  {
148  for (unsigned int i = 0; i < allTracks.size(); i++)
149  {
150  for (unsigned int j = i + 1; j < allTracks.size(); j++)
151  {
152 
153  getIPVariables(allTracks[i], allTracks[j], allVertices[k],
154  min_TrackVertex_3D_DCA, min_TrackVertex_2D_DCA,
155  max_TrackVertex_3D_DCA, max_TrackVertex_2D_DCA,
156  min_TrackTrack_3D_DCA);
157 
158  wCaloFloats[0] = woutCaloFloats[0] = min_TrackVertex_3D_DCA;
159  wCaloFloats[1] = woutCaloFloats[1] = min_TrackVertex_2D_DCA;
160  wCaloFloats[2] = woutCaloFloats[2] = woutCaloAndMinTrackFloats[0] = max_TrackVertex_3D_DCA;
161  wCaloFloats[3] = woutCaloFloats[3] = woutCaloAndMinTrackFloats[1] = max_TrackVertex_2D_DCA;
162  wCaloFloats[4] = maxEMCalEnergy;
163  wCaloFloats[5] = woutCaloFloats[4] = woutCaloAndMinTrackFloats[2] = min_TrackTrack_3D_DCA;
165 
166  if (m_useCutsTrigger)
167  {
168  bool trigger = runCutsTrigger(meanMult, maxEMCalEnergy,
169  max_TrackVertex_3D_DCA,
170  max_TrackVertex_2D_DCA,
171  min_TrackTrack_3D_DCA);
172 
173  if (trigger) triggerDecisionsMVA.find("cuts")->second = true;
174  }
175 
177  {
178  bool trigger = runCutsTrigger(meanMult, FLT_MAX,
179  max_TrackVertex_3D_DCA,
180  max_TrackVertex_2D_DCA,
181  min_TrackTrack_3D_DCA);
182 
183  if (trigger) triggerDecisionsMVA.find("cutsWithoutCalo")->second = true;
184  }
185 
187  {
189  if (trigger) triggerDecisionsMVA.find("MVAWithCalo")->second = true;
190  }
191 
193  {
195  if (trigger) triggerDecisionsMVA.find("MVAWithoutCalo")->second = true;
196  }
197 
199  {
201  if (trigger) triggerDecisionsMVA.find("MVAWithoutCaloAndMinTrack")->second = true;
202  }
203 
204  }
205  }
206  }
207 
209 
210  const int numberOfFiredTriggers = std::accumulate(begin(triggerDecisionsMVA), end(triggerDecisionsMVA), 0,
211  [](const int previous, const std::pair<const std::string, bool>& element)
212  { return previous + element.second; });
213 
214  if (numberOfFiredTriggers != 0) anyTriggerFired = true;
215 
216  return anyTriggerFired;
217 }
218 
219 bool HFTriggerMVA::runCutsTrigger(float mean_hits, float emcal_energy,
220  float IP, float IP_xy, float DCA)
221 {
222  bool triggerDecision = false;
223 
224  if (mean_hits >= meanMult &&
225  emcal_energy >= minEMCalEnergy &&
226  IP >= trackVertex3DDCA &&
227  IP_xy >= trackVertex2DDCA &&
228  DCA <= trackTrackDCA) triggerDecision = true;
229 
230  return triggerDecision;
231 }
232 
233 bool HFTriggerMVA::runMVATrigger(TMVA::Reader* reader, std::string method, std::vector<float> inputValues, float cut)
234 {
235  float mvaResponse = (Float_t) reader->EvaluateMVA(inputValues, method.c_str());
236  return mvaResponse >= cut;
237 }
238 
239 void HFTriggerMVA::calculateMultiplicity(PHCompositeNode *topNode, float& meanMultiplicity, float& asymmetryMultiplicity)
240 {
241  TrkrHitSetContainer* hitContainer = findNode::getClass<TrkrHitSetContainer>(topNode, "TRKR_HITSET");
242 
243  TrkrHitSetContainer::ConstRange inttHitSetRange[2];
244  for (int i = 0; i < 2; i++) inttHitSetRange[i] = hitContainer->getHitSets(TrkrDefs::TrkrId::inttId, i + 4);
245 
246  int inttHits[2] = {0};
247 
248  for (int i = 0; i < 2; i++)
249  {
250  for (TrkrHitSetContainer::ConstIterator hitsetitr = inttHitSetRange[i].first;
251  hitsetitr != inttHitSetRange[i].second;
252  ++hitsetitr)
253  {
254  TrkrHitSet *hitset = hitsetitr->second;
255  inttHits[i] += hitset->size();
256  }
257  }
258 
259  meanMultiplicity = (inttHits[0] + inttHits[1])/2;
260  asymmetryMultiplicity = (inttHits[0] - inttHits[1])/(inttHits[0] + inttHits[1]);
261 }
262 
264 {
265  float maxEnergy = 0;
266  PHNodeIterator nodeIter(topNode);
267  m_dst_trackmap = findNode::getClass<SvtxTrackMap>(topNode, "SvtxTrackMap");
268 
269  for (SvtxTrackMap::Iter iter = m_dst_trackmap->begin(); iter != m_dst_trackmap->end(); ++iter)
270  {
271  m_dst_track = iter->second;
272  float thisEnergy = m_dst_track->get_cal_cluster_e(SvtxTrack::CAL_LAYER(1));
273  maxEnergy = std::max(maxEnergy, thisEnergy);
274  }
275 
276  return maxEnergy;
277 
278 }
279 
281  float& minIP, float& minIP_xy,
282  float& maxIP, float& maxIP_xy, float& DCA)
283 {
284  float track1_IP = calcualteTrackVertexDCA(track1, vertex);
285  float track1_IP_xy = calcualteTrackVertex2DDCA(track1, vertex);
286  float track2_IP = calcualteTrackVertexDCA(track2, vertex);
287  float track2_IP_xy = calcualteTrackVertex2DDCA(track2, vertex);
288 
289  minIP = std::min(track1_IP, track2_IP);
290  minIP_xy = std::min(track1_IP_xy, track2_IP_xy);
291  maxIP = std::max(track1_IP, track2_IP);
292  maxIP_xy = std::max(track1_IP_xy, track2_IP_xy);
293  DCA = calcualteTrackTrackDCA(track1, track2);
294 }
295 
297 {
298  Vertex vertex;
299 
300  vertex(0,0) = m_dst_vertex->get_x();
301  vertex(1,0) = m_dst_vertex->get_y();
302  vertex(2,0) = m_dst_vertex->get_z();
303 
304  return vertex;
305 }
306 
308 {
309  std::vector<Vertex> primaryVertices;
310  m_dst_vertexmap = findNode::getClass<SvtxVertexMap>(topNode, "SvtxVertexMap");
311 
312  for (SvtxVertexMap::ConstIter iter = m_dst_vertexmap->begin(); iter != m_dst_vertexmap->end(); ++iter)
313  {
314  m_dst_vertex = iter->second;
315  primaryVertices.push_back(makeVertex(topNode));
316  }
317 
318  return primaryVertices;
319 }
320 
322 {
323  Track track;
324 
325  track(0,0) = m_dst_track->get_x();
326  track(1,0) = m_dst_track->get_y();
327  track(2,0) = m_dst_track->get_z();
328  track(3,0) = m_dst_track->get_px();
329  track(4,0) = m_dst_track->get_py();
330  track(5,0) = m_dst_track->get_pz();
331 
332  return track;
333 }
334 
335 std::vector<Track> HFTriggerMVA::makeAllTracks(PHCompositeNode *topNode)
336 {
337  std::vector<Track> tracks;
338  m_dst_trackmap = findNode::getClass<SvtxTrackMap>(topNode, "SvtxTrackMap");
339 
340  for (SvtxTrackMap::Iter iter = m_dst_trackmap->begin(); iter != m_dst_trackmap->end(); ++iter)
341  {
342  m_dst_track = iter->second;
343  tracks.push_back(makeTrack(topNode));
344  }
345 
346  return tracks;
347 }
348 
349 int HFTriggerMVA::decomposeTrack(Track track, TrackX& trackPosition, TrackP& trackMomentum)
350 {
351  for (unsigned int i = 0; i < 3; i++)
352  {
353  trackPosition(i,0) = track(i,0);
354  trackMomentum(i,0) = track(i+3,0);
355  }
356 
357  return 0;
358 }
359 
360 
362 {
363  TrackX pos;
364  TrackP mom;
365  DCA dcaVertex;
366 
367  decomposeTrack(track, pos, mom);
368 
369  dcaVertex = pos - vertex - mom.dot(pos - vertex)*mom/(mom.dot(mom));
370 
371  float twoD_DCA = std::sqrt(std::pow(dcaVertex[0], 2) + std::pow(dcaVertex[1], 2));
372 
373  return twoD_DCA;
374 }
375 
377 {
378  TrackX pos;
379  TrackP mom;
380  DCA dcaVertex;
381 
382  decomposeTrack(track, pos, mom);
383 
384  dcaVertex = pos - vertex - mom.dot(pos - vertex)*mom/(mom.dot(mom));
385 
386  return std::abs(dcaVertex.norm());
387 }
388 
390 {
391  TrackX posOne;
392  TrackP momOne;
393  TrackX posTwo;
394  TrackP momTwo;
395  float dcaTrackSize;
396 
397  decomposeTrack(trackOne, posOne, momOne);
398  decomposeTrack(trackTwo, posTwo, momTwo);
399 
400  Eigen::Vector3f momOneCrossmomTwo = momOne.cross(momTwo);
401  Eigen::Vector3f posOneMinusposTwo = posOne - posTwo;
402  dcaTrackSize = std::abs(momOneCrossmomTwo.dot(posOneMinusposTwo)/(momOneCrossmomTwo.norm()));
403 
404  return dcaTrackSize;
405 }
406 
407 std::tuple<TMVA::Reader*, std::vector<Float_t>> HFTriggerMVA::initMVA(std::vector<std::string> variableList, std::string method, std::string mvaFile)
408 {
409  TMVA::Tools::Instance(); //Start TMVA
410  TMVA::Reader *reader = new TMVA::Reader("!Color:!Silent");
411 
412  std::vector<Float_t> reader_floats;
413 
414  for (unsigned int i = 0; i < variableList.size(); ++i)
415  {
416  reader_floats.push_back(0);
417  reader->AddVariable(variableList[i].c_str(), &reader_floats[i]);
418  }
419  reader->BookMVA(method.c_str(), mvaFile.c_str());
420 
421  return make_tuple(reader, reader_floats);
422 }
423 
425 {
426  std::cout << "\n---------------HFTriggerMVA run information---------------" << std::endl;
427  std::cout << "The number of events processed is: " << m_events << std::endl;
428  std::cout << "The number of events that did not trigger is: " << m_no_trigger << std::endl;
429  std::cout << "The number of events that fired the cuts-based trigger is: " << m_cuts_and_no_mva_wcalo_counter + m_cuts_and_mva_wcalo_counter << std::endl;
430  std::cout << "The number of events that fired the cuts-based trigger, with no calorimetry is: " << m_cuts_and_no_mva_woutcalo_counter + m_cuts_and_mva_woutcalo_counter << std::endl;
431  std::cout << "The number of events that fired the MVA trigger is: " << m_no_cuts_and_mva_wcalo_counter + m_cuts_and_mva_wcalo_counter << std::endl;
432  std::cout << "The number of events that fired the MVA trigger, with no calorimetry is: " << m_no_cuts_and_mva_woutcalo_counter + m_cuts_and_mva_woutcalo_counter << std::endl;
433  std::cout << "The number of events that fired the MVA trigger, with no calorimetry or min track is: " << m_no_cuts_and_mva_woutcalo_and_mintracks_counter + m_cuts_and_mva_woutcalo_and_mintracks_counter << std::endl;
434  std::cout << "The number of events triggered is: " << m_counter << std::endl;
435  std::cout << "--Comparing cuts-based and MVA, both with Calorimetry:" << std::endl;
436  std::cout << "----The number of events that fired the cuts-based trigger but not the MVA trigger is: " << m_cuts_and_no_mva_wcalo_counter << std::endl;
437  std::cout << "----The number of events that fired the MVA trigger but not the cuts-based trigger is: " << m_no_cuts_and_mva_wcalo_counter << std::endl;
438  std::cout << "----The number of events that fired both the cuts-based trigger and the MVA triggers is: " << m_cuts_and_mva_wcalo_counter << std::endl;
439  std::cout << "----The number of events that fired neither the cuts-based trigger or the MVA triggers is: " << m_no_cuts_and_no_mva_wcalo_counter << std::endl;
440  std::cout << "--Comparing cuts-based and MVA, both without Calorimetry:" << std::endl;
441  std::cout << "----The number of events that fired the cuts-based trigger but not the MVA trigger is: " << m_cuts_and_no_mva_woutcalo_counter << std::endl;
442  std::cout << "----The number of events that fired the MVA trigger but not the cuts-based trigger is: " << m_no_cuts_and_mva_woutcalo_counter << std::endl;
443  std::cout << "----The number of events that fired both the cuts-based trigger and the MVA triggers is: " << m_cuts_and_mva_woutcalo_counter << std::endl;
444  std::cout << "----The number of events that fired neither the cuts-based trigger or the MVA triggers is: " << m_no_cuts_and_no_mva_woutcalo_counter << std::endl;
445  std::cout << "--Comparing cuts-based and MVA without Calorimetry or IP of second track:" << std::endl;
446  std::cout << "----The number of events that fired the cuts-based trigger but not the MVA trigger is: " << m_cuts_and_no_mva_woutcalo_and_mintracks_counter << std::endl;
447  std::cout << "----The number of events that fired the MVA trigger but not the cuts-based trigger is: " << m_no_cuts_and_mva_woutcalo_and_mintracks_counter << std::endl;
448  std::cout << "----The number of events that fired both the cuts-based trigger and the MVA triggers is: " << m_cuts_and_mva_woutcalo_and_mintracks_counter << std::endl;
449  std::cout << "----The number of events that fired neither the cuts-based trigger or the MVA triggers is: " << m_no_cuts_and_no_mva_woutcalo_and_mintracks_counter << std::endl;
450  std::cout << "----------------------------------------------------------\n" << std::endl;
451 }
452 
454 {
455  std::cout << "\n---------------HFTriggerMVA event information---------------" << std::endl;
456  if (m_useCutsTrigger) std::cout << "The cuts based trigger decision is " << triggerDecisionsMVA.find("cuts")->second << std::endl;
457  if (m_useMVAwCaloTrigger) std::cout << "The MVA wCalo trigger decision is " << triggerDecisionsMVA.find("MVAWithCalo")->second << std::endl;
458  std::cout << "---------------------------------------------------------\n" << std::endl;
459 }
460