GENIEGenerator
Loading...
Searching...
No Matches
NuSmear.h
Go to the documentation of this file.
1//____________________________________________________________________________
2/*
3\name NuSmear smearing system
4\brief Provides preliminary simulation of energy smearing and angular
5 smearing for neutrino-nucleon interactions via parameterized
6 model-based presets in the DUNE-CDR and Default models.
7
8 To see the full NuSmear paper, visit:
9 https://inspirehep.net/literature/2150455
10
11\author Ishaan Vohra <ivohra@exeter.edu / ishaanklv@gmail.com>
12 Phillips Exeter Academy
13\created August 16, 2022
14*/
15//____________________________________________________________________________
16
17#include <iostream>
18#include <string>
19#include <map>
20#include <random>
21#include "GHepParticle.h"
22#include "PDGCodes.h"
23#include "TVector3.h"
24#include "PDGUtils.h"
25
26#ifndef _NUSMEAR_H
27#define _NUSMEAR_H
28
29using namespace genie;
30
31// DUNE-CDR resolution functions
32
33double PiP_Res_duneCdr(double myE, double myKE, double myPmag)
34{
35 if (myKE >= 0.1)
36 {
37 return 0.15;
38 }
39 else
40 {
41 return -1;
42 }
43}
44
45double PiM_Res_duneCdr(double myE, double myKE, double myPmag)
46{
47 if (myKE >= 0.1)
48 {
49 return 0.15;
50 }
51 else
52 {
53 return -1;
54 }
55}
56
57double Pi0_Res_duneCdr(double myE, double myKE, double myPmag)
58{
59 if (myKE >= 0.05)
60 {
61 return pow((pow(0.05, 2) + pow((0.3 / (pow(myE, 0.5))), 2)), 0.5);
62 }
63 else
64 {
65 return -1;
66 }
67}
68
69double KP_Res_duneCdr(double myE, double myKE, double myPmag)
70{
71 if (myKE >= 0.05)
72 {
73 return pow((pow(0.05, 2) + pow((0.3 / (pow(myE, 0.5))), 2)), 0.5);
74 }
75 else
76 {
77 return -1;
78 }
79}
80
81double KM_Res_duneCdr(double myE, double myKE, double myPmag)
82{
83 if (myKE >= 0.05)
84 {
85 return pow(pow(0.05, 2) + pow((0.3 / (pow(myE, 0.5))), 2), 0.5);
86 }
87 else
88 {
89 return -1;
90 }
91}
92
93double Gamma_Res_duneCdr(double myE, double myKE, double myPmag)
94{
95 if (myKE >= 0.03)
96 {
97 return pow(pow(0.02, 2) + pow(0.15 / (pow(myE, 0.5)), 2), 0.5);
98 }
99 else
100 {
101 return -1;
102 }
103}
104
105double Proton_Res_duneCdr(double myE, double myKE, double myPmag)
106{
107 if (myKE >= 0.05)
108 {
109 if (myPmag < 0.4)
110 {
111 return 0.1;
112 }
113 else
114 {
115 return pow(pow(0.05, 2) + pow(0.3 / (pow(myKE, 0.5)), 2), 0.5);
116 }
117 }
118 else
119 {
120 return -1;
121 }
122}
123
124double Electron_Res_duneCdr(double myE, double myKE, double myPmag)
125{
126 if (myKE >= 0.03)
127 {
128 return pow(pow(0.02, 2) + pow(0.15 / (pow(myE, 0.5)), 2), 0.5);
129 }
130 else
131 {
132 return -1;
133 }
134}
135
136double Positron_Res_duneCdr(double myE, double myKE, double myPmag)
137{
138 if (myKE >= 0.03)
139 {
140 return pow(pow(0.02, 2) + pow(0.15 / (pow(myE, 0.5)), 2), 0.5);
141 }
142 else
143 {
144 return -1;
145 }
146}
147
148double Muon_Res_duneCdr(double myE, double myKE, double myPmag)
149{
150 if (myKE >= 0.03)
151 {
152 return 0.15;
153 }
154 else
155 {
156 return -1;
157 }
158}
159
160double AntiMuon_Res_duneCdr(double myE, double myKE, double myPmag)
161{
162 if (myKE >= 0.03)
163 {
164 return 0.15;
165 }
166 else
167 {
168 return -1;
169 }
170}
171
172double Neutron_Res_duneCdr(double myE, double myKE, double myPmag)
173{
174 if (myKE >= 0.05)
175 {
176 return 0.4 / (pow(myKE, 0.5));
177 }
178 else
179 {
180 return -1;
181 }
182}
183
184double K0_Res_duneCdr(double myE, double myKE, double myPmag)
185{
186 if (myKE >= 0.05)
187 {
188 return pow((pow(0.05, 2) + pow((0.3 / (pow(myE, 0.5))), 2)), 0.5);
189 }
190 else
191 {
192 return -1;
193 }
194}
195
196double AntiK0_Res_duneCdr(double myE, double myKE, double myPmag)
197{
198 if (myKE >= 0.05)
199 {
200 return pow((pow(0.05, 2) + pow((0.3 / (pow(myE, 0.5))), 2)), 0.5);
201 }
202 else
203 {
204 return -1;
205 }
206}
207
208double Lambda_Res_duneCdr(double myE, double myKE, double myPmag)
209{
210 if (myKE >= 0.05)
211 {
212 return pow((pow(0.05, 2) + pow((0.3 / (pow(myE, 0.5))), 2)), 0.5);
213 }
214 else
215 {
216 return -1;
217 }
218}
219
220double SigmaP_Res_duneCdr(double myE, double myKE, double myPmag)
221{
222 if (myKE >= 0.05)
223 {
224 return pow((pow(0.05, 2) + pow((0.3 / (pow(myE, 0.5))), 2)), 0.5);
225 }
226 else
227 {
228 return -1;
229 }
230}
231
232double Sigma0_Res_duneCdr(double myE, double myKE, double myPmag)
233{
234 if (myKE >= 0.05)
235 {
236 return pow((pow(0.05, 2) + pow((0.3 / (pow(myE, 0.5))), 2)), 0.5);
237 }
238 else
239 {
240 return -1;
241 }
242}
243
244double SigmaM_Res_duneCdr(double myE, double myKE, double myPmag)
245{
246 if (myKE >= 0.05)
247 {
248 return pow((pow(0.05, 2) + pow((0.3 / (pow(myE, 0.5))), 2)), 0.5);
249 }
250 else
251 {
252 return -1;
253 }
254}
255
256// Mersenne twister pseudo-random number generation
257
258std::random_device rd;
259std::mt19937 gen(rd());
260
261// Energy smearing function
262
263double smearE(int myPdg, double myE, double myKE, double myPx, double myPy, double myPz, std::string model)
264{
265 std::map<int, int> myMap;
266
267 myMap[kPdgPiP] = 0;
268 myMap[kPdgPiM] = 1;
269 myMap[kPdgPi0] = 2;
270 myMap[kPdgKP] = 3;
271 myMap[kPdgKM] = 4;
272 myMap[kPdgGamma] = 5;
273 myMap[kPdgProton] = 6;
274 myMap[kPdgElectron] = 7;
275 myMap[kPdgPositron] = 8;
276 myMap[kPdgMuon] = 9;
277 myMap[kPdgAntiMuon] = 10;
278 myMap[kPdgNeutron] = 11;
279 myMap[kPdgK0] = 12;
280 myMap[kPdgAntiK0] = 13;
281 myMap[kPdgLambda] = 14;
282 myMap[kPdgSigmaP] = 15;
283 myMap[kPdgSigma0] = 16;
284 myMap[kPdgSigmaM] = 17;
285
286 TVector3 P(myPx, myPy, myPz);
287 TVector3 Z(0, 0, 1);
288 double myPmag = P.Mag();
289
290 int in = myMap.find(myPdg)->second;
291
292 if (model == "duneCdr")
293 {
294
295 double (*resolution_ptr_duneCdr[18])(double, double, double) = {
314
315 double resolution = (*resolution_ptr_duneCdr[in])(myE, myKE, myPmag);
316
317 if (resolution == -1)
318 {
319 return 0;
320 }
321 else
322 {
323 double var = 0;
324 double eSq = 0;
325
326 if (pdg::IsNeutronOrProton(myPdg))
327 {
328 var += pow((resolution * myKE), 2);
329 eSq += pow(myKE, 2);
330 }
331 else
332 {
333 var += pow((resolution * myE), 2);
334 eSq += pow(myE, 2);
335 }
336
337 double m = log(eSq / (pow(var + eSq, 0.5)));
338 double s = pow(log(1 + (var / eSq)), 0.5);
339
340 std::lognormal_distribution<double> distLognorm(m, s);
341
342 if (myPdg == kPdgNeutron)
343 {
344 if (myPmag < 1)
345 {
346 std::uniform_real_distribution<double> distUni(0, 1);
347
348 if (distUni(gen) < 0.1)
349 {
350 return 0;
351 }
352 else
353 {
354 return 0.6 * (distLognorm(gen));
355 }
356 }
357 else
358 {
359 return 0.6 * (distLognorm(gen));
360 }
361 }
362 else
363 {
364 return distLognorm(gen);
365 }
366 }
367 }
368
369 // Default model resolutions and particle detection dependencies
370
371 else if (model == "default")
372 {
373 double info[18][2] = {
374
375 {0.15, 1},
376 {0.15, 1},
377 {0.15, 1},
378 {0.2, 1},
379 {0.2, 1},
380 {0.3, 0.5},
381 {0.4, 1},
382 {0.4, 1},
383 {0.4, 1},
384 {0.15, 1},
385 {0.15, 1},
386 {0.5, 0.5},
387 {0.2, 1},
388 {0.2, 1},
389 {0.3, 1},
390 {0.3, 1},
391 {0.3, 1},
392 {0.3, 1}};
393
394 double resolution = info[in][0];
395 double chanceToSee = info[in][1];
396 double var = 0;
397 double eSq = 0;
398
399 if (pdg::IsNeutronOrProton(myPdg))
400 {
401 var += pow((resolution * myKE), 2);
402 eSq += pow(myKE, 2);
403 }
404 else
405 {
406 var += pow((resolution * myE), 2);
407 eSq += pow(myE, 2);
408 }
409
410 double m = log(eSq / (pow(var + eSq, 0.5)));
411 double s = pow(log(1 + (var / eSq)), 0.5);
412
413 std::lognormal_distribution<double> distLognorm(m, s);
414 std::uniform_real_distribution<double> distUni(0, 1);
415
416 if (distUni(gen) < chanceToSee)
417 {
418 if (myKE > 0.05)
419 {
420 return distLognorm(gen);
421 }
422 else
423 {
424 return 0;
425 }
426 }
427 else
428 {
429 return 0;
430 }
431 }
432 else
433 {
434 std::cout << "Error: Resolution model not found./n";
435 }
436}
437
438// Angular smearing function
439
440double smearA(int myPdg, double myPx, double myPy, double myPz, std::string model)
441{
442 std::map<int, int> myMap;
443
444 myMap[kPdgPiP] = 0;
445 myMap[kPdgPiM] = 1;
446 myMap[kPdgPi0] = 2;
447 myMap[kPdgKP] = 3;
448 myMap[kPdgKM] = 4;
449 myMap[kPdgGamma] = 5;
450 myMap[kPdgProton] = 6;
451 myMap[kPdgElectron] = 7;
452 myMap[kPdgPositron] = 8;
453 myMap[kPdgMuon] = 9;
454 myMap[kPdgAntiMuon] = 10;
455 myMap[kPdgNeutron] = 11;
456 myMap[kPdgK0] = 12;
457 myMap[kPdgAntiK0] = 13;
458 myMap[kPdgLambda] = 14;
459 myMap[kPdgSigmaP] = 15;
460 myMap[kPdgSigma0] = 16;
461 myMap[kPdgSigmaM] = 17;
462
463 TVector3 P(myPx, myPy, myPz);
464 TVector3 Z(0, 0, 1);
465 double theta = (P.Angle(Z)) / M_PI * 180;
466
467 int in = myMap.find(myPdg)->second;
468
469 // DUNE-CDR and Default angular smearing values
470
471 double angularResDeg_DuneCdr[18] = {
472 1,
473 1,
474 5,
475 5,
476 5,
477 1,
478 5,
479 1,
480 1,
481 1,
482 1,
483 5,
484 5,
485 5,
486 5,
487 5,
488 5,
489 5};
490
491 double angularResDeg_Default[18] = {
492 2,
493 2,
494 8,
495 2,
496 2,
497 3,
498 8,
499 2,
500 2,
501 2,
502 2,
503 10,
504 8,
505 8,
506 8,
507 8,
508 8,
509 8};
510
511 double resolution = 0;
512
513 if (model == "duneCdr")
514 {
515 resolution += (angularResDeg_DuneCdr[in]);
516 }
517 else if (model == "default")
518 {
519 resolution += (angularResDeg_Default[in]);
520 }
521
522 std::normal_distribution<double> distNorm(theta, resolution);
523 return distNorm(gen);
524}
525
526#endif
double Gamma_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:93
double Electron_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:124
double Lambda_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:208
double AntiK0_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:196
std::mt19937 gen(rd())
double smearE(int myPdg, double myE, double myKE, double myPx, double myPy, double myPz, std::string model)
Definition NuSmear.h:263
double Positron_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:136
double PiM_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:45
double K0_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:184
double Neutron_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:172
std::random_device rd
Definition NuSmear.h:258
double AntiMuon_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:160
double SigmaP_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:220
double Pi0_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:57
double SigmaM_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:244
double Proton_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:105
double smearA(int myPdg, double myPx, double myPy, double myPz, std::string model)
Definition NuSmear.h:440
double PiP_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:33
double KP_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:69
double Muon_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:148
double Sigma0_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:232
double KM_Res_duneCdr(double myE, double myKE, double myPmag)
Definition NuSmear.h:81
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils.
bool IsNeutronOrProton(int pdgc)
Definition PDGUtils.cxx:351
THE MAIN GENIE PROJECT NAMESPACE
Definition AlgCmp.h:25
const int kPdgPiM
Definition PDGCodes.h:159
const int kPdgSigma0
Definition PDGCodes.h:88
const int kPdgAntiMuon
Definition PDGCodes.h:38
const int kPdgProton
Definition PDGCodes.h:81
const int kPdgSigmaP
Definition PDGCodes.h:87
const int kPdgPi0
Definition PDGCodes.h:160
const int kPdgKP
Definition PDGCodes.h:172
const int kPdgNeutron
Definition PDGCodes.h:83
const int kPdgKM
Definition PDGCodes.h:173
const int kPdgPiP
Definition PDGCodes.h:158
const int kPdgLambda
Definition PDGCodes.h:85
const int kPdgSigmaM
Definition PDGCodes.h:89
const int kPdgMuon
Definition PDGCodes.h:37
const int kPdgPositron
Definition PDGCodes.h:36
const int kPdgGamma
Definition PDGCodes.h:189
const int kPdgAntiK0
Definition PDGCodes.h:175
const int kPdgElectron
Definition PDGCodes.h:35
const int kPdgK0
Definition PDGCodes.h:174