File indexing completed on 2026-03-28 08:36:10
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 import argparse as ap
0024 import ROOT
0025 import numpy as np
0026
0027 from podio.reading import get_reader
0028
0029
0030 IFileDefault = "root://dtn-eic.jlab.org//volatile/eic/EPIC/RECO/25.10.4/epic_craterlake/DIS/pythia6.428-1.0/NC/noRad/ep/10x130/q2_10to100/pythia6.428-1.0_NC_noRad_ep_10x130_q2_10to100_ab.0625.eicrecon.edm4eic.root"
0031 OFileDefault = "test_podio.root"
0032
0033
0034 def Calculate(
0035 ifile = IFileDefault,
0036 ofile = OFileDefault,
0037 ):
0038 """Calculate JES/R
0039
0040 Calculate JES/R for a collection of jets. Excludes
0041 any generator-level jets with electrons to avoid
0042 DIS electron.
0043
0044 Args:
0045 ifile: input file produced by EICrecon
0046 ofile: output file
0047 Returns:
0048 tuple of the JES and JER
0049 """
0050
0051
0052 reader = get_reader(ifile)
0053 print("\n Starting calculation:")
0054 print(f" input = {ifile}")
0055 print(f" output = {ofile}")
0056
0057
0058 hres = ROOT.TH1D("hEneResPODIO", ";(E_{jet}^{rec} - E_{jet}^{gen}) / E_{jet}^{gen}", 50, -2., 3.)
0059 hres.Sumw2()
0060
0061 nframes = len(reader.get("events"))
0062 print(f" Starting event loop, {nframes} events to process.")
0063
0064
0065 for iframe, frame in enumerate(reader.get("events")):
0066
0067
0068 if (iframe % 100 == 0):
0069 print(f" Processing event {iframe + 1}/{nframes}...")
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079 gen_jets = frame.get("GeneratedChargedJets")
0080 rec_jets = frame.get("ReconstructedChargedJets")
0081
0082
0083 for gjet in gen_jets:
0084
0085
0086 gpt = np.sqrt((gjet.getMomentum().x**2) + (gjet.getMomentum().y**2))
0087 gphi = np.arctan2(gjet.getMomentum().y, gjet.getMomentum().x)
0088 gtheta = np.arctan2(gpt, gjet.getMomentum().z)
0089 geta = -np.log(np.tan(gtheta/2))
0090
0091
0092
0093 if gjet.getEnergy() < 5:
0094 continue
0095
0096
0097
0098
0099 if np.abs(geta) > 2.5:
0100 continue
0101
0102
0103
0104 has_electron = False
0105 for gcst in gjet.getParticles():
0106 if gcst.getPDG() == 11:
0107 has_electron = True
0108 break
0109
0110 if has_electron:
0111 continue
0112
0113
0114
0115 match = None
0116 min_dist = 9999.
0117 for rjet in rec_jets:
0118
0119
0120 rpt = np.sqrt((rjet.getMomentum().x**2) + (rjet.getMomentum().y**2))
0121 rphi = np.arctan2(rjet.getMomentum().y, rjet.getMomentum().x)
0122 rtheta = np.arctan2(rpt, rjet.getMomentum().z)
0123 reta = -np.log(np.tan(rtheta/2))
0124
0125
0126
0127 deta = reta - geta
0128 dphi = rphi - gphi
0129 dist = np.sqrt((deta**2) + (dphi**2))
0130
0131
0132 if dist > 0.05:
0133 continue
0134
0135
0136 if dist < min_dist:
0137 match = rjet
0138 min_dist = dist
0139
0140
0141 if match is None:
0142 continue
0143
0144
0145 eres = (match.getEnergy() - gjet.getEnergy())/gjet.getEnergy()
0146 hres.Fill(eres)
0147
0148
0149 fres = ROOT.TF1("fEneRes", "gaus(0)", -0.5, 0.5)
0150 fres.SetParameter(0, hres.Integral())
0151 fres.SetParameter(1, hres.GetMean())
0152 fres.SetParameter(2, hres.GetRMS())
0153 hres.Fit(fres, "r")
0154 JES = fres.GetParameter(1) + 1
0155 JER = fres.GetParameter(2)
0156 print(f" Finished event loop:")
0157 print(f" JES = {JES}, JER = {JER}")
0158
0159
0160 with ROOT.TFile(ofile, "recreate") as ofile:
0161 ofile.WriteObject(hres, "hEneResPODIO")
0162 ofile.Close()
0163
0164 print(" Finished calculation!\n")
0165 return (JES, JER)
0166
0167
0168
0169
0170 if __name__ == "__main__":
0171
0172
0173 parser = ap.ArgumentParser()
0174 parser.add_argument(
0175 "-i",
0176 "--input",
0177 help = "Input file",
0178 nargs = '?',
0179 const = IFileDefault,
0180 default = IFileDefault,
0181 type = str
0182 )
0183 parser.add_argument(
0184 "-o",
0185 "--output",
0186 help = "Output file",
0187 nargs = '?',
0188 const = OFileDefault,
0189 default = OFileDefault,
0190 type = str
0191 )
0192 args = parser.parse_args()
0193
0194
0195 Calculate(args.input, args.output)
0196
0197