def mean_poisson_pval(d, b, b_error, conv_width=3, step_size=1): """ Mostly transcribed from https://svnweb.cern.ch/trac/atlasoff/browser/Trigger/TrigFTK/SuPlot/trunk/src/bumphunter/StatisticsAnalysis.C (including the docstring) Convolve a Gaussian (non-negative part) with a Poisson. Background is b+-b_error, and we need the mean Poisson probability to observe at least d (if d >=b, else at most d), given this PDF for b. The way is to cut the PDF or b into segments, whose area is exactly calculable, take the Poisson probability at the center of each gaussian slice, and average the probabilities using the area of each slice as weight. But here, currently, we are guaranteed to have d > b so some of this simplifies. d - data counts b - background counts b_error - error in bkg counts conv_width - range of l in convolution loop (I think this is how many sigmas of to convolve) step_size - step size for convolution TODO: I think there might be a better way to do this using ROOT.TMath """ if b_error == 0: return TMath.Gamma(d, b) # Guaranteed to have d > b, so this is equivalent to commonFunctions.h:503 # TODO: Pythonify the following mean, total_weight = 0.0, 0.0 l = -conv_width while l <= conv_width: bcenter = max(0, b + l*b_error) this_slice_weight = Math.normal_cdf(l + 0.5*step_size) - Math.normal_cdf(l - 0.5*step_size) this_pval = poisson_pval(d, bcenter) mean += this_pval*this_slice_weight total_weight += this_slice_weight l += step_size return mean / total_weight
def poisson_pval(d, b): """ Two sided only """ return TMath.Gamma(d, b) if d >= b else 1 - TMath.Gamma(d+1, b)
def func_nkg_ind_show(x,par): #//NKG function for fitting 3 parameters: (Ne,rM,s) return (par[0]/np.power(par[1],2))*(TMath.Gamma(4.5-par[2]))/(2*np.pi*(TMath.Gamma(par[2]))*(TMath.Gamma(4.5-2*par[2])))*np.power(x[0]/par[1],par[2]-2)*np.power(1.0+x[0]/par[1],par[2]-4.5)
def fit_NKG(detectors,event): print('fit core position') # directions for fitting theta=(event.fit_theta)*np.pi/180.0 phi=(90.0+360.0-event.fit_theta)*np.pi/180.0 #Northward (anticlockwise) from East (X-axis) psi=2*np.pi-phi x_shower=np.zeros([LORA.nDetA]) y_shower=np.zeros([LORA.nDetA]) x_pos=np.zeros([LORA.nDetA]) y_pos=np.zeros([LORA.nDetA]) z_shower=np.zeros([LORA.nDetA]) temp_det_array=[] temp_den_array=[] temp_x_pos=[] temp_y_pos=[] # find core position in shower plane for first guess for fit. 4 densest detectors are used for i in np.arange(LORA.nDetA): x_shower[i],y_shower[i],z_shower[i]=theta_phi(theta,phi,psi,detectors[i].x_cord,detectors[i].y_cord,detectors[i].z_cord) x_pos[i]=detectors[i].x_cord y_pos[i]=detectors[i].y_cord if detectors[i].density>=LORA.Density_Cut and detectors[i].density<=LORA.Density_Cut_High: temp_den_array.append(detectors[i].density) temp_det_array.append(i) temp_x_pos.append(x_shower[i]) temp_y_pos.append(x_shower[i]) ind=np.argsort(np.asarray(temp_den_array))[::-1] temp_den_array=np.asarray(temp_den_array) temp_det_array=np.asarray(temp_det_array) temp_x_array=np.asarray(temp_x_pos) temp_y_array=np.asarray(temp_y_pos) temp_total_den=temp_den_array[ind[0]]+temp_den_array[ind[1]]+temp_den_array[ind[2]]+temp_den_array[ind[3]] x_core=(x_shower[temp_det_array[ind[0]]]*temp_den_array[ind[0]]+x_shower[temp_det_array[ind[1]]]*temp_den_array[ind[1]]+x_shower[temp_det_array[ind[2]]]*temp_den_array[ind[2]]+x_shower[temp_det_array[ind[3]]]*temp_den_array[ind[3]])/temp_total_den y_core=(y_shower[temp_det_array[ind[0]]]*temp_den_array[ind[0]]+y_shower[temp_det_array[ind[1]]]*temp_den_array[ind[1]]+y_shower[temp_det_array[ind[2]]]*temp_den_array[ind[2]]+y_shower[temp_det_array[ind[3]]]*temp_den_array[ind[3]])/temp_total_den # find min/max detector positions nBinsX=int(((np.max(x_pos)+10)-(np.min(x_pos)-10))/LORA.Bin_Size_X) nBinsY=int(((np.max(y_pos)+10)-(np.min(y_pos)-10))/LORA.Bin_Size_Y) x_min=(np.min(x_pos)-10) x_max=(np.max(x_pos)+10) y_min=(np.min(y_pos)-10) y_max=(np.max(y_pos)+10) nBinsX_shower=int(((np.max(x_shower)+10)-(np.min(x_shower)-10))/LORA.Bin_Size_X) nBinsY_shower=int(((np.max(y_shower)+10)-(np.min(y_shower)-10))/LORA.Bin_Size_Y) x_min_shower=(np.min(x_shower)-150) x_max_shower=(np.max(x_shower)+150) y_min_shower=(np.min(y_shower)-150) y_max_shower=(np.max(y_shower)+150) evt_display = TH2F('Event','Event',nBinsX,x_min,x_max,nBinsY,y_min,y_max) # ground plane evt_display_shower = TH2F('Event_shower','Event_shower',nBinsX_shower,x_min_shower,x_max_shower,nBinsY_shower,y_min_shower,y_max_shower) # shower plane lat_den_show=TH1F('Lateral_density','Lateral_density',LORA.No_Bin_R,LORA.min_R,LORA.max_R) time_display = TH2F('time','time',nBinsX,x_min,x_max,nBinsY,y_min,y_max) #ground plane rho=np.zeros([LORA.nDetA]) rho_shower=np.zeros([LORA.nDetA]) rho_err=np.zeros([LORA.nDetA]) nDet_triggered=0 f_den=0 shower_size=0 for i in np.arange(LORA.nDetA): rho[i]=detectors[i].density rho_err[i]=detectors[i].err_density if rho[i]>=LORA.Density_Cut and rho[i]<=LORA.Density_Cut_High: nDet_triggered=nDet_triggered+1 evt_display.SetBinContent(evt_display.GetXaxis().FindBin(x_pos[i]),evt_display.GetYaxis().FindBin(y_pos[i]),rho[i]) evt_display_shower.SetBinContent(evt_display_shower.GetXaxis().FindBin(x_shower[i]),evt_display_shower.GetYaxis().FindBin(y_shower[i]),rho[i]) f_den=f_den+(1.0/np.power(LORA.rM,2))*(TMath.Gamma(4.5-LORA.Age))/(2*np.pi*(TMath.Gamma(1.0))*(TMath.Gamma(4.5-2*LORA.Age)))*np.power(np.sqrt(np.power(x_core-x_shower[i],2)+np.power(y_core-y_shower[i],2))/LORA.rM,LORA.Age-2)*np.power(1.0+np.sqrt(np.power(x_core-x_shower[i],2)+np.power(y_core-y_shower[i],2))/LORA.rM,(LORA.Age-4.5)) shower_size=shower_size+rho[i] # first iteration of fit -> doing Ne, xcore, ycore Ne_fit,rM_fit,s_fit,x_core_fit,y_core_fit,x_core_fit_err,y_core_fit_err, corr_coef_xy=TF2_Fit_NKG(evt_display_shower,shower_size/f_den,LORA.rM,LORA.Age,x_core,y_core,x_min_shower,x_max_shower,y_min_shower,y_max_shower) print('x: {0:.2f} -> {1:.2f}'.format(x_core, x_core_fit)) print('y: {0:.2f} -> {1:.2f}'.format(y_core, y_core_fit)) #print 'Ne: {0:.2f} -> {1:.2f}'.format(shower_size/f_den, Ne_fit) R_Max=0 R_Min=1000000 radius_show=np.zeros([LORA.nDetA]) radius_bin_show=np.zeros([LORA.nDetA]) for i in np.arange(LORA.nDetA): if rho[i]>=LORA.Density_Cut and rho[i]<=LORA.Density_Cut_High: radius_show[i]=np.abs(np.sqrt(np.power(x_core_fit-x_shower[i],2)+np.power(y_core_fit-y_shower[i],2))) radius_bin_show[i]=lat_den_show.FindBin(radius_show[i]) if radius_show[i]>R_Max: R_Max=radius_show[i] if radius_show[i]<R_Min: R_Min=radius_show[i] lat_den_show.SetBinContent(int(radius_bin_show[i]),rho[i]) lat_den_show.SetBinError(int(radius_bin_show[i]),rho_err[i]) Ne_fit,rM_fit,s_fit,Ne_fit_er=TF1_Fit_NKG(lat_den_show,Ne_fit,LORA.rM,LORA.Age,R_Min,R_Max) print('Ne: {0:.2f}, Rm: {1:.2f}, xCore: {2:.2f}, yCore: {3:.2f}'.format(Ne_fit, rM_fit,x_core_fit, y_core_fit)) # iterate 2d, 1d fits for k in np.arange(4): del lat_den_show lat_den_show=TH1F('Lateral_density','Lateral_density',LORA.No_Bin_R,LORA.min_R,LORA.max_R) Ne_fit,rM_fit,s_fit,x_core_fit,y_core_fit,x_core_fit_err,y_core_fit_err,corr_coef_xy=TF2_Fit_NKG(evt_display_shower,Ne_fit,rM_fit,s_fit,x_core_fit,y_core_fit,x_min_shower,x_max_shower,y_min_shower,y_max_shower) R_Max=0 R_Min=1000000 for i in np.arange(LORA.nDetA): if rho[i]>=LORA.Density_Cut and rho[i]<=LORA.Density_Cut_High: radius_show[i]=np.abs(np.sqrt(np.power(x_core_fit-x_shower[i],2)+np.power(y_core_fit-y_shower[i],2))) radius_bin_show[i]=lat_den_show.FindBin(radius_show[i]) if radius_show[i]>R_Max: R_Max=radius_show[i] if radius_show[i]<R_Min: R_Min=radius_show[i] lat_den_show.SetBinContent(int(radius_bin_show[i]),rho[i]) lat_den_show.SetBinError(int(radius_bin_show[i]),rho_err[i]) Ne_fit,rM_fit,s_fit,Ne_fit_err=TF1_Fit_NKG(lat_den_show,Ne_fit,rM_fit,s_fit,R_Min,R_Max) print('Ne: {0:.2f}, Rm: {1:.2f}, xCore: {2:.2f}, yCore: {3:.2f}'.format(Ne_fit, rM_fit,x_core_fit,y_core_fit)) # do atm correction ################################## atm_data=read_attenuation() size_theta=np.zeros([30]) if len(atm_data)!=11: print('no atm corrections') else: f_no=len(atm_data) f_int=atm_data.T[0] f_logN_Ref=atm_data.T[1] err1=atm_data.T[2] f_X0=atm_data.T[3] err2=atm_data.T[4] f_lamb=atm_data.T[5] err3=atm_data.T[6] Lambda0=0 err_Lambda0=0 for k in np.arange(len(f_int)): size_theta[k]=f_logN_Ref[k]-(f_X0[k]/f_lamb[k])*(1/np.cos(theta)-1/np.cos(np.pi*LORA.Ref_angle/180.0))*0.4342944819 #log10(size) for attenuation curve kk at zenith angle 'theta' #print size_theta[k] if np.log10(Ne_fit) >= size_theta[1]: ## typo? 1->k? Lambda0=f_lamb[k] # //Extropolation err_Lambda0=err3[k] print('Extrapolation: k={0} s_theta={1} s2={2} lamb={3}'.format(k,size_theta[k],np.log10(Ne_fit),Lambda0)) break elif np.log10(Ne_fit) >= size_theta[k]: Lambda0=(f_lamb[k]*(np.log10(Ne_fit)-size_theta[k-1])+f_lamb[k-1]*(size_theta[k]-np.log10(Ne_fit)))/(size_theta[k]-size_theta[k-1]) # //Interpolation err_Lambda0=(err3[k]*(np.log10(Ne_fit)-size_theta[k-1])+err3[k-1]*(size_theta[k]-np.log10(Ne_fit)))/(size_theta[k]-size_theta[k-1]) # //Interpolation print('Interpolation: k={0} s_theta={1} s2={2} lamb={3}'.format(k,size_theta[k],np.log10(Ne_fit),Lambda0)) break #### size_theta[f_no-1]=f_logN_Ref[f_no-1]-(f_X0[f_no-1]/f_lamb[f_no-1])*(1/np.cos(theta)-1/np.cos(np.pi*LORA.Ref_angle/180))*0.4342944819 if np.log10(Ne_fit) >= size_theta[f_no-1]: Lambda0=f_lamb[f_no-1] #; //Extropolation err_Lambda0=err3[f_no-1] print('Extrapolation: k={0} s_theta={1} s2={2} lamb={3}'.format(k,size_theta[k],np.log10(Ne_fit),Lambda0)) log_size_Ref=np.log10(Ne_fit)+(LORA.X0/Lambda0)*(1/np.cos(theta)-1/np.cos(np.pi*LORA.Ref_angle/180.0))*0.4342944819# ; //log10() size_Ref=np.power(10,log_size_Ref) err_size_Ref=np.sqrt(np.power(Ne_fit_err/Ne_fit,2)+np.power(np.log(10)*LORA.X0*(1/np.cos(theta)-1/np.cos(np.pi*LORA.Ref_angle/180.0))*0.4342944819,2)*np.power(err_Lambda0/np.power(Lambda0,2),2))*size_Ref #energy_Ref=pow(size_Ref,par_b)*pow(10,par_a)*pow(10,-6) ; //Energy(PeV) at Ref_angle: Formula from KASCADE simulation (2008) #err_energy_Ref=sqrt(pow(log(10)*err_a,2)+pow(log(size_Ref)*err_b,2)+pow(par_b*err_size_Ref/size_Ref,2))*energy_Ref ; //error on energy at Ref_angle energy_Ref=np.power(size_Ref,LORA.par_b)*np.power(10.0,LORA.par_a)*np.power(10.0,-6.0) #; #//Energy(PeV) at Ref_angle: Formula from KASCADE simulation (2008) err_energy_Ref=np.sqrt(np.power(np.log(10)*LORA.err_a,2)+np.power(np.log10(size_Ref)*LORA.err_b,2)+np.power(LORA.par_b*err_size_Ref/size_Ref,2))*energy_Ref ##; //error on energy at #undo core rotation X3,Y3,Z3=back_theta_phi(theta,phi,psi,x_core_fit,y_core_fit,0) l,m,n=back_theta_phi(theta,phi,psi,0,0,1) x_core_ground=l*(-Z3/n)+X3 ; y_core_ground=m*(-Z3/n)+Y3 ; print('x_core={0:.2f} y_core={1:.2f}'.format(x_core_ground,y_core_ground)) energy=np.power(Ne_fit,LORA.par_b)*np.power(10.0,LORA.par_a)*np.power(10.0,-6.0)# ; //Energy (PeV): Formula from KASCADE simulation (2008) err_energy=np.sqrt(np.power(np.log(10)*LORA.err_a,2)+np.power(np.log10(Ne_fit)*LORA.err_b,2)+np.power(LORA.par_b*Ne_fit_err/Ne_fit,2))*energy #; //error on energy #find first time stamp min_utc=1e10 min_nsec=1e10 for i in np.arange(LORA.nDetA): if detectors[i].gps>1 and detectors[i].cal_time>1: if detectors[i].gps<min_utc: min_utc=detectors[i].gps if detectors[i].cal_time<min_nsec: min_nsec=detectors[i].cal_time # assign event values event.x_core=x_core_ground event.y_core=y_core_ground event.x_core_err=x_core_fit_err event.y_core_err=y_core_fit_err event.z_core=0 event.UTC_min=min_utc event.nsec_min=min_nsec event.energy= energy event.energy_err=err_energy event.Rm=rM_fit event.Ne=Ne_fit event.Ne_err=Ne_fit_err event.CorCoef_xy=corr_coef_xy event.Ne_RefA=size_Ref event.NeErr_RefA=err_size_Ref event.Energy_RefA=energy_Ref event.EnergyErr_RefA=err_energy_Ref
def func_nkg_show(x,par): #NKG function for fitting 5 parameters: (x_core,y_core,Ne,rM,s) return (par[0]/np.power(par[1],2))*(TMath.Gamma(4.5-par[2]))/(2*np.pi*(TMath.Gamma(par[2]))*(TMath.Gamma(4.5-2*par[2])))*np.power(np.sqrt(np.power(par[3]-x[0],2)+np.power(par[4]-x[1],2))/par[1],par[2]-2)*np.power(1.0+np.sqrt(np.power(par[3]-x[0],2)+np.power(par[4]-x[1],2))/par[1],par[2]-4.5)