def calculate2dfrom1d(q,I,Nx,Ny,bcx,bcy,dist,energy,pixelsize,noise=False): """Create a 2D scattering image from a scattering curve. Inputs: q: q-values I: intensities Nx: number of rows Ny: number of columns bcx: beam center row coordinate (counting from 1) bcy: beam center column coordinate (counting from 1) dist: sample-detector distance energy: photon energy pixelsize: size of a pixel noise: True if you want to add noise (re-sample the scattering image from a Poisson distribution). False if not. Or give a number for relative error. Outputs: the scattering image itself. """ A=np.zeros((Nx,Ny)) D=calculateDmatrix(A,pixelsize,bcx,bcy) q1=4*np.pi*np.sin(0.5*np.arctan(D/dist))*energy/HC A=np.interp(q1,q,I,left=0,right=0) if noise: if type(noise)==type(True): A=np.random.poisson(A) else: A=A*(1+(np.random.random(A.shape)*2-1)*noise) return A
def calculatetwothetamatrix(mat,dist,res,bcx,bcy): """Calculate two-theta values for detector pixels Inputs: mat: scattering image (or mask) matrix, only its shape is needed dist: sample-detector distance, in mm. res: pixel size (mm) bcx, bcy: beam positions (row, column) in pixel coordinates, counting starts from 1. Output: a matrix of the same shape as mat, containing twotheta values for the pixels. """ return np.arctan(calculateDmatrix(mat.astype(np.uint8),res,bcx,bcy)/dist)
def calculateqmatrix(mat,dist,energy,res,bcx,bcy): """Calculate q values for detector pixels Inputs: mat: scattering image (or mask) matrix, only its shape is needed energy: true (calibrated) photon energy dist: sample-detector distance, in mm. res: pixel size (mm) bcx, bcy: beam positions (row, column) in pixel coordinates, counting starts from 1. Output: a matrix of the same shape as mat, containing q values for the individual pixels. """ return 4*np.pi*np.sin(0.5*np.arctan(calculateDmatrix(mat,res,bcx,bcy)/dist))*energy/HC
def qrangefrommask(mask,energy,distance,res,bcx,bcy,fullyunmasked=False): """Calculate q-range from mask matrix Inputs: mask: mask matrix (1 unmasked, 0 masked) energy: calibrated energy distance: sample-to-detector distance res: pixel size bcx: row coordinate of beam center (starting from 1) bcy: column coordinate of beam center (starting from 1) fullyunmasked: if the q-range should be fully unmasked (only the beginning and the end is checked). Set it to True if you want only full circles (eg. for azimuthal averaging). False gives you the entire unmasked q-range (ti. including partially covered q rings) Outputs: qmin,qmax,Nq qmin: smallest q-value (smallest distance of unmasked points from the origin) qmax: largest q-value (largest distance of unmasked points from the origin) Nq: number of q-bins (approx. one q-bin for one pixel) """ D=calculateDmatrix(mask,res,bcx,bcy) dmin=np.nanmin(D[mask!=0]) dmax=np.nanmax(D[mask!=0]) qmin=4*np.pi*np.sin(0.5*np.arctan(dmin/distance))*energy/HC qmax=4*np.pi*np.sin(0.5*np.arctan(dmax/distance))*energy/HC Nq=np.ceil(dmax-dmin) if fullyunmasked: # the smallest of the border elements in D Dbordermin=min(D[:,0].min(),D[0,:].min(),D[-1,:].min(),D[:,-1].min()) qbordermin=4*np.pi*np.sin(0.5*np.arctan(Dbordermin/distance))*energy/HC qmax=min(qmax,qbordermin) return qmin,qmax,Nq