File indexing completed on 2024-09-27 07:02:38
0001 import numpy as np, pandas as pd, matplotlib.pyplot as plt, matplotlib as mpl, awkward as ak, sys, uproot as ur
0002 import mplhep as hep
0003 hep.style.use("CMS")
0004
0005 plt.rcParams['figure.facecolor']='white'
0006 plt.rcParams['savefig.facecolor']='white'
0007 plt.rcParams['savefig.bbox']='tight'
0008
0009 plt.rcParams["figure.figsize"] = (7, 7)
0010 config=sys.argv[1].split("/")[1]
0011 outdir=sys.argv[1]+"/"
0012 try:
0013 import os
0014 os.mkdir(outdir[:-1])
0015 except:
0016 pass
0017
0018
0019 arrays_sim={}
0020 for p in 20,30,40,50,60,70,80:
0021 arrays_sim[p] = ur.open(f'sim_output/insert_neutron/{config}_rec_neutron_{p}GeV.edm4eic.root:events')\
0022 .arrays()
0023
0024 def gauss(x, A,mu, sigma):
0025 return A * np.exp(-(x-mu)**2/(2*sigma**2))
0026
0027
0028 for array in arrays_sim.values():
0029 tilt=-0.025
0030 px=array['MCParticles.momentum.x'][:,2]
0031 py=array['MCParticles.momentum.y'][:,2]
0032 pz=array['MCParticles.momentum.z'][:,2]
0033 p=np.sqrt(px**2+py**2+pz**2)
0034
0035 pxp=px*np.cos(tilt)-pz*np.sin(tilt)
0036 pyp=py
0037 pzp=pz*np.cos(tilt)+px*np.sin(tilt)
0038
0039 array['E_truth']=np.hypot(p, 0.9406)
0040 array['eta_truth']=1/2*np.log((p+pzp)/(p-pzp))
0041 array['theta_truth']=np.arccos(pzp/p)
0042
0043
0044
0045 for array in arrays_sim.values():
0046 tilt=-0.025
0047 x=array['HcalEndcapPInsertClusters.position.x']
0048 y=array['HcalEndcapPInsertClusters.position.y']
0049 z=array['HcalEndcapPInsertClusters.position.z']
0050 E=array['HcalEndcapPInsertClusters.energy']
0051 r=np.sqrt(x**2+y**2+z**2)
0052
0053 xp=x*np.cos(tilt)-z*np.sin(tilt)
0054 yp=y
0055 zp=z*np.cos(tilt)+x*np.sin(tilt)
0056
0057 w=E
0058
0059 array['theta_recon']=np.sum(np.arccos(zp/r)*w, axis=-1)/np.sum(w, axis=-1)
0060 array['eta_recon']=-np.log(np.tan(array['theta_recon']/2))
0061
0062
0063
0064 print("making theta recon plot")
0065 from scipy.optimize import curve_fit
0066
0067 fig, axs=plt.subplots(1,2, figsize=(16,8))
0068 plt.sca(axs[0])
0069 p=40
0070 eta_min=3.4; eta_max=3.6
0071 y,x,_=plt.hist(1000*(arrays_sim[p]['theta_recon']-arrays_sim[p]['theta_truth'])\
0072 [(arrays_sim[p]['eta_truth']>eta_min)&(arrays_sim[p]['eta_truth']<eta_max)], bins=50,
0073 range=(-10,10), histtype='step')
0074 bc=(x[1:]+x[:-1])/2
0075 slc=abs(bc)<3
0076
0077 fnc=gauss
0078 sigma=np.sqrt(y[slc])+(y[slc]==0)
0079 p0=(100, 0, 5)
0080 coeff, var_matrix = curve_fit(fnc, list(bc[slc]), list(y[slc]), p0=p0,sigma=list(sigma))
0081 xx=np.linspace(-5,5,100)
0082 plt.plot(xx,fnc(xx,*coeff))
0083
0084
0085 plt.xlabel("$\\theta_{rec}-\\theta_{truth}$ [mrad]")
0086 plt.ylabel("events")
0087 plt.title(f"$p={p}$ GeV, ${eta_min}<\\eta<{eta_max}$")
0088
0089 r=[3.2,3.4,3.6,3.8,4.0]
0090 for eta_min, eta_max in zip(r[:-1],r[1:]):
0091 xvals=[]
0092 sigmas=[]
0093 dsigmas=[]
0094 for p in 20,30,40, 50, 60, 70, 80:
0095 y,x=np.histogram(1000*(arrays_sim[p]['theta_recon']-arrays_sim[p]['theta_truth'])\
0096 [(arrays_sim[p]['eta_truth']>eta_min)&(arrays_sim[p]['eta_truth']<eta_max)],
0097 bins=50, range=(-10,10))
0098 bc=(x[1:]+x[:-1])/2
0099 slc=abs(bc)<3
0100 fnc=gauss
0101 p0=(100, 0, 5)
0102
0103 sigma=np.sqrt(y[slc])+(y[slc]==0)
0104 try:
0105 coeff, var_matrix = curve_fit(fnc, list(bc[slc]), list(y[slc]), p0=p0,sigma=list(sigma))
0106 sigmas.append(np.abs(coeff[2]))
0107 dsigmas.append(np.sqrt(var_matrix[2][2]))
0108 xvals.append(p)
0109 except:
0110 pass
0111 plt.sca(axs[1])
0112 plt.errorbar(xvals, sigmas, dsigmas, ls='', marker='o', label=f"${eta_min}<\\eta<{eta_max}$")
0113 plt.xlabel("$p_{n}$ [GeV]")
0114 plt.ylabel("$\\sigma[\\theta]$ [mrad]")
0115 plt.ylim(0)
0116 plt.legend()
0117 plt.tight_layout()
0118 plt.savefig(outdir+"neutron_theta_recon.pdf")
0119
0120
0121 pvals=[]
0122 resvals=[]
0123 reserrs=[]
0124 wvals=[]
0125 svals=[]
0126 Euncorr=[]
0127
0128 print("determining the energy recon correction parameters")
0129 fig,axs=plt.subplots(1,2, figsize=(20,10))
0130 eta_min=3.4;eta_max=3.6
0131 for p in 20, 30,40,50,60,70, 80:
0132 best_res=1000
0133 res_err=1000
0134 best_s=1000
0135 wrange=np.linspace(30, 70, 41)*0.0257
0136 coeff_best=None
0137
0138 wbest=0
0139 a=arrays_sim[p]
0140 h=np.sum(a[f'HcalEndcapPInsertClusters.energy'], axis=-1)
0141 e=np.sum(a[f'EcalEndcapPInsertClusters.energy'], axis=-1)
0142 for w in wrange:
0143
0144 r=(e/w+h)[(h>0)&(a['eta_truth']>eta_min)&(a['eta_truth']<eta_max)]
0145 y,x=np.histogram(r,bins=50)
0146 bcs=(x[1:]+x[:-1])/2
0147 fnc=gauss
0148 slc=abs(bcs-np.mean(r)*1.25)<2*np.std(r)
0149 sigma=np.sqrt(y[slc])+0.5*(y[slc]==0)
0150 p0=(100, np.mean(r), np.std(r))
0151 try:
0152 coeff, var_matrix = curve_fit(fnc, list(bcs[slc]), list(y[slc]), p0=p0,sigma=list(sigma))
0153 res=np.abs(coeff[2]/coeff[1])
0154
0155 if res<best_res:
0156 best_res=res
0157 coeff_best=coeff
0158 res_err=res*np.hypot(np.sqrt(var_matrix[2][2])/coeff[2], np.sqrt(var_matrix[1][1])/coeff[1])
0159 wbest=w
0160 best_s=np.hypot(p,0.9406)/coeff[1]
0161 Euncorr_best=coeff[1]
0162 except :
0163 print("fit failed")
0164
0165 if p==50:
0166 r=(e/wbest+h)[(h>0)&(a['eta_truth']>3.4)&(a['eta_truth']<3.6)]
0167 plt.sca(axs[0])
0168 y, x, _= plt.hist(r, histtype='step', bins=50)
0169 xx=np.linspace(20, 55, 100)
0170 plt.plot(xx,fnc(xx, *coeff_best), ls='-')
0171 plt.xlabel("$E_{uncorr}=E_{Hcal}+E_{Ecal}/w$ [GeV]")
0172 plt.title(f"p=50 GeV, ${eta_min}<\\eta<{eta_max}$, w={wbest:.2f}")
0173 plt.axvline(np.sqrt(50**2+.9406**2), color='g', ls=':')
0174 plt.text(40, max(y)*0.9, "generated\nenergy", color='g', fontsize=20)
0175
0176 Euncorr.append(Euncorr_best)
0177 resvals.append(best_res)
0178 reserrs.append(res_err)
0179 pvals.append(p)
0180 svals.append(best_s)
0181 wvals.append(wbest)
0182
0183 pvals=np.array(pvals)
0184 svals=np.array(svals)
0185 Euncorr=np.array(Euncorr)
0186 plt.sca(axs[1])
0187 plt.plot(Euncorr,wvals, label="w")
0188 w_avg=np.mean(wvals)
0189 plt.axhline(w_avg, label=f'w avg: {w_avg:.2f}', ls=':')
0190 plt.plot(Euncorr,svals, label="s")
0191 m=(np.sum(svals*Euncorr)*len(Euncorr)-np.sum(Euncorr)*np.sum(svals))/(np.sum(Euncorr**2)*len(Euncorr)-np.sum(Euncorr)**2)
0192 b=np.mean(svals)-np.mean(Euncorr)*m
0193 plt.plot(Euncorr,Euncorr*m+b, label=f"s fit: ${m:.4f}E_{{uncorr}}+{b:.2f}$", ls=':')
0194
0195 plt.xlabel("$E_{uncorr}=E_{Hcal}+E_{Ecal}/w$ [GeV]")
0196 plt.title("$E_{n,recon}=s\\times(E_{Hcal}+E_{Ecal}/w)$")
0197 plt.ylabel('parameter values')
0198 plt.legend()
0199 plt.ylim(0)
0200 plt.savefig(outdir+"neutron_energy_params.pdf")
0201
0202
0203 print("making energy recon plot")
0204 fig, axs=plt.subplots(1,3, figsize=(24,8))
0205 partitions=[3.2,3.4, 3.6, 3.8, 4.0]
0206 for eta_min, eta_max in zip(partitions[:-1],partitions[1:]):
0207 pvals=[]
0208 resvals=[]
0209 reserrs=[]
0210 scalevals=[]
0211 scaleerrs=[]
0212 for p in 20, 30,40,50,60,70, 80:
0213 best_res=1000
0214 res_err=1000
0215
0216
0217 wrange=np.linspace(30, 70, 30)*0.0257
0218
0219 w=w_avg
0220 a=arrays_sim[p]
0221 h=np.sum(a[f'HcalEndcapPInsertClusters.energy'], axis=-1)
0222 e=np.sum(a[f'EcalEndcapPInsertClusters.energy'], axis=-1)
0223
0224 uncorr=(e/w+h)
0225 s=-0.0064*uncorr+1.80
0226 r=uncorr*s
0227 r=r[(h>0)&(a['eta_truth']>eta_min)&(a['eta_truth']<eta_max)]
0228 y,x=np.histogram(r,bins=50)
0229 bcs=(x[1:]+x[:-1])/2
0230 fnc=gauss
0231 slc=abs(bcs-np.mean(r)*1.25)<2*np.std(r)
0232 sigma=np.sqrt(y[slc])+0.5*(y[slc]==0)
0233 p0=(100, np.mean(r), np.std(r))
0234 try:
0235 coeff, var_matrix = curve_fit(fnc, list(bcs[slc]), list(y[slc]), p0=p0,sigma=list(sigma))
0236 res=np.abs(coeff[2]/coeff[1])
0237
0238 if res<best_res:
0239 best_res=res
0240 res_err=res*np.hypot(np.sqrt(var_matrix[2][2])/coeff[2], np.sqrt(var_matrix[1][1])/coeff[1])
0241 wbest=w
0242 scale=coeff[1]/np.sqrt(p**2+0.9406**2)
0243 dscale=np.sqrt(var_matrix[1][1]/np.sqrt(p**2+0.9406**2))
0244 except :
0245 print("fit failed")
0246 if p==50 and eta_min==3.4:
0247 plt.sca(axs[0])
0248 plt.errorbar(bcs, y, np.sqrt(y)+(y==0),marker='o', ls='', )
0249 plt.title(f'p={p} GeV, ${eta_min}<\\eta<{eta_max}$')
0250 plt.xlabel("$E_{recon}$ [GeV]")
0251 plt.ylabel("events")
0252
0253 xx=np.linspace(40, 70, 50)
0254 plt.plot(xx, fnc(xx, *coeff))
0255 resvals.append(best_res)
0256 reserrs.append(res_err)
0257 scalevals.append(scale)
0258 scaleerrs.append(dscale)
0259 pvals.append(p)
0260 plt.sca(axs[1])
0261 plt.errorbar(pvals, resvals, reserrs, marker='o', ls='', label=f"${eta_min}<\\eta<{eta_max}$")
0262
0263 plt.ylabel("$\\sigma[E]/\\mu[E]$")
0264 plt.xlabel("$p_{n}$ [GeV]")
0265
0266 plt.sca(axs[2])
0267 plt.errorbar(pvals, scalevals, scaleerrs, marker='o', ls='', label=f"${eta_min}<\\eta<{eta_max}$")
0268
0269
0270 plt.ylabel("$\\mu[E]/E$")
0271
0272
0273 axs[2].set_xlabel("$p_n$ [GeV]")
0274 axs[2].axhline(1, ls='--', color='0.5', alpha=0.7)
0275 axs[0].set_ylim(0)
0276 axs[1].set_ylim(0, 0.35)
0277 axs[2].set_ylim(0)
0278 axs[1].legend()
0279 axs[2].legend()
0280 plt.tight_layout()
0281 plt.savefig(outdir+"neutron_energy_recon.pdf")