DetectorResponse.cc
Go to the documentation of this file.
1 #include "DetectorResponse.h"
2 #include "DetectorResponseConfig.h"
3 
4 #include <sstream>
5 
6 #include <cstdio>
7 #include <cmath>
8 #include <cstdlib>
9 #include <algorithm>
10 #include <stdexcept>
11 
12 
13 using namespace std;
14 using namespace TabulatedTankSimulatorNS;
15 
16 namespace TabulatedTankSimulatorNS {
17 
18  static const char* electronName = "electron";
19  static const char* gammaName = "gamma";
20  static const char* muonName = "muon";
21  static const char* muonNameLow = "muon-low"; // The area over which particles are injected is larger
22  static const char* michelName = "michel-electron";
23  static const char* michelNameLow = "michel-electron-low"; // The area over which particles are injected is larger
24 
25  //----- Zenith grid [0] WCD [1] ASCII [2] AMIGA
26  const unsigned int nTo_Grid[3] = { 19 , 19 , 22 };
27  const double Theta_Grid[3][50] = {
28  { 0, 12, 25, 36, 45, 53, 60, 63, 67, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88},
29  { 0, 12, 25, 36, 45, 53, 60, 63, 67, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88},
30  { 0, 8, 12, 20, 25, 27, 30, 36, 38, 40, 42, 45, 47, 50, 53, 57, 60, 62, 64, 66, 68, 70 }
31  };
32 
33  //------Energy grid [0] WCD [1] ASCII [2] AMIGA
34 
35  const unsigned int nKE_Electron[3] = { 35 , 35 , 35 };
36  const double lKE_Electron[3][50] = {
37  {
38  -4.000, -3.800, -3.400, -3.200, -3.000, -2.900, -2.800, -2.700, -2.600, -2.500,
39  -2.400, -2.300, -2.200, -2.100, -2.000, -1.800, -1.600, -1.400, -1.200, -1.000,
40  -0.800, -0.600, -0.400, -0.200, 0.000, 0.200, 0.400, 0.600, 0.800, 1.000,
41  1.200, 1.400, 1.600, 1.800, 2.000
42  },
43 
44  {
45  -4.000, -3.800, -3.400, -3.200, -3.000, -2.900, -2.800, -2.700, -2.600, -2.500,
46  -2.400, -2.300, -2.200, -2.100, -2.000, -1.800, -1.600, -1.400, -1.200, -1.000,
47  -0.800, -0.600, -0.400, -0.200, 0.000, 0.200, 0.400, 0.600, 0.800, 1.000,
48  1.200, 1.400, 1.600, 1.800, 2.000
49  },
50 
51  {
52  -4.000, -3.800, -3.400, -3.200, -3.000, -2.900, -2.800, -2.700, -2.600, -2.500,
53  -2.400, -2.300, -2.200, -2.100, -2.000, -1.800, -1.600, -1.400, -1.200, -1.000,
54  -0.800, -0.600, -0.400, -0.200, 0.000, 0.200, 0.400, 0.600, 0.800, 1.000,
55  1.200, 1.400, 1.600, 1.800, 2.000
56  }
57  };
58 
59 
60  const unsigned int nKE_Gamma[3] = { 31 , 31 , 31 };
61  const double lKE_Gamma[3][50] = {
62  {
63  -4.000, -3.800, -3.600, -3.400, -3.200, -3.000, -2.800, -2.600, -2.400, -2.200,
64  -2.000, -1.800, -1.600, -1.400, -1.200, -1.000, -0.800, -0.600, -0.400, -0.200,
65  0.000, 0.200, 0.400, 0.600, 0.800, 1.000, 1.200, 1.400, 1.600, 1.800,
66  2.000
67  },
68 
69  {
70  -4.000, -3.800, -3.600, -3.400, -3.200, -3.000, -2.800, -2.600, -2.400, -2.200,
71  -2.000, -1.800, -1.600, -1.400, -1.200, -1.000, -0.800, -0.600, -0.400, -0.200,
72  0.000, 0.200, 0.400, 0.600, 0.800, 1.000, 1.200, 1.400, 1.600, 1.800,
73  2.000
74  },
75 
76 
77  {
78  -4.000, -3.800, -3.600, -3.400, -3.200, -3.000, -2.800, -2.600, -2.400, -2.200,
79  -2.000, -1.800, -1.600, -1.400, -1.200, -1.000, -0.800, -0.600, -0.400, -0.200,
80  0.000, 0.200, 0.400, 0.600, 0.800, 1.000, 1.200, 1.400, 1.600, 1.800,
81  2.000
82  }
83  };
84 
85 
86 
87  const unsigned int nKE_Muon[3] = { 34 , 34 , 34 };
88  const double lKE_Muon[3][50] = {
89 
90  {
91  -3.000, -2.800, -2.600, -2.400, -2.200, -2.000, -1.850, -1.700, -1.550, -1.400,
92  -1.250, -1.100, -0.950, -0.800, -0.650, -0.500, -0.350, -0.200, -0.050, 0.100,
93  0.250, 0.400, 0.550, 0.700, 0.850, 1.000, 1.300, 1.600, 1.900, 2.200,
94  2.500, 2.800, 3.100, 3.400
95  },
96 
97  {
98  -3.000, -2.800, -2.600, -2.400, -2.200, -2.000, -1.850, -1.700, -1.550, -1.400,
99  -1.250, -1.100, -0.950, -0.800, -0.650, -0.500, -0.350, -0.200, -0.050, 0.100,
100  0.250, 0.400, 0.550, 0.700, 0.850, 1.000, 1.300, 1.600, 1.900, 2.200,
101  2.500, 2.800, 3.100, 3.400
102  },
103 
104  {
105  -0.600, -0.500, -0.400, -0.300, -0.200, -0.150, -0.100, -0.075, -0.050, -0.025,
106  0.000, 0.025, 0.050, 0.075, 0.100, 0.125, 0.150, 0.175, 0.200, 0.225,
107  0.250, 0.275, 0.300, 0.325, 0.350, 0.375, 0.400, 0.425, 0.500, 0.600,
108  0.800, 1.000, 1.200, 1.400
109  }
110  };
111 
112 
113  const unsigned int nKE_MuonLow[3] = { 19 , 19 , 34 };
114  const double lKE_MuonLow[3][50] = {
115 
116  {
117  -3.000, -2.800, -2.600, -2.400, -2.200, -2.000, -1.850, -1.700, -1.550, -1.400,
118  -1.250, -1.100, -0.950, -0.800, -0.650, -0.500, -0.350, -0.200, -0.050
119  },
120 
121  {
122  -3.000, -2.800, -2.600, -2.400, -2.200, -2.000, -1.850, -1.700, -1.550, -1.400,
123  -1.250, -1.100, -0.950, -0.800, -0.650, -0.500, -0.350, -0.200, -0.050
124  },
125 
126  {
127  -0.600, -0.500, -0.400, -0.300, -0.200, -0.150, -0.100, -0.075, -0.050, -0.025,
128  0.000, 0.025, 0.050, 0.075, 0.100, 0.125, 0.150, 0.175, 0.200, 0.225,
129  0.250, 0.275, 0.300, 0.325, 0.350, 0.375, 0.400, 0.425, 0.500, 0.600,
130  0.800, 1.000, 1.200, 1.400
131  }
132  };
133 
134 
135 
136  inline bool peordering(const pair<int, double>& v1, const pair<int, double>& v2)
137  {
138  return (v1.first < v2.first);
139  }
140 
141 }
142 
143 
144 double
145 DetectorResponse::GetAreaProj(int itype, double theta, double ke)
146 {
147  // NOTE : For ASCII the projected area has a modulation with azimuth.
148  // At 88 [deg] there is a modulation of +-7% with azimuth.
149  // The mean over all azimuths is used, which corresponds approximately to the case of azimuth=90 [deg]
150  // ( projected particle direction perpendicular to the long side of the box)
151 
152  if (itype < 0 || itype > 2) return 0.;
153 
154  double f = 1.;
155  if (fUseEnlargeArea && itype == 0 && log10(ke) < lKE_MuonLow[fDetectorType][nKE_MuonLow[fDetectorType] - 1]) f = 2.;
156 
157  if (fDetectorType == 0) return M_PI * tankr * tankr * f * f + 2.*tankh * tankr * f * tan(theta);
158  else if (fDetectorType == 1) {
159  double L = scinlength * f, W = scinwidth * f, H = scinheight;
160  double /*Max=sqrt(L*L+W*W)*H*tan(theta), Min=W*H*tan(theta),*/ Mean = L * H * tan(theta);
161  return L * W + Mean;
162  } else return MDlength * MDwidth * nMD;
163 }
164 
165 double
166 DetectorResponse::GetAreaPerp(int itype, double theta, double ke)
167 {
168  return GetAreaProj(itype, theta, ke) * cos(theta);
169 }
170 
171 double
172 DetectorResponse::GetRelativeTrack(double theta)
173 {
174  if (fDetectorType == 0) return 1. / (cos(theta) + 2.*tankh * sin(theta) / M_PI / tankr);
175  else return 1. / cos(theta);
176 }
177 
178 
179 //-----------------------------------------------------------------------------
180 //------------Constructor
181 //-----------------------------------------------------------------------------
182 
183 
184 
185 DetectorResponse::DetectorResponse(bool flag, int DetectorType, bool UseEnlargeArea)
186 {
187  fUseEnlargeArea = UseEnlargeArea;
188  fDetectorType = DetectorType;
189 
190  //Check valid detector
191  if (fDetectorType < 0 || fDetectorType > 2) {
192  printf("Incorrect detector type %d \n", fDetectorType);
193  exit(1);
194  }
195 
196  //Set iGrid
197  iGrid = fDetectorType;
198 
199  //Set NPECUT
200  if (fDetectorType == 2) NPECUT = UNDEF;
201  else NPECUT = 10;
202 
203  //Set CDF/G4 Dir
204  fDataDir = DATA_DIR;
205  fDataDir += "/";
206 
207  if (fDetectorType == 0 && flag) fDataDir += "g4files-wcd";
208  else if (fDetectorType == 0 && !flag) fDataDir += "cdffiles-wcd";
209  else if (fDetectorType == 1 && flag) fDataDir += "g4files-scin";
210  else if (fDetectorType == 1 && !flag) fDataDir += "cdffiles-scin";
211  else if (fDetectorType == 2 && flag) fDataDir += "g4files-md";
212  else if (fDetectorType == 2 && !flag) fDataDir += "cdffiles-md";
213 
214 
215  for (int itype = 0; itype < NTYPES - 2; itype++) { // NTYPES particle species implemented so far
216  //const char *pName;
217  unsigned int nx = nTo_Grid[iGrid], ny;
218  const double* xvalue = Theta_Grid[iGrid], *yvalue;
219  vector <PeCDF>* fCDFs, *fCDFs_dec;
220  switch (itype) {
221  case 0: {
222  /*pName=muonName;*/ ny = nKE_Muon[iGrid] ;
223  yvalue = lKE_Muon[iGrid];
224  fCDFs = &fMuonCDFs;
225  fCDFs_dec = &fMichelElectronCDFs;
226  break;
227  }
228  case 1: {
229  /*pName=electronName;*/ ny = nKE_Electron[iGrid];
230  yvalue = lKE_Electron[iGrid];
231  fCDFs = &fElectronCDFs;
232  fCDFs_dec = NULL;
233  break;
234  }
235  case 2: {
236  /*pName=gammaName;*/ ny = nKE_Gamma[iGrid];
237  yvalue = lKE_Gamma[iGrid];
238  fCDFs = &fGammaCDFs;
239  fCDFs_dec = NULL;
240  break;
241  }
242  case 3: {
243  /*pName=muonNameLow;*/ ny = nKE_MuonLow[iGrid];
244  yvalue = lKE_MuonLow[iGrid];
245  fCDFs = &fMuonLowCDFs;
246  fCDFs_dec = &fMichelElectronLowCDFs;
247  break;
248  }
249  default:
250  continue;
251  }
252 
253  if (fDetectorType == 2 && itype != 0) continue;
254 
255  //--Create the CDFs
256  for (unsigned int j = 0; j < ny; j++) {
257  for (unsigned int i = 0; i < nx; i++) {
258  PeCDF thisCDF, thisCDF_MichelElectron;
259  thisCDF.itype = itype;
260 
261  thisCDF.theta = xvalue[i] * M_PI / 180.;
262  thisCDF.theta_deg = xvalue[i];
263  thisCDF.lke = yvalue[j];
264 
265  thisCDF.mean = 0.;
266  thisCDF.rms = 0.;
267  thisCDF.nentries = 0;
268  thisCDF.nentriesCut = 0;
269  thisCDF.probZero = 0.;
270  thisCDF.probCut = 0.;
271  thisCDF.probDecay = 0.;
272  thisCDF.probHit = 0.;
273  thisCDF.PeCut = NPECUT;
274  thisCDF.median = 0.;
275 
276  thisCDF_MichelElectron = thisCDF;
277  thisCDF_MichelElectron.itype = (itype == 0 ? 4 : (itype == 3 ? 5 : UNDEF));
278 
279  if (flag) ReadG4File(thisCDF, thisCDF_MichelElectron);
280 
281  fCDFs->push_back(thisCDF);
282  //---Signal from Michel electron
283  if (fCDFs_dec != NULL && DetectorType != 2) fCDFs_dec->push_back(thisCDF_MichelElectron);
284  }
285  }
286  bool ok = true;
287  if (!flag) {
288  ok = ReadCDFFile(fCDFs, nx * ny);
289  if (fCDFs_dec != NULL && DetectorType != 2) ReadCDFFile(fCDFs_dec, nx * ny);
290  } else {
291  ok = WriteCDFFile(fCDFs);
292  if (fCDFs_dec != NULL && DetectorType != 2) WriteCDFFile(fCDFs_dec);
293  }
294 
295  if (!ok) {
296  printf("Severe problem initializing DetectorResponse | Failed reading/writing CDF Files \n");
297  exit(1);
298  }
299  }
300 
301 
302  // Set Unit per PE
303  if (fDetectorType == 0) UnitPerPE = UnitPerPE_wcd;
304  else if (fDetectorType == 1) UnitPerPE = UnitPerPE_scin;
305  else UnitPerPE = UnitPerPE_md;
306 }
307 
308 
309 //-----------------------------------------------------------------------------
310 //------------Get Name, Get bin number, Get CDF of a bin
311 //-----------------------------------------------------------------------------
312 
313 const char* DetectorResponse::GetParticleName(int itype)
314 {
315  if (itype == 0) return muonName;
316  else if (itype == 1) return electronName;
317  else if (itype == 2) return gammaName;
318  else if (itype == 3) return muonNameLow;
319  else if (itype == 4) return michelName;
320  else if (itype == 5) return michelNameLow;
321 
322  return "unknownParticle";
323 }
324 
325 
326 //lke log10(ke) GeV , itype (internal coding), to in radians
327 // ibins[4] --> [0] (to1,ke1) [1] (to1,ke2) [2] (to2,ke1) [3] (to2,ke2)
328 // cbin --> closest bin
329 int
330 DetectorResponse::GetBin(double lke, double to, int itype, int* ibins , bool& flag)
331 {
332  int cbin;
333  unsigned int nx = nTo_Grid[iGrid], ny;
334  const double* xvalue = Theta_Grid[iGrid], *yvalue;
335  switch (itype) {
336  case 0: {
337  ny = nKE_Muon[iGrid] ;
338  yvalue = lKE_Muon[iGrid];
339  break;
340  }
341  case 1: {
342  ny = nKE_Electron[iGrid];
343  yvalue = lKE_Electron[iGrid];
344  break;
345  }
346  case 2: {
347  ny = nKE_Gamma[iGrid];
348  yvalue = lKE_Gamma[iGrid];
349  break;
350  }
351  case 3: {
352  ny = nKE_MuonLow[iGrid];
353  yvalue = lKE_MuonLow[iGrid];
354  break;
355  }
356  case 4: {
357  ny = nKE_Muon[iGrid] ;
358  yvalue = lKE_Muon[iGrid];
359  break;
360  }
361  case 5: {
362  ny = nKE_MuonLow[iGrid] ;
363  yvalue = lKE_MuonLow[iGrid];
364  break;
365  }
366  default:
367  ostringstream what;
368  what << "Unknown particle type (" << itype << ") in " << __func__ << " at " << __FILE__ << ":" << __LINE__;
369  throw std::logic_error(what.str());
370  }
371 
372  double lkemin = yvalue[0], lkemax = yvalue[ny - 1];
373  double thetamin = xvalue[0] * M_PI / 180., thetamax = xvalue[nx - 1] * M_PI / 180.;
374  int ix_bin = -1, iy_bin = -1;
375  bool extrapol_flag_to = false;
376  bool extrapol_flag_ke = false;
377  flag = false;
378 
379  //Extrapolation check
380  if (to < thetamin) {
381  ix_bin = 0;
382  extrapol_flag_to = true;
383  flag = true;
384  } else if (to >= thetamax) {
385  ix_bin = nx - 2;
386  extrapol_flag_to = true;
387  flag = true;
388  }
389 
390  if (lke < lkemin) {
391  iy_bin = 0;
392  extrapol_flag_ke = true;
393  flag = true;
394  } else if (lke >= lkemax) {
395  iy_bin = ny - 2;
396  extrapol_flag_ke = true;
397  flag = true;
398  }
399 
400  //Interpolation bins
401  if (extrapol_flag_to) {
402  if (DEBUG_RESP == 1)
403  printf("Warning: Particle angle outside range, an extrapolation will be used, %10.2lf deg !\n", to * 180. / M_PI);
404  } else {
405  for (unsigned int ix = 0; ix < (nx - 1); ix++)
406  if (to >= (xvalue[ix]*M_PI / 180.) && to < (xvalue[ix + 1]*M_PI / 180.)) {
407  ix_bin = ix;
408  break;
409  }
410  }
411 
412  if (extrapol_flag_ke) {
413  if (DEBUG_RESP == 1) printf("Warning: Particle Energy outside range, an extrapolation will be used, log(ke)=%10.7lf GeV \n", lke);
414  } else {
415  for (unsigned int iy = 0; iy < (ny - 1); iy++)
416  if (lke >= yvalue[iy] && lke < yvalue[iy + 1]) {
417  iy_bin = iy;
418  break;
419  }
420  }
421 
422  if (nx == 1) {
423  ibins[0] = iy_bin * nx;
424  ibins[1] = (iy_bin + 1) * nx;
425  ibins[2] = iy_bin * nx;
426  ibins[3] = (iy_bin + 1) * nx;
427  } else {
428  ibins[0] = iy_bin * nx + ix_bin;
429  ibins[1] = (iy_bin + 1) * nx + ix_bin;
430  ibins[2] = iy_bin * nx + ix_bin + 1;
431  ibins[3] = (iy_bin + 1) * nx + ix_bin + 1;
432  }
433 
434  //Closest bin
435  double min;
436  int cbin_x = -1, cbin_y = -1;
437  min = 1.e10;
438  for (unsigned int ix = 0; ix < nx; ix++)
439  if (fabs(to * 180. / M_PI - xvalue[ix]) < min) {
440  cbin_x = ix;
441  min = fabs(to * 180. / M_PI - xvalue[ix]);
442  }
443  min = 1.e10;
444  for (unsigned int iy = 0; iy < ny; iy++)
445  if (fabs(lke - yvalue[iy]) < min) {
446  cbin_y = iy;
447  min = fabs(lke - yvalue[iy]);
448  }
449  if (cbin_x < 0 || cbin_y < 0) return -1;
450 
451  cbin = cbin_y * nx + cbin_x;
452 
453  return cbin;
454 }
455 
456 
457 PeCDF
458 DetectorResponse::GetCDF(int itype, int ibin)
459 {
460  vector <PeCDF>* fCDFs;
461  switch (itype) {
462  case 0: {
463  fCDFs = &fMuonCDFs;
464  break;
465  }
466  case 1: {
467  fCDFs = &fElectronCDFs;
468  break;
469  }
470  case 2: {
471  fCDFs = &fGammaCDFs;
472  break;
473  }
474  case 3: {
475  fCDFs = &fMuonLowCDFs;
476  break;
477  }
478  case 4: {
479  fCDFs = &fMichelElectronCDFs;
480  break;
481  }
482  case 5: {
483  fCDFs = &fMichelElectronLowCDFs;
484  break;
485  }
486 
487  default:
488  ostringstream what;
489  what << "Unknown particle type (" << itype << ") in " << __func__ << " at " << __FILE__ << ":" << __LINE__;
490  throw std::logic_error(what.str());
491  }
492 
493  PeCDF pCDF = fCDFs->at(ibin);
494 
495  printf("%s (%d) log(ke)=%4.2lf theta=%.0lf mean=%e rms=%e nentries=%d pzero=%e pcut=%e | (-npe,npeCut)(%d,%d) ",
496  GetParticleName(pCDF.itype), pCDF.itype, pCDF.lke, pCDF.theta_deg,
497  pCDF.mean, pCDF.rms, pCDF.nentries, pCDF.probZero, pCDF.probCut, pCDF.cdf[0].first, NPECUT);
498  if (itype == 0) printf(" pdecay=%e \n", pCDF.probDecay);
499  else printf("\n");
500  return pCDF;
501 }
502 
503 
504 
505 //------------------------------------------------------------
506 //--Read the G4 File and set up the CDF
507 //------------------------------------------------------------
508 
509 bool
510 DetectorResponse::ReadG4File(PeCDF& pCDF, PeCDF& pCDF_dec)
511 {
512 
513  //G4File name
514  char G4FileName[200];
515  sprintf(G4FileName, "%s/%s/ke%5.3lf_to%d.dat", fDataDir.c_str()
516  , GetParticleName(pCDF.itype), pCDF.lke, int(pCDF.theta_deg));
517 
518  //--Open G4 file
519  FILE* fp = fopen(G4FileName, "r");
520  if (fp == NULL) {
521  printf("Could not open %s file \n", G4FileName);
522  return false;
523  }
524 
525  printf("Reading %s file \n", G4FileName);
526 
527  while (true) {
528  int partId;
529  double keo;
530  double to = 0;
531  double x, y, z;
532 
533  //int decayFlag=0;
534  double petot = 0., petot_decay = 0.;
535 
536  if (fDetectorType < 2) {
537  // Length units [mm]
538  double ASCII_Track_p, ASCII_Edep_p;
539  double ASCII_Track, ASCII_Edep, ASCII_Edep_Michel;
540 
541  double ASCII_petot, ASCII_petot_Michel;
542  double ASCII_FADCSum_LG, ASCII_FADCSum_HG;
543 
544  double WCD_Track_p;
545  double WCD_petot, WCD_petot_Michel;
546  double WCD_FADCSum_LG, WCD_FADCSum_HG;
547 
548  int decayFlag_Hall;
549  double MichelKE, MichelZ, MichelTheta;
550 
551  double dummy1, dummy2;
552  double fTrack_Ref, fTrack_ASCII, fTrack_WCD;
553 
554  int nread = fscanf(fp, "%d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %d %lf %lf %lf %lf %lf %lf %lf ",
555  &partId, &to, &keo, &x, &y, &z,
556  &fTrack_Ref, &fTrack_ASCII, &fTrack_WCD, &WCD_Track_p,
557  &ASCII_Track_p, &ASCII_Edep_p, &ASCII_Track, &ASCII_Edep, &ASCII_Edep_Michel,
558  &ASCII_petot, &WCD_petot,
559  &ASCII_FADCSum_LG, &ASCII_FADCSum_HG, &WCD_FADCSum_LG, &WCD_FADCSum_HG,
560  &decayFlag_Hall, &MichelKE, &MichelZ, &MichelTheta,
561  &ASCII_petot_Michel, &WCD_petot_Michel , &dummy1, &dummy2);
562  if (nread != 29) break;
563 
564  petot = (fDetectorType == 0 ? WCD_petot - WCD_petot_Michel : ASCII_petot - ASCII_petot_Michel);
565  petot_decay = (fDetectorType == 0 ? WCD_petot_Michel : ASCII_petot_Michel);
566 
567  for (int icase = 0; icase < 2; icase++) {
568  double pe = (icase == 0 ? petot : petot_decay);
569  PeCDF* thisCDF = (icase == 0 ? &pCDF : &pCDF_dec);
570 
571  thisCDF->mean += pe;
572  thisCDF->rms += pow(pe, 2.);
573  thisCDF->nentries++;
574 
575  if (pe == 0.) thisCDF->probZero += 1.;
576  if (icase == 0 && petot_decay > 0.) thisCDF->probDecay += 1.;
577  if (pe < NPECUT && NPECUT != UNDEF) {
578  thisCDF->probCut += 1.;
579  thisCDF->nentriesCut++;
580  }
581 
582  int size = thisCDF->prob.size();
583  bool flag_e = false;
584  for (int ipe = 0; ipe < size; ipe++)
585  if (int(pe) == thisCDF->prob[ipe].first) {
586  flag_e = true;
587  thisCDF->prob[ipe].second += 1.;
588  }
589  if (!flag_e) thisCDF->prob.push_back(pair<int, double>((int)pe, 1));
590  }
591  }
592  //----
593  else if (fDetectorType == 2) {
594  double /*theta,ke,xinj,yinj,zinj,*/track_p, edep_p, track, edep, meanX, npe;
595  //unsigned int id;
596  double xabove , yabove , zabove;
597  double xbelow , ybelow ,/*zbelow,*/ebelow, tbelow;
598  double xabove_sec, yabove_sec,/*zabove_sec,*/eabove_sec, tabove_sec;
599  double xbelow_sec, ybelow_sec,/*zbelow_sec,*/ebelow_sec, tbelow_sec;
600 
601  unsigned int nread = fscanf(fp, "%d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf ",
602  &partId, &to, &keo, &x, &y, &z, &track_p, &edep_p, &track, &edep, &npe, &meanX,
603  &xabove, &yabove, &zabove,
604  &ebelow, &xbelow, &ybelow, &tbelow,
605  &eabove_sec, &xabove_sec, &yabove_sec, &tabove_sec,
606  &ebelow_sec, &xbelow_sec, &ybelow_sec, &tbelow_sec);
607  if (nread != 27) break;
608  if (xbelow > 0. && xbelow / 10. < TabulatedTankSimulatorNS::MDlength && fabs(ybelow / 10.) < TabulatedTankSimulatorNS::MDwidth / 2.) pCDF.probHit += 1.;
609  pCDF.nentries++;
610  }
611 
612  // Checks
613  if (fabs(to - pCDF.theta_deg) > 0.1) {
614  printf("Reading wrong file \n");
615  continue;
616  }
617  if (fabs(log10(keo) - pCDF.lke) > 0.01) {
618  printf("Reading wrong file \n");
619  continue;
620  }
621 
622  }
623  fclose(fp);
624 
625  //-----------------------------------
626  // Set (probZero,probCut,probDecay,probHit,mean,rms,CDF)
627  //-----------------------------------
628  if (fDetectorType == 2) {
629  if (pCDF.nentries > 0) pCDF.probHit = pCDF.probHit / double(pCDF.nentries) * MDAreaRatio;
630  else pCDF.probHit = 0;
631  } else {
632  for (int icase = 0; icase < 2; icase++) {
633  PeCDF* thisCDF = (icase == 0 ? &pCDF : &pCDF_dec);
634  if (thisCDF->nentries > 0) {
635  thisCDF->probZero = thisCDF->probZero / double(thisCDF->nentries);
636  thisCDF->probDecay = thisCDF->probDecay / double(thisCDF->nentries);
637  thisCDF->probCut = thisCDF->probCut / double(thisCDF->nentries);
638  thisCDF->mean /= double(thisCDF->nentries);
639  thisCDF->rms = sqrt(double(thisCDF->nentries) / double(thisCDF->nentries - 1) * (thisCDF->rms / double(thisCDF->nentries) - thisCDF->mean * thisCDF->mean));
640  SetUpCDFs(thisCDF);
641  } else {
642  thisCDF->probZero = 1.;
643  thisCDF->probDecay = 0.;
644  thisCDF->probCut = 1.;
645  thisCDF->mean = 0.;
646  thisCDF->rms = 0.;
647  }
648  }
649  }
650 
651  if (fDetectorType == 2) return true;
652 
653  return true;
654 }
655 
656 
657 void
658 DetectorResponse::SetUpCDFs(PeCDF* pCDF)
659 {
660 
661  /*Order CDFs in increasing of order of pes*/
662  sort(pCDF->prob.begin(), pCDF->prob.end(), peordering);
663 
664  /*Set Mean/RMS/Nentries */
665  double nentries = double(pCDF->nentries);
666  double nentriesCut = double(pCDF->nentriesCut);
667  pCDF->median = 0;
668 
669  /*CDF when n_pe < NPECUT */
670  if (NPECUT == UNDEF)
671  pCDF->PeCut = (pCDF->prob.size() > 0 ? pCDF->prob[0].first : 0);
672  else {
673  pCDF->PeCut = NPECUT;
674  for (int ipe = 0; ipe < NPECUT; ipe++) {
675  double acc = 0.;
676  for (unsigned int ii = 0; ii < pCDF->prob.size(); ii++) {
677  if (pCDF->prob[ii].first > (NPECUT - 1)) break;
678  if (pCDF->prob[ii].first <= ipe) acc += pCDF->prob[ii].second;
679  }
680  if (nentriesCut > 0.) acc = acc / double(nentriesCut);
681  else acc = 0.;
682 
683  pCDF->cdf.push_back(pair<int, double>(ipe, acc));
684  }
685  if (nentries == nentriesCut) {
686  pCDF->prob.clear();
687  return;
688  }
689  }
690 
691  /*CDF when n_pe >=NPECUT */
692  int nbins;
693  if ((nentries - nentriesCut) < 10.) nbins = 1;
694  else nbins = int(NCDFMAX < (nentries - nentriesCut) / 10. ? NCDFMAX : (nentries - nentriesCut) / 10.);
695  int step = int(nentries - nentriesCut) / nbins;
696 
697  double cnt_acc = 0., cnt = 0.;
698  for (unsigned int ipe = 0; ipe < pCDF->prob.size(); ipe++) {
699  int npe = pCDF->prob[ipe].first;
700  double nparticles = pCDF->prob[ipe].second;
701 
702  if (npe < pCDF->PeCut) continue; /*Skip n_pe<PeCut*/
703  cnt_acc += nparticles;
704  cnt += nparticles; /*Counter*/
705 
706  if (pCDF->median == 0. && (cnt_acc + nentriesCut) / nentries > 0.5) pCDF->median = npe; /*Set the Median*/
707 
708  if (cnt >= step || ipe == (pCDF->prob.size() - 1)) {
709  double prob = cnt_acc / (nentries - nentriesCut);
710  pCDF->cdf.push_back(pair<int, double>(npe, prob)) ;
711  cnt = 0.;
712  }
713  }
714 
715  pCDF->prob.clear(); /*Clear the single entry CDFs, too much memory space*/
716 }
717 
718 
719 
720 //-----------------------------------------------------------------------------
721 //------------Read/Write CDF files
722 //-----------------------------------------------------------------------------
723 
724 bool
725 DetectorResponse::ReadCDFFile(vector<PeCDF>* fCDFs, int size)
726 {
727  char CDFFileName[200];
728  if (fDetectorType == 0)
729  sprintf(CDFFileName, "%s/%s.wcd.dat", fDataDir.c_str(), GetParticleName(fCDFs->at(0).itype));
730  else if (fDetectorType == 1)
731  sprintf(CDFFileName, "%s/%s.scin.dat", fDataDir.c_str(), GetParticleName(fCDFs->at(0).itype));
732  else if (fDetectorType == 2)
733  sprintf(CDFFileName, "%s/%s.md.dat", fDataDir.c_str(), GetParticleName(fCDFs->at(0).itype));
734 
735 
736  FILE* fp;
737  fp = fopen(CDFFileName, "r");
738 
739  if (!fp) {
740  printf("Could not open %s file \n", CDFFileName);
741  return false;
742  }
743 
744  int cnt = 0;
745  while (!feof(fp)) {
746  if (cnt >= size) break;
747 
748  unsigned int nbins = 0;
749  int PeCut = 0, itype = -1, nentries = 0, nentriesCut = 0;
750  double lke, to_deg, mean, rms, median, probCut, probHit, probZero;
751  int nread =
752  fscanf(fp, "%d %lf %lf %lf %lf %lf %d %d %lf %lf %lf %d %u ",
753  &itype, &lke, &to_deg, &mean, &rms, &median, &nentries, &nentriesCut, &probZero, &probCut, &probHit, &PeCut, &nbins);
754  if (nread != 13) return false;
755 
756  bool extrapol_flag;
757  int bins[4];
758  int ibin = GetBin(lke, to_deg * M_PI / 180., itype, bins, extrapol_flag);
759 
760  if (ibin < 0 || ibin > size) return false;
761 
762  if (itype != fCDFs->at(ibin).itype) return false;
763  if (fabs(lke - fCDFs->at(ibin).lke)) return false;
764  if (fabs(to_deg - fCDFs->at(ibin).theta_deg)) return false;
765  if (fDetectorType < 0 || fDetectorType > 2) return false;
766  if (PeCut != NPECUT && NPECUT != UNDEF) return false;
767 
768  fCDFs->at(ibin).mean = mean;
769  fCDFs->at(ibin).rms = rms;
770  fCDFs->at(ibin).median = median;
771  fCDFs->at(ibin).nentries = nentries;
772  fCDFs->at(ibin).nentriesCut = nentriesCut;
773  fCDFs->at(ibin).PeCut = PeCut;
774  fCDFs->at(ibin).probCut = probCut;
775  fCDFs->at(ibin).probZero = probCut;
776  fCDFs->at(ibin).probHit = probHit;
777 
778  for (unsigned int i = 0; i < nbins; i++) {
779  int npe = 0;
780  double prob = 0.;
781  if (fscanf(fp, " %d %lf ", &npe, &prob) != 2) return false;
782  fCDFs->at(ibin).cdf.push_back(pair<int, double>(npe, prob));
783  }
784  if (fCDFs->at(ibin).cdf.size() != nbins) return false;
785  cnt++;
786  }
787 
788  if (cnt != size) return false;
789 
790  return true;
791 }
792 
793 
794 bool
795 DetectorResponse::WriteCDFFile(vector<PeCDF>* fCDFs)
796 {
797  //---Write CDF file
798  char CDFFileName[200];
799  if (fDetectorType == 0)
800  sprintf(CDFFileName, "%s/%s.wcd.dat", fDataDir.c_str(), GetParticleName(fCDFs->at(0).itype));
801  else if (fDetectorType == 1)
802  sprintf(CDFFileName, "%s/%s.scin.dat", fDataDir.c_str(), GetParticleName(fCDFs->at(0).itype));
803  else if (fDetectorType == 2)
804  sprintf(CDFFileName, "%s/%s.md.dat", fDataDir.c_str(), GetParticleName(fCDFs->at(0).itype));
805 
806  printf("Writing %s CDFFileName \n", CDFFileName);
807 
808  FILE* fp = fopen(CDFFileName, "w");
809  if (!fp) {
810  printf("Could not open %s file \n", CDFFileName);
811  return false;
812  }
813 
814  for (unsigned int ibin = 0; ibin < fCDFs->size(); ibin++) {
815 
816  fprintf(fp, "%d %e %4.2lf %e %e %e %d %d %e %e %e %d %zu \n ",
817  fCDFs->at(ibin).itype, fCDFs->at(ibin).lke,
818  fCDFs->at(ibin).theta_deg, fCDFs->at(ibin).mean, fCDFs->at(ibin).rms,
819  fCDFs->at(ibin).median, fCDFs->at(ibin).nentries, fCDFs->at(ibin).nentriesCut,
820  fCDFs->at(ibin).probZero, fCDFs->at(ibin).probCut, fCDFs->at(ibin).probHit, fCDFs->at(ibin).PeCut, fCDFs->at(ibin).cdf.size());
821 
822  for (unsigned int i = 0; i < fCDFs->at(ibin).cdf.size(); i++)
823  fprintf(fp, " %d %e \n ", fCDFs->at(ibin).cdf[i].first, fCDFs->at(ibin).cdf[i].second);
824  }
825  fclose(fp);
826 
827  return true;
828 }
829 
830 
831 //-----------------------------------------------------------------------------
832 //------------Signal Interpolation utilities
833 //-----------------------------------------------------------------------------
834 
835 
836 //--Linear Interpolation
837 double
838 DetectorResponse::Interpolate(double* x, double* y, double x0)
839 {
840  if (x[0] == x[1] && y[0] == y[1]) return y[0];
841 
842  double y0 = (y[1] - y[0]) / (x[1] - x[0]) * (x0 - x[0]) + y[0];
843  return y0;
844 }
845 
846 //---Calculate the signal given a value of the CDF
847 double
848 DetectorResponse::GetSignalBin(double f, PeCDF& fPeCDF)
849 {
850  //---Give back the Mean
851  if (f == -100) return fPeCDF.mean;
852 
853  //-Get the bins
854  int start = (NPECUT == UNDEF ? 0 : NPECUT);
855  int end = fPeCDF.cdf.size() ;
856  int size = end - start;
857 
858  if (size == 0) return fPeCDF.PeCut;
859 
860  int icdf = 0;
861  for (int i = start; i < end ; i++)
862  if (fPeCDF.cdf[i].second > f) {
863  icdf = i;
864  break;
865  }
866 
867 
868  double x[2], y[2];
869  if (icdf == start) {
870  x[0] = 0.;
871  x[1] = fPeCDF.cdf[icdf].second;
872  y[0] = fPeCDF.PeCut - 1;
873  y[1] = fPeCDF.cdf[icdf].first;
874  } else {
875  if (icdf == (end - 1) && size > 2) icdf = icdf - 1;
876 
877  x[0] = fPeCDF.cdf[icdf - 1].second;
878  x[1] = fPeCDF.cdf[icdf].second;
879  y[0] = fPeCDF.cdf[icdf - 1].first;
880  y[1] = fPeCDF.cdf[icdf].first;
881  }
882  double res = Interpolate(x, y, f);
883 
884  return round(res + 0.5);
885 
886 }
887 
888 //-----------------------------------------------------------------------------
889 // Hit probability ( only for muons in the Muon Detector )
890 // Interpolation in sec(theta)
891 // theta in radians
892 // ke in GeV
893 //-----------------------------------------------------------------------------
894 bool DetectorResponse::IsHit(double ke, double theta, int itype , double f)
895 {
896  if (itype != 0) return false;
897  if (fDetectorType != 2) return false;
898  if (f <= 0.) return false;
899  if (ke > 10.) return true;
900 
901  bool outsideRange = false;
902  vector <PeCDF>* fCDFs = &fMuonCDFs;
903  unsigned int nx = nTo_Grid[iGrid], ny = nKE_Muon[iGrid];
904 
905  //Check on f
906  if (!(f == -100) && !(f > 0 && f < 1)) return false;
907 
908  //Check completeness of CDF
909  if (fCDFs->size() < nx * ny) {
910  printf("Warning: there are no enough CDFs for this particle specie %zu , %u %u || TERMINATE \n", fCDFs->size(), nx, ny);
911  return false; //--Terminate the program
912  }
913 
914  //x value to interpolate
915  double lke0 = log10(ke);
916  double track0 = GetRelativeTrack(theta);
917 
918  //--Bins to be used for interpolation
919  int ibins[4]; // 0->(to1,ke1) 1->(to1,ke2) 2->(to2,ke1) 3->(to2,ke2)
920  GetBin(lke0 , theta, itype, ibins, outsideRange);
921 
922  //Check entries
923  bool entriesFlag = (fCDFs->at(ibins[0]).nentries == 0 || fCDFs->at(ibins[1]).nentries == 0 ||
924  fCDFs->at(ibins[2]).nentries == 0 || fCDFs->at(ibins[3]).nentries == 0);
925 
926  if (entriesFlag) {
927  printf("Warning: one of the bins needed to interpolate have no entries, in both branches, Particle : %d theta %5.2lf log(ke) %5.2lf \n", itype, theta * 180. / M_PI, lke0);
928  return false;
929  }
930 
931  //Set x values of interpolation
932  double lke[2] = { fCDFs->at(ibins[0]).lke, fCDFs->at(ibins[1]).lke };
933  double to[2] = { fCDFs->at(ibins[0]).theta, fCDFs->at(ibins[2]).theta};
934  double track[2];
935  track[0] = GetRelativeTrack(to[0]);
936  track[1] = GetRelativeTrack(to[1]);
937 
938  //-----------------------------------------------------------------------------------------------------------------
939 
940  double ptheta[2];
941  double hit[2];
942 
943  hit[0] = fCDFs->at(ibins[0]).probHit;
944  hit[1] = fCDFs->at(ibins[1]).probHit;
945  ptheta[0] = Interpolate(lke, hit, lke0);
946 
947 
948  hit[0] = fCDFs->at(ibins[2]).probHit;
949  hit[1] = fCDFs->at(ibins[3]).probHit;
950  ptheta[1] = Interpolate(lke, hit, lke0);
951 
952  double probHit = Interpolate(track, ptheta, track0);
953 
954  if (f < probHit) return true;
955  else return false;
956 
957 }
958 
959 //-----------------------------------------------------------------------------
960 // Signal
961 //-----------------------------------------------------------------------------
962 
963 //It returns the signal in Total Number of PEs
964 //If the muon decays the electron signal is not added, unless the Mean Signal is requested
965 //Theta in radians, ke in GeV, particle Id
966 double DetectorResponse::GetPe(double ke, double theta, int itype , double f)
967 {
968  //--Signal ~ E for EM particles (calorimeter approach) and independent on Theta
969  //--Signal ~ <track> for Muons and independent on energy
970 
971  //-- itype = 0 (Muons/AntiMuons) 1 (Electrons/Positrons) 2 (Gammas) 3 (Muons/AntiMuons enlarge area) 4 ( Michel electron ) 5 ( Michel electron enlarge area )
972 
973  //--Therefore:
974  // 1) Interpolations in E are done in (log Signal,log E)
975  // 2) Interpolation in Theta are done in ( Signal, Track(Theta) )
976 
977  if (fDetectorType == 2) return 0.;
978 
979  if (fUseEnlargeArea && itype == 0 && log10(ke) < lKE_MuonLow[fDetectorType][nKE_MuonLow[fDetectorType] - 1]) itype = 3;
980  if (fUseEnlargeArea && itype == 4 && log10(ke) < lKE_MuonLow[fDetectorType][nKE_MuonLow[fDetectorType] - 1]) itype = 5;
981 
982  vector <PeCDF>* fCDFs;
983  unsigned int nx = nTo_Grid[iGrid], ny;
984  bool outsideRange = false;
985 
986  //Check on f
987  if (!(f == -100) && !(f >= 0. && f <= 1.)) return 0.;
988 
989  //Select CDF
990  if (itype == 0) {
991  ny = nKE_Muon[iGrid];
992  fCDFs = &fMuonCDFs;
993  } else if (itype == 1) {
994  ny = nKE_Electron[iGrid];
995  fCDFs = &fElectronCDFs;
996  } else if (itype == 2) {
997  ny = nKE_Gamma[iGrid];
998  fCDFs = &fGammaCDFs;
999  } else if (itype == 3) {
1000  ny = nKE_MuonLow[iGrid];
1001  fCDFs = &fMuonLowCDFs;
1002  } else if (itype == 4) {
1003  ny = nKE_Muon[iGrid];
1004  fCDFs = &fMichelElectronCDFs;
1005  } else if (itype == 5) {
1006  ny = nKE_MuonLow[iGrid];
1007  fCDFs = &fMichelElectronLowCDFs;
1008  } else return 0.;
1009 
1010  //Check completeness of CDF
1011  if (fCDFs->size() < nx * ny) {
1012  printf("Warning: there are no enough CDFs for this particle specie %zu , %u %u || TERMINATE \n", fCDFs->size(), nx, ny);
1013  return 0.; //--Terminate the program
1014  }
1015 
1016  //x value to interpolate
1017  double lke0 = log10(ke);
1018  double track0 = GetRelativeTrack(theta);
1019 
1020  //--Bins to be used for interpolation
1021  int ibins[4]; // 0->(to1,ke1) 1->(to1,ke2) 2->(to2,ke1) 3->(to2,ke2)
1022  GetBin(lke0 , theta, itype, ibins, outsideRange);
1023 
1024  //Check entries
1025  bool entriesFlag = (fCDFs->at(ibins[0]).nentries == 0 || fCDFs->at(ibins[1]).nentries == 0 ||
1026  fCDFs->at(ibins[2]).nentries == 0 || fCDFs->at(ibins[3]).nentries == 0);
1027  if (entriesFlag) {
1028  printf("Warning: one of the bins needed to interpolate have no entries, Particle : %d theta %5.2lf log(ke) %5.2lf \n", itype, theta * 180. / M_PI, lke0);
1029  return 0.;
1030  }
1031 
1032  //Set x values of interpolation
1033  double lke[2] = { fCDFs->at(ibins[0]).lke, fCDFs->at(ibins[1]).lke };
1034  double to[2] = { fCDFs->at(ibins[0]).theta, fCDFs->at(ibins[2]).theta};
1035  double track[2];
1036  track[0] = GetRelativeTrack(to[0]);
1037  track[1] = GetRelativeTrack(to[1]);
1038 
1039 
1040  //-----------------------------------------------------------------------------------------------------------------
1041  //----Interpolate the Probability for 0,1,...NPECUT-1 Photoelectrons
1042  //-----------------------------------------------------------------------------------------------------------------
1043  double fcorr = f;
1044  if (f != -100 && NPECUT != UNDEF) {
1045  double probCut = 0.;
1046 
1047  double zero[2], ptheta[2];
1048  //int entries[2];
1049  zero[0] = fCDFs->at(ibins[0]).probCut;
1050  zero[1] = fCDFs->at(ibins[1]).probCut;
1051  ptheta[0] = Interpolate(lke, zero, lke0);
1052  //entries[0]=fCDFs->at(ibins[0]).nentries; entries[1]=fCDFs->at(ibins[1]).nentries;
1053 
1054  zero[0] = fCDFs->at(ibins[2]).probCut;
1055  zero[1] = fCDFs->at(ibins[3]).probCut;
1056  //entries[0]=fCDFs->at(ibins[2]).nentries; entries[1]=fCDFs->at(ibins[3]).nentries;
1057  ptheta[1] = Interpolate(lke, zero, lke0);
1058  probCut = Interpolate(track, ptheta, track0);
1059 
1060 
1061  if (fcorr < probCut) {
1062 
1063  //---Calculate the Interpolated probability <= 0...9 Pes
1064  double probLow = 0.;
1065  double npe = 0.;
1066  for (int jj = 0; jj < NPECUT; jj++) {
1067  zero[0] = fCDFs->at(ibins[0]).cdf[jj].second;
1068  zero[1] = fCDFs->at(ibins[1]).cdf[jj].second;
1069  ptheta[0] = Interpolate(lke, zero, lke0);
1070 
1071  zero[0] = fCDFs->at(ibins[2]).cdf[jj].second;
1072  zero[1] = fCDFs->at(ibins[3]).cdf[jj].second;
1073  ptheta[1] = Interpolate(lke, zero, lke0);
1074  probLow = Interpolate(track, ptheta, track0);
1075 
1076  npe = double(jj);
1077  if (probLow > fcorr / probCut) break;
1078  }
1079  return npe;
1080  }
1081  fcorr = (fcorr - probCut) / (1 - probCut);
1082  }
1083 
1084  //-----------------------------------------------------------------------------------------------------------
1085  //----Interpolate when >NPECUT Photoelectrons
1086  //-----------------------------------------------------------------------------------------------------------
1087  {
1088 
1089  double signal[2], lsignal[2];
1090 
1091  //---Interpolation in Energy for Theta1
1092  signal[0] = double(GetSignalBin(fcorr, fCDFs->at(ibins[0])));
1093  signal[1] = double(GetSignalBin(fcorr, fCDFs->at(ibins[1])));
1094 
1095  lsignal[0] = log10(signal[0]);
1096  lsignal[1] = log10(signal[1]);
1097  double s1;
1098  if (signal[0] > 0. && signal[1] > 0.)
1099  s1 = pow(10., Interpolate(lke, lsignal, lke0));
1100  else
1101  s1 = Interpolate(lke, signal, lke0);
1102 
1103  //---Interpolation in Energy for Theta2
1104  signal[0] = double(GetSignalBin(fcorr, fCDFs->at(ibins[2])));
1105  signal[1] = double(GetSignalBin(fcorr, fCDFs->at(ibins[3])));
1106 
1107  lsignal[0] = log10(signal[0]);
1108  lsignal[1] = log10(signal[1]);
1109 
1110  double s2;
1111  if (signal[0] > 0. && signal[1] > 0.)
1112  s2 = pow(10., Interpolate(lke, lsignal, lke0));
1113  else
1114  s2 = Interpolate(lke, signal, lke0);
1115 
1116 
1117  double y[2] = {s1, s2};
1118  double s3 = Interpolate(track, y, track0);
1119 
1120 
1121  if (f == -100.) return s3;
1122  return round(s3);
1123  }
1124 
1125 }
static const char * muonNameLow
#define NCDFMAX
static const char * michelName
const unsigned int nTo_Grid[3]
const unsigned int nKE_Gamma[3]
const double scinwidth
Definition: UnivRec.h:43
const double lKE_Electron[3][50]
double Interpolate(const double dx, const double dy, const double x)
const double scinheight
Definition: UnivRec.h:44
const double scinlength
Definition: UnivRec.h:42
static const char * electronName
bool ok(bool okay)
Definition: testlib.cc:89
double pow(const double x, const unsigned int i)
int exit
Definition: dump1090.h:237
static const char * michelNameLow
const double MDwidth
Definition: UnivRec.h:49
bool peordering(const pair< int, double > &v1, const pair< int, double > &v2)
const double lKE_Muon[3][50]
const double lKE_MuonLow[3][50]
const unsigned int nKE_Muon[3]
static const char * muonName
const double lKE_Gamma[3][50]
const double nMD
Definition: UnivRec.h:47
std::vector< std::pair< int, double > > prob
const unsigned int nKE_MuonLow[3]
const double Theta_Grid[3][50]
#define UNDEF
Definition: UnivRec.h:24
const double tankh
Definition: UnivRec.h:38
double Mean(const std::vector< double > &v)
Definition: Functions.h:31
const unsigned int nKE_Electron[3]
std::vector< std::pair< int, double > > cdf
#define NTYPES
const double MDlength
Definition: UnivRec.h:48
static const char * gammaName
const double tankr
Definition: UnivRec.h:39
#define DEBUG_RESP

, generated on Tue Sep 26 2023.