Belle II Software  release-08-01-10
analysis-lookuptable-creation-photon-efficiency-datamc-ratio.py
1 #!/usr/bin/env python3
2 
3 
10 
11 import glob
12 import numpy as np
13 import argparse
14 
15 import basf2 as b2
16 
17 parser = argparse.ArgumentParser()
18 parser.add_argument(
19  '-i',
20  '--input_path',
21  default="/afs/desy.de/user/h/hsvidras/repositories/photoneff/analysis/plots_lima/lima/",
22  help='Path to folder with efficiency ratio files generated by the photon efficiency workflow.')
23 args = parser.parse_args()
24 
25 # Define bin constructors
26 
27 
28 def make_1D_bin(name, min_val, max_val):
29  return {name: [min_val, max_val]}
30 
31 
32 def make_2D_bin(bin_x, bin_y):
33  bin_2d = bin_x.copy()
34  bin_2d.update(bin_y)
35  return bin_2d
36 
37 
38 def make_3D_bin(bin_x, bin_y, bin_z):
39  bin_3d = bin_x.copy()
40  bin_3d.update(bin_y)
41  bin_3d.update(bin_z)
42  return bin_3d
43 
44 # To make these one needs tables generated with the photon efficiency code
45 # REPOSITORY: https://stash.desy.de/projects/DBX/repos/photoneff/browse
46 # They provide you with 2D theta phi tables, for different photon energy bins.
47 # The energy bins are defined in the file names, but the theta, phi bins are not, so they are given in separate files.
48 # The naming scheme has to be exact for this to work, but luckily the code in the repository takes care of all that.
49 # So you only need to input the location where you want the code to look for these tables.
50 # Essentially files are create for edges named
51 # BINS: table_pRecoilPhipRecoilTheta_pRecoilfrom0p2andpRecoilto0p4_pRecoil[Theta,Phi]bins.npy
52 # RATIOS: table_pRecoilPhipRecoilTheta*[values, statistical_up, statistical_down, systematic_up,systematic_down].npy
53 # , where * stands for bins in the format of: from0p2andpRecoilto0p4 (meaning 0.2<pRecoil<0.4)
54 # All this will be read automatically, but the naming scheme has to be exact.
55 
56 
57 table_location = args.input_path
58 
59 # Define bin ranges. Bins may be of different size
60 yedges = np.load(f"{table_location}/table_pRecoilPhipRecoilTheta_pRecoilfrom0p2andpRecoilto0p4_pRecoilPhibins.npy")
61 xedges = np.load(f"{table_location}/table_pRecoilPhipRecoilTheta_pRecoilfrom0p2andpRecoilto0p4_pRecoilThetabins.npy")
62 
63 # Define values to put into the table, that correspond to previously defined bins.
64 values = glob.glob(f"{table_location}/table_pRecoilPhipRecoilTheta*values.npy")
65 stat_up = glob.glob(f"{table_location}/table_pRecoilPhipRecoilTheta*statistical_up.npy")
66 stat_down = glob.glob(f"{table_location}/table_pRecoilPhipRecoilTheta*statistical_down.npy")
67 sys_up = glob.glob(f"{table_location}/table_pRecoilPhipRecoilTheta*systematic_up.npy")
68 sys_down = glob.glob(f"{table_location}/table_pRecoilPhipRecoilTheta*systematic_down.npy")
69 
70 bins_p = []
71 bins_phi = [make_1D_bin("phi", lowbin, highbin) for lowbin, highbin in zip(yedges[:-1], yedges[1:])]
72 bins_theta = [make_1D_bin("theta", lowbin, highbin) for lowbin, highbin in zip(xedges[:-1], xedges[1:])]
73 
74 table = []
75 
76 for n, valuenp in enumerate(values):
77 
78  bins_with_text = valuenp.split('pRecoilfrom')[1].split('pRecoilto')
79  lowbin_str = bins_with_text[0][:-3].replace('p', '.')
80  highbin_str = bins_with_text[1][:-11].replace('p', '.')
81  pbin = make_1D_bin("E", float(lowbin_str), float(highbin_str))
82 
83  value = np.load(valuenp)
84  stat_err_up_table = np.load(stat_up[n])
85  stat_err_down_table = np.load(stat_down[n])
86  sys_err_up_table = np.load(sys_up[n])
87  sys_err_down_table = np.load(sys_down[n])
88  for j, ybin in enumerate(bins_phi):
89  for i, xbin in enumerate(bins_theta):
90  weightInfo = {}
91  weightInfo["Weight"] = value[i, j]
92  weightInfo["StatErrUp"] = stat_err_up_table[i, j]
93  weightInfo["StatErrDown"] = stat_err_down_table[i, j]
94  weightInfo["SystErrUp"] = sys_err_up_table[i, j]
95  weightInfo["SystErrDown"] = sys_err_down_table[i, j]
96  weightInfo["TotalErrUp"] = (sys_err_up_table[i, j]**2 + stat_err_up_table[i, j]**2)**0.5
97  weightInfo["TotalErrDown"] = (sys_err_down_table[i, j]**2 + stat_err_down_table[i, j]**2)**0.5
98  table.append([weightInfo, make_3D_bin(xbin, ybin, pbin)])
99 
100 # And of course let's define out-of-range bin info
101 outOfRangeWeightInfo = {}
102 outOfRangeWeightInfo["Weight"] = np.nan
103 outOfRangeWeightInfo["StatErrUp"] = np.nan
104 outOfRangeWeightInfo["SystErrUp"] = np.nan
105 outOfRangeWeightInfo["StatErrDown"] = np.nan
106 outOfRangeWeightInfo["SystErrDown"] = np.nan
107 outOfRangeWeightInfo["TotalErrDown"] = np.nan
108 outOfRangeWeightInfo["TotalErrDown"] = np.nan
109 
110 # Now, let's configure table creator
111 addtable = b2.register_module('ParticleWeightingLookUpCreator')
112 addtable.param('tableIDNotSpec', table)
113 addtable.param('outOfRangeWeight', outOfRangeWeightInfo)
114 addtable.param('experimentHigh', -1)
115 addtable.param('experimentLow', 0)
116 addtable.param('runHigh', -1)
117 addtable.param('runLow', 0)
118 addtable.param('tableName', "PhotonEfficiencyDataMCRatio_June2021")
119 
120 eventinfosetter = b2.register_module('EventInfoSetter')
121 eventinfosetter.param('evtNumList', [10])
122 eventinfosetter.param('runList', [0])
123 eventinfosetter.param('expList', [0])
124 
125 my_path = b2.create_path()
126 my_path.add_module(addtable)
127 my_path.add_module(eventinfosetter)
128 
129 b2.process(my_path)