EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AnalysisFunctions.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file AnalysisFunctions.cc
1 #ifndef ANALYSISFUNCTIONS
2 #define ANALYSISFUNCTIONS
3 
4 #include "TROOT.h"
5 #include "TLorentzVector.h"
6 #include "TVector3.h"
7 #include "TClonesArray.h"
8 #include "TMath.h"
9 
10 #include <vector>
11 #include <string>
12 #include <map>
13 #include <iostream>
14 #include <math.h>
15 
16 #include "classes/DelphesClasses.h"
17 
18 // Template functions for applying cuts and selecting subsets of particle lists
19 
20 template<class T>std::vector<T *> SelectorFcn(std::vector<T *>particles,
21  bool selector(T *))
22 {
23  std::vector<T *> output_list;
24 
25  for (T *particle : particles) {
26  if (selector(particle)) {
27  output_list.push_back(particle);
28  }
29  }
30 
31  return output_list;
32 }
33 
34 // Computations of fundamental quantities, like Bjorken x, etc.
35 
36 
37 inline std::map<std::string, float>DISVariables(TClonesArray *branchParticle)
38 {
39  // four-momenta of proton, electron, virtual photon/Z^0/W^+-.
40  auto pProton = static_cast<GenParticle *>(branchParticle->At(0))->P4(); // these
41  // numbers
42  // 0
43  // ,
44  // 3,
45  // 5
46  // are
47  // hardcoded
48  // in
49  // Pythia8
50  auto pleptonIn = static_cast<GenParticle *>(branchParticle->At(3))->P4();
51  auto pleptonOut = static_cast<GenParticle *>(branchParticle->At(5))->P4();
52  auto pPhoton = pleptonIn - pleptonOut;
53 
54  // Q2, W2, Bjorken x, y, nu.
55  float Q2 = -pPhoton.M2();
56  float W2 = (pProton + pPhoton).M2();
57  float x = Q2 / (2. * pProton.Dot(pPhoton));
58  float y = (pProton.Dot(pPhoton)) / (pProton.Dot(pleptonIn));
59 
60 
61  std::map<std::string, float> dis_variables;
62  dis_variables["Q2"] = Q2;
63  dis_variables["W2"] = W2;
64  dis_variables["x"] = x;
65  dis_variables["y"] = y;
66 
67  return dis_variables;
68 }
69 
70 inline std::map<std::string, float>DISJacquetBlondel(TClonesArray *tracks,
71  TClonesArray *electrons,
72  TClonesArray *photons,
73  TClonesArray *neutral_hadrons)
74 {
75  // Jacquet-Blondel method:
76  float delta_track = 0.0;
77  auto temp_p = TVector3();
78 
79  for (int i = 0; i < tracks->GetEntries(); i++) {
80  auto track_mom = static_cast<Track *>(tracks->At(i))->P4();
81 
82  if (isnan(track_mom.E()))
83  continue;
84  delta_track += (track_mom.E() - track_mom.Pz());
85  temp_p = temp_p + track_mom.Vect();
86  }
87 
88  float delta_track_noel = 0.0;
89 
90  if (electrons->GetEntries() > 0) {
91  auto e = static_cast<Track *>(electrons->At(0))->P4();
92 
93  if (!isnan(e.E())) {
94  delta_track_noel = delta_track - (e.E() - e.Pz());
95  }
96  }
97 
98  float delta_photon = 0.0;
99 
100  for (int i = 0; i < photons->GetEntries(); i++) {
101  auto pf_mom = static_cast<Photon *>(photons->At(i))->P4();
102 
103  if (isnan(pf_mom.E()))
104  continue;
105  delta_photon += (pf_mom.E() - pf_mom.Pz());
106  temp_p = temp_p + pf_mom.Vect();
107  }
108 
109  float delta_neutral = 0;
110  float delta_neutral_noBarrel = 0;
111  auto ptmiss_noBarrel = TVector3();
112 
113  for (int i = 0; i < neutral_hadrons->GetEntries(); i++) {
114  auto pf_mom = static_cast<Tower *>(neutral_hadrons->At(i))->P4();
115 
116  if (isnan(pf_mom.E()))
117  continue;
118  delta_neutral += (pf_mom.E() - pf_mom.Pz());
119  temp_p = temp_p + pf_mom.Vect();
120 
121  if (TMath::Abs(pf_mom.Eta()) > 1.0) {
122  delta_neutral_noBarrel += (pf_mom.E() - pf_mom.Pz());
123  ptmiss_noBarrel = ptmiss_noBarrel + pf_mom.Vect();
124  }
125  }
126 
127  float delta = delta_track + delta_photon + delta_neutral;
128 
129  // delta_noel = delta_track_noel + delta_photon + delta_neutral
130  // delta_noel_noBarrel = delta_track_noel + delta_photon +
131  // delta_neutral_noBarrel
132  float delta_noBarrel = delta_track + delta_photon + delta_neutral_noBarrel;
133 
134  float y_JB = delta / (2.0 * 10.0);
135  auto ptmiss = temp_p.Perp();
136  float Q2_JB = (ptmiss * ptmiss) / (1.0 - y_JB);
137  float s = 4.0 * 10.0 * 275.0;
138  float x_JB = Q2_JB / (s * y_JB);
139 
140  std::map<std::string, float> dis_variables;
141  dis_variables["x_JB"] = x_JB;
142  dis_variables["Q2_JB"] = Q2_JB;
143  dis_variables["y_JB"] = y_JB;
144 
145  return dis_variables;
146 }
147 
148 //
149 // Tagging Methods
150 //
151 
152 inline bool IsTaggingTrack(Track *track)
153 {
154  bool good_track = true;
155 
156 
157  // Avoid decays that are too far from the beamspot (e.g. Ks, etc.)
158  float d0 = TMath::Abs(track->D0);
159  float z0 = TMath::Abs(track->DZ);
160 
161  // In the original approach, we merely restricted d0 to be < 3mm
162  // However, with Ks and Lambda, etc. long-lived light decays turned on,
163  // more displaced tracks started contaminating this in light jets.
164  // (e.g. with small d0 but large z0)
165  // Use a 3D impact parameter maximum to constrain these tracks.
166 
167  float r0 = TMath::Sqrt(d0 * d0 + z0 * z0);
168 
169  if (r0 > 3.0) // mm
170  good_track &= false;
171 
172  return good_track;
173 }
174 
175 inline float sIP3D(Jet *jet, Track *track)
176 {
177  const TLorentzVector& jetMomentum = jet->P4();
178  float jpx = jetMomentum.Px();
179  float jpy = jetMomentum.Py();
180  float jpz = jetMomentum.Pz();
181 
182  float d0 = TMath::Abs(track->D0);
183 
184  float xd = track->Xd;
185  float yd = track->Yd;
186  float zd = track->Zd;
187  float dd0 = TMath::Abs(track->ErrorD0);
188  float dz = TMath::Abs(track->DZ);
189  float ddz = TMath::Abs(track->ErrorDZ);
190 
191  int sign = (jpx * xd + jpy * yd + jpz * zd > 0.0) ? 1 : -1;
192 
193  // add transverse and longitudinal significances in quadrature
194  float sip = sign * TMath::Sqrt(TMath::Power(d0 / dd0, 2) + TMath::Power(dz / ddz, 2));
195 
196  // if (d0 > 3) { // 3mm maximum in d0
197  if (!IsTaggingTrack(track) || TMath::IsNaN(sip) || !TMath::Finite(sip)) {
198  // Tracks far outside the beamspot region should be ignored (Ks, Lambda,
199  // etc.); tracks with bad d0, z0 error values, etc. should be ignored.
200  sip = -199.0;
201  }
202 
203  return sip;
204 }
205 
206 inline bool Tagged_Kaon(Jet *jet, std::vector<Track *>kaons, float minSignif, float minPT, int minKaons)
207 {
208  bool tagged = false;
209  int kaon_count = 0;
210 
211  for (auto kaon : kaons) {
212  if (kaon->P4().DeltaR(jet->P4()) > 0.5)
213  continue;
214 
215  if (kaon->PT < minPT)
216  continue;
217 
218  if (!IsTaggingTrack(kaon))
219  continue;
220 
221 
222  if (sIP3D(jet, kaon) < minSignif)
223  continue;
224 
225  kaon_count++;
226 
227  if (kaon_count >= minKaons)
228  break;
229  }
230 
231  tagged = (kaon_count >= minKaons);
232 
233  return tagged;
234 }
235 
236 inline bool Tagged_Electron(Jet *jet, std::vector<Track *>electrons, float minSignif, float minPT, int minElectrons)
237 {
238  bool tagged = false;
239  int electron_count = 0;
240 
241  for (auto electron : electrons) {
242  if (electron->P4().DeltaR(jet->P4()) > 0.5)
243  continue;
244 
245  if (electron->PT < minPT)
246  continue;
247 
248  if (!IsTaggingTrack(electron))
249  continue;
250 
251  if (sIP3D(jet, electron) < minSignif)
252  continue;
253 
254  electron_count++;
255 
256  if (electron_count >= minElectrons)
257  break;
258  }
259 
260  tagged = (electron_count >= minElectrons);
261 
262  return tagged;
263 }
264 
265 inline bool Tagged_Muon(Jet *jet, std::vector<Track *>muons, float minSignif, float minPT, int minMuons)
266 {
267  bool tagged = false;
268  int muon_count = 0;
269 
270  for (auto muon : muons) {
271  if (muon->P4().DeltaR(jet->P4()) > 0.5)
272  continue;
273 
274  if (muon->PT < minPT)
275  continue;
276 
277  if (!IsTaggingTrack(muon))
278  continue;
279 
280  if (sIP3D(jet, muon) < minSignif)
281  continue;
282 
283 
284  muon_count++;
285 
286  if (muon_count >= minMuons)
287  break;
288  }
289 
290  tagged = (muon_count >= minMuons);
291 
292  return tagged;
293 }
294 
295 inline bool Tagged_sIP3D(Jet *jet, TClonesArray tracks,
296  float minSignif, float minPT, int minTracks)
297 {
298  bool tagged = false;
299 
300  const TLorentzVector& jetMomentum = jet->P4();
301  float jpx = jetMomentum.Px();
302  float jpy = jetMomentum.Py();
303  float jpz = jetMomentum.Pz();
304 
305  auto jet_constituents = tracks;
306 
307  int N_sIPtrack = 0;
308 
309  // std::cout << "------------ Processing Jet " << jet << " ------------" <<
310  // std::endl;
311 
312  for (int iconst = 0; iconst < jet_constituents.GetEntries(); iconst++) {
313  if (N_sIPtrack >= minTracks)
314  break;
315 
316  auto constituent = jet_constituents.At(iconst);
317 
318  if (constituent == 0) continue;
319 
320  if (constituent->IsA() == Track::Class()) {
321  auto track = static_cast<Track *>(constituent);
322 
323  const TLorentzVector& trkMomentum = track->P4();
324  float tpt = trkMomentum.Pt();
325 
326  if (tpt < minPT) continue;
327 
328  if (trkMomentum.DeltaR(jetMomentum) > 0.5)
329  continue;
330 
331  // Avoid decays that are too far from the beamspot (e.g. Ks, etc.)
332  // float d0 = TMath::Abs(track->D0);
333  // float z0 = TMath::Abs(track->DZ);
334  if (!IsTaggingTrack(track))
335  continue;
336 
337  float sip = sIP3D(jet, track);
338 
339 
340  if (sip > minSignif) N_sIPtrack++;
341  }
342  }
343 
344  tagged = (N_sIPtrack >= minTracks);
345 
346  // std::cout << "------------ xxxxxxxxxxxxxx ------------" << std::endl;
347 
348  return tagged;
349 }
350 
351 #endif // ifndef ANALYSISFUNCTIONS