Skip to content
Snippets Groups Projects
Unverified Commit 9a878fba authored by Sebouh Paul's avatar Sebouh Paul Committed by GitHub
Browse files

Update the neutron benchmark plots (#27)

* Update neutron_plots.py

import uproot as ur

* fixed another bug in the neutron_plots.py

* different fit for the neutron energy corrections; also add YR requirements

* removed YR requirements from neutron plots; also used a different energy correction formula
parent a2cbe912
No related branches found
No related tags found
No related merge requests found
Pipeline #101463 passed
...@@ -21,7 +21,6 @@ for p in 20,30,40,50,60,70,80: ...@@ -21,7 +21,6 @@ for p in 20,30,40,50,60,70,80:
arrays_sim[p] = ur.open(f'sim_output/neutron/{config}_rec_neutron_{p}GeV.edm4hep.root:events')\ arrays_sim[p] = ur.open(f'sim_output/neutron/{config}_rec_neutron_{p}GeV.edm4hep.root:events')\
.arrays() .arrays()
#get reconstructed theta, eta, and E
def gauss(x, A,mu, sigma): def gauss(x, A,mu, sigma):
return A * np.exp(-(x-mu)**2/(2*sigma**2)) return A * np.exp(-(x-mu)**2/(2*sigma**2))
...@@ -41,7 +40,8 @@ for array in arrays_sim.values(): ...@@ -41,7 +40,8 @@ for array in arrays_sim.values():
array['eta_truth']=1/2*np.log((p+pzp)/(p-pzp)) array['eta_truth']=1/2*np.log((p+pzp)/(p-pzp))
array['theta_truth']=np.arccos(pzp/p) array['theta_truth']=np.arccos(pzp/p)
#weighted avg of theta of cluster centers, by energy #
# get reconstructed theta as avg of theta of cluster centers, weighted by energy
for array in arrays_sim.values(): for array in arrays_sim.values():
tilt=-0.025 tilt=-0.025
x=array['HcalEndcapPInsertClusters.position.x'] x=array['HcalEndcapPInsertClusters.position.x']
...@@ -59,14 +59,9 @@ for array in arrays_sim.values(): ...@@ -59,14 +59,9 @@ for array in arrays_sim.values():
array['theta_recon']=np.sum(np.arccos(zp/r)*w, axis=-1)/np.sum(w, axis=-1) array['theta_recon']=np.sum(np.arccos(zp/r)*w, axis=-1)/np.sum(w, axis=-1)
array['eta_recon']=-np.log(np.tan(array['theta_recon']/2)) array['eta_recon']=-np.log(np.tan(array['theta_recon']/2))
array['E_Hcal']=np.sum(array['HcalEndcapPInsertClusters.energy'], axis=-1)#*20/12.5
array['E_Ecal']=np.sum(array['EcalEndcapPInsertClusters.energy'], axis=-1)#*27/20
array['E_recon']=array['E_Hcal']/(0.70-.30/np.sqrt(array['E_Hcal']))\
+array['E_Ecal']/(0.82-0.35/np.sqrt(array['E_Ecal']))
#plot theta residuals: #plot theta residuals:
print("making theta recon plot")
from scipy.optimize import curve_fit from scipy.optimize import curve_fit
fig, axs=plt.subplots(1,2, figsize=(16,8)) fig, axs=plt.subplots(1,2, figsize=(16,8))
...@@ -91,7 +86,7 @@ plt.xlabel("$\\theta_{rec}-\\theta_{truth}$ [mrad]") ...@@ -91,7 +86,7 @@ plt.xlabel("$\\theta_{rec}-\\theta_{truth}$ [mrad]")
plt.ylabel("events") plt.ylabel("events")
plt.title(f"$p={p}$ GeV, ${eta_min}<\\eta<{eta_max}$") plt.title(f"$p={p}$ GeV, ${eta_min}<\\eta<{eta_max}$")
r=[3.0,3.2,3.4,3.6,3.8] r=[3.2,3.4,3.6,3.8,4.0]
for eta_min, eta_max in zip(r[:-1],r[1:]): for eta_min, eta_max in zip(r[:-1],r[1:]):
xvals=[] xvals=[]
sigmas=[] sigmas=[]
...@@ -122,54 +117,165 @@ plt.legend() ...@@ -122,54 +117,165 @@ plt.legend()
plt.tight_layout() plt.tight_layout()
plt.savefig(outdir+"neutron_theta_recon.pdf") plt.savefig(outdir+"neutron_theta_recon.pdf")
fig, axs=plt.subplots(1,2, figsize=(16,8)) #now determine the energy recon parameters
plt.sca(axs[0]) pvals=[]
p=50 resvals=[]
eta_min=3.4; eta_max=3.6 reserrs=[]
y,x,_=plt.hist(((arrays_sim[p]['E_recon']-arrays_sim[p]['E_truth'])/arrays_sim[p]['E_truth'])\ wvals=[]
[(arrays_sim[p]['eta_truth']>eta_min)&(arrays_sim[p]['eta_truth']<eta_max)&(arrays_sim[p]['E_Hcal']>0)], bins=50, svals=[]
range=(-.5,.5), histtype='step') Euncorr=[]
bc=(x[1:]+x[:-1])/2
slc=abs(bc)<0.4
# try:
p0=(100, 0, 0.3)
fnc=gauss
sigma=np.sqrt(y[slc])+(y[slc]==0)
coeff, var_matrix = curve_fit(fnc, list(bc[slc]), list(y[slc]), p0=p0,sigma=list(sigma))
xx=np.linspace(-.5,.5,100)
plt.plot(xx,fnc(xx,*coeff))
# except:
# pass
plt.xlabel("$(E_{rec}-E_{truth})/E_{truth}$")
plt.ylabel("events")
plt.title(f"$p={p}$ GeV, ${eta_min}<\\eta<{eta_max}$")
r=[3.0,3.2,3.4,3.6,3.8] print("determining the energy recon correction parameters")
for eta_min, eta_max in zip(r[:-1],r[1:]): fig,axs=plt.subplots(1,2, figsize=(20,10))
xvals=[] eta_min=3.4;eta_max=3.6
sigmas=[] for p in 20, 30,40,50,60,70, 80:
dsigmas=[] best_res=1000
for p in 20,30,40, 50, 60, 70, 80: res_err=1000
y,x=np.histogram(((arrays_sim[p]['E_recon']-arrays_sim[p]['E_truth'])/arrays_sim[p]['E_truth'])\ best_s=1000
[(arrays_sim[p]['eta_truth']>eta_min)&(arrays_sim[p]['eta_truth']<eta_max)], bins=50, range=(-.5,.5)) wrange=np.linspace(30, 70, 41)*0.0257
bc=(x[1:]+x[:-1])/2 coeff_best=None
slc=abs(bc)<0.5
wbest=0
a=arrays_sim[p]
h=np.sum(a[f'HcalEndcapPInsertClusters.energy'], axis=-1)
e=np.sum(a[f'EcalEndcapPInsertClusters.energy'], axis=-1)
for w in wrange:
r=(e/w+h)[(h>0)&(a['eta_truth']>eta_min)&(a['eta_truth']<eta_max)]
y,x=np.histogram(r,bins=50)
bcs=(x[1:]+x[:-1])/2
fnc=gauss fnc=gauss
p0=(100, 0, 0.3) slc=abs(bcs-np.mean(r)*1.25)<2*np.std(r)
#print(bc[slc],y[slc]) sigma=np.sqrt(y[slc])+0.5*(y[slc]==0)
sigma=np.sqrt(y[slc])+(y[slc]==0) p0=(100, np.mean(r), np.std(r))
try: try:
coeff, var_matrix = curve_fit(fnc, list(bc[slc]), list(y[slc]), p0=p0,sigma=list(sigma)) coeff, var_matrix = curve_fit(fnc, list(bcs[slc]), list(y[slc]), p0=p0,sigma=list(sigma))
sigmas.append(np.abs(coeff[2])) res=np.abs(coeff[2]/coeff[1])
dsigmas.append(np.sqrt(var_matrix[2][2]))
xvals.append(p) if res<best_res:
except: best_res=res
pass coeff_best=coeff
plt.sca(axs[1]) res_err=res*np.hypot(np.sqrt(var_matrix[2][2])/coeff[2], np.sqrt(var_matrix[1][1])/coeff[1])
plt.errorbar(xvals, sigmas, dsigmas, ls='', marker='o', label=f"${eta_min}<\\eta<{eta_max}$") wbest=w
plt.xlabel("$p_{n}$ [GeV]") best_s=np.hypot(p,0.9406)/coeff[1]
plt.ylabel("$\\sigma[E]/E$") Euncorr_best=coeff[1]
plt.ylim(0) except :
print("fit failed")
if p==50:
r=(e/wbest+h)[(h>0)&(a['eta_truth']>3.4)&(a['eta_truth']<3.6)]
plt.sca(axs[0])
y, x, _= plt.hist(r, histtype='step', bins=50)
xx=np.linspace(20, 55, 100)
plt.plot(xx,fnc(xx, *coeff_best), ls='-')
plt.xlabel("$E_{uncorr}=E_{Hcal}+E_{Ecal}/w$ [GeV]")
plt.title(f"p=50 GeV, ${eta_min}<\\eta<{eta_max}$, w={wbest:.2f}")
plt.axvline(np.sqrt(50**2+.9406**2), color='g', ls=':')
plt.text(40, max(y)*0.9, "generated\nenergy", color='g', fontsize=20)
Euncorr.append(Euncorr_best)
resvals.append(best_res)
reserrs.append(res_err)
pvals.append(p)
svals.append(best_s)
wvals.append(wbest)
pvals=np.array(pvals)
svals=np.array(svals)
Euncorr=np.array(Euncorr)
plt.sca(axs[1])
plt.plot(Euncorr,wvals, label="w")
w_avg=np.mean(wvals)
plt.axhline(w_avg, label=f'w avg: {w_avg:.2f}', ls=':')
plt.plot(Euncorr,svals, label="s")
m=(np.sum(svals*Euncorr)*len(Euncorr)-np.sum(Euncorr)*np.sum(svals))/(np.sum(Euncorr**2)*len(Euncorr)-np.sum(Euncorr)**2)
b=np.mean(svals)-np.mean(Euncorr)*m
plt.plot(Euncorr,Euncorr*m+b, label=f"s fit: ${m:.4f}E_{{uncorr}}+{b:.2f}$", ls=':')
plt.xlabel("$E_{uncorr}=E_{Hcal}+E_{Ecal}/w$ [GeV]")
plt.title("$E_{n,recon}=s\\times(E_{Hcal}+E_{Ecal}/w)$")
plt.ylabel('parameter values')
plt.legend() plt.legend()
plt.ylim(0)
plt.savefig(outdir+"neutron_energy_params.pdf")
#now make the energy plot
print("making energy recon plot")
fig, axs=plt.subplots(1,3, figsize=(24,8))
partitions=[3.2,3.4, 3.6, 3.8, 4.0]
for eta_min, eta_max in zip(partitions[:-1],partitions[1:]):
pvals=[]
resvals=[]
reserrs=[]
scalevals=[]
scaleerrs=[]
for p in 20, 30,40,50,60,70, 80:
best_res=1000
res_err=1000
wrange=np.linspace(30, 70, 30)*0.0257
w=w_avg
a=arrays_sim[p]
h=np.sum(a[f'HcalEndcapPInsertClusters.energy'], axis=-1)
e=np.sum(a[f'EcalEndcapPInsertClusters.energy'], axis=-1)
#phi=a['phi_truth']
uncorr=(e/w+h)
s=-0.0064*uncorr+1.80
r=uncorr*s #reconstructed energy with correction
r=r[(h>0)&(a['eta_truth']>eta_min)&(a['eta_truth']<eta_max)]#&(abs(phi)>np.pi/2)]
y,x=np.histogram(r,bins=50)
bcs=(x[1:]+x[:-1])/2
fnc=gauss
slc=abs(bcs-np.mean(r)*1.25)<2*np.std(r)
sigma=np.sqrt(y[slc])+0.5*(y[slc]==0)
p0=(100, np.mean(r), np.std(r))
try:
coeff, var_matrix = curve_fit(fnc, list(bcs[slc]), list(y[slc]), p0=p0,sigma=list(sigma))
res=np.abs(coeff[2]/coeff[1])
if res<best_res:
best_res=res
res_err=res*np.hypot(np.sqrt(var_matrix[2][2])/coeff[2], np.sqrt(var_matrix[1][1])/coeff[1])
wbest=w
scale=coeff[1]/np.sqrt(p**2+0.9406**2)
dscale=np.sqrt(var_matrix[1][1]/np.sqrt(p**2+0.9406**2))
except :
print("fit failed")
if p==50 and eta_min==3.4:
plt.sca(axs[0])
plt.errorbar(bcs, y, np.sqrt(y)+(y==0),marker='o', ls='', )
plt.title(f'p={p} GeV, ${eta_min}<\\eta<{eta_max}$')
plt.xlabel("$E_{recon}$ [GeV]")
plt.ylabel("events")
#plt.ylim(0)
xx=np.linspace(40, 70, 50)
plt.plot(xx, fnc(xx, *coeff))
resvals.append(best_res)
reserrs.append(res_err)
scalevals.append(scale)
scaleerrs.append(dscale)
pvals.append(p)
plt.sca(axs[1])
plt.errorbar(pvals, resvals, reserrs, marker='o', ls='', label=f"${eta_min}<\\eta<{eta_max}$")
#plt.ylim(0)
plt.ylabel("$\\sigma[E]/\\mu[E]$")
plt.xlabel("$p_{n}$ [GeV]")
plt.sca(axs[2])
plt.errorbar(pvals, scalevals, scaleerrs, marker='o', ls='', label=f"${eta_min}<\\eta<{eta_max}$")
plt.ylabel("$\\mu[E]/E$")
axs[2].set_xlabel("$p_n$ [GeV]")
axs[2].axhline(1, ls='--', color='0.5', alpha=0.7)
axs[0].set_ylim(0)
axs[1].set_ylim(0, 0.35)
axs[2].set_ylim(0)
axs[1].legend()
axs[2].legend()
plt.tight_layout() plt.tight_layout()
plt.savefig(outdir+"neutron_energy_recon.pdf") plt.savefig(outdir+"neutron_energy_recon.pdf")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment