Belle II Software  release-05-01-25
eclChargedPidDatabaseImporter.py
1 # !/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 
4 description = """
5 eclChargedPidDatabaseImporter.py :
6 script to perform fits of PDFs for ECL charged PID for different charged particle hypotheses,
7 and create a (local) DB payload.
8 """
9 
10 __author__ = "Marco Milesi"
11 __email__ = "marco.milesi@unimelb.edu.au"
12 __maintainer__ = "Marco Milesi"
13 __date__ = "June 2018"
14 
15 import os
16 import sys
17 import array
18 import glob
19 import argparse
20 
21 # NB: do NOT modify these lists, unless you really know what you're doing!
22 g_hypotheses = [11, -11, 13, -13, 211, -211, 321, -321, 2212, -2212]
23 
24 parser = argparse.ArgumentParser(description=description)
25 
26 parser.add_argument("inputpath",
27  metavar="inputpath",
28  type=str,
29  help="Path to the directory where input histograms are stored.")
30 parser.add_argument("--noDB",
31  dest="noDB",
32  action="store_true",
33  default=False,
34  help="Do not create DB payload. Just for debugging.")
35 parser.add_argument("-or", "--outputROOT",
36  dest="outputROOT",
37  action="store",
38  default="",
39  help="Create an output ROOT file with the PDFs at the path given. Useful for debugging.")
40 parser.add_argument("-op", "--outputplots",
41  dest="outputplots",
42  action="store",
43  default="",
44  help="Create plots for the fits in pdf format at the path given.")
45 
46 args = parser.parse_args()
47 
48 import ROOT
49 
50 # Silence ROOT!
51 ROOT.gROOT.SetBatch(True)
52 ROOT.gErrorIgnoreLevel = ROOT.kWarning
53 # Silence RooFit!
54 ROOT.RooMsgService.instance().setGlobalKillBelow(ROOT.RooFit.WARNING)
55 ROOT.RooMsgService.instance().setSilentMode(True)
56 
57 from electrons_pdf import fit_electron_eop
58 from muons_pdf import fit_muon_eop
59 from pions_pdf import fit_pion_eop
60 from kaons_pdf import fit_kaon_eop
61 from protons_pdf import fit_proton_eop
62 
63 if __name__ == "__main__":
64 
65  # Create a DB payload for ECL charged PID PDFs.
66  payload = ROOT.Belle2.ECLChargedPidPDFs()
67 
68  # Create a 2D grid w/ the PDF binning to be stored in the DB payload.
69  # row idx (vary along Y axis) : i --> p
70  # column idx (vary along X axis) : j --> theta
71  pmin_vals = [300.0, 400.0, 500.0, 750.0, 1000.0, 1500.0, 2000.0, 3000.0, 4000.0, 4500.0, 5000.0]
72  thetamin_vals = [0.0, 17.0, 31.4, 32.2, 44.0, 117.0, 128.7, 130.7, 150.0]
73 
74  # MUST set the correct units in the payload object,
75  # otherwise the module using the payload will have totally unexpected behaviour!
76  payload.setEnergyUnit(ROOT.Belle2.Unit.MeV)
77  payload.setAngularUnit(ROOT.Belle2.Unit.deg)
78 
79  arr_p = array.array("d", pmin_vals + [5500.0])
80  arr_theta = array.array("d", thetamin_vals + [180.0])
81 
82  histgrid = ROOT.TH2F("binsgrid", "bins grid;#theta_{lab};p_{lab} [MeV/c]", len(thetamin_vals), arr_theta, len(pmin_vals), arr_p)
83  # Fill w/ random stuff gaussianly-distributed. Just cosmetics.
84  xyg = ROOT.TF2("xyg", "xygaus", thetamin_vals[0], 180.0, pmin_vals[0], 5500.0)
85  xyg.SetParameters(10000, 75.0, 65.0, 2500.0, 2000.0)
86  histgrid.FillRandom("xyg", 1000000)
87  histgrid.SetDirectory(0)
88 
89  if args.outputROOT:
90  if not os.path.exists(args.outputROOT):
91  os.makedirs(args.outputROOT)
92 
93  for hypo in g_hypotheses:
94 
95  # Store the TH2F bin grid in the payload instance.
96  payload.setBinsHist(hypo, histgrid)
97 
98  if args.outputROOT:
99  append = "" if hypo > 0 else "anti"
100  outROOT = ROOT.TFile("{0}/pdf_{1}{2}.root".format(args.outputROOT, append, abs(hypo)), "RECREATE")
101  outROOT.cd()
102  histgrid.Write()
103 
104  for ip, pmin in enumerate(pmin_vals, 1):
105 
106  # TEMP
107  # if not ip==5: continue
108 
109  pmax = pmin_vals[ip] if ip <= pmin_vals.index(pmin_vals[-1]) else arr_p[-1]
110 
111  for jth, thetamin in enumerate(thetamin_vals, 1):
112 
113  # TEMP
114  # if not jth==5: continue
115 
116  thetamax = thetamin_vals[jth] if jth <= thetamin_vals.index(thetamin_vals[-1]) else arr_theta[-1]
117 
118  params = {"inputpath": args.inputpath,
119  "pmin": pmin,
120  "pmax": pmax,
121  "idx_p": ip,
122  "thetamin": thetamin,
123  "thetamax": thetamax,
124  "idx_theta": jth,
125  "hypo": hypo,
126  "charge": hypo / abs(hypo), # The fit functions need to know whether we are looking at +/- particles.
127  "outputplots": args.outputplots
128  }
129 
130  print(
131  "Hypothesis: {0},\t{1:.2f} < p < {2:.2f},\t{3:.2f} < theta < {4:.2f}".format(
132  hypo, pmin, pmax, thetamin, thetamax))
133 
134  if abs(hypo) == 11:
135  pdf = fit_electron_eop(**params)
136  elif abs(hypo) == 13:
137  pdf = fit_muon_eop(**params)
138  elif abs(hypo) == 211:
139  pdf = fit_pion_eop(**params)
140  elif abs(hypo) == 321:
141  pdf = fit_kaon_eop(**params)
142  elif abs(hypo) == 2212:
143  pdf = fit_proton_eop(**params)
144 
145  # Store the PDF for this 2D bin in the payload instance.
146  payload.setPDFsInternalMap(hypo, ip, jth, pdf)
147 
148  if args.outputROOT:
149  outROOT.cd()
150  pdf.Write()
151 
152  payload.setPDFsMap(hypo)
153 
154  if not args.noDB:
155  ROOT.Belle2.Database.Instance().storeData("ECLChargedPidPDFs",
156  payload,
157  ROOT.Belle2.IntervalOfValidity.always())