-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcorrelation.py
144 lines (120 loc) · 4.83 KB
/
correlation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import numpy as np
import matplotlib.pyplot as plt
from lmfit import models
from scipy import ndimage
import utils
def _spatial_correlation_fourier(fim1, fim2_star, fmask, fmask_star):
A_num1 = np.fft.irfft2(fim1*fim2_star)
A_num2 = np.fft.irfft2(fmask*fmask_star)
# A_num2 *=A_num2>0.4 # remove Fourier components that are too small
A = A_num1 * A_num2
A_denom = np.fft.irfft2(fim1*fmask_star) * np.fft.irfft2(fim2_star*fmask) # symmetric normalization
# make sure the normalization value isn't 0 otherwise the autocorr will 'explode'
pos = np.where(np.abs(A_denom)!=0)
A[pos] /= A_denom[pos]
A = np.fft.fftshift(A)
return A
def spatial_correlation_fourier(img, img2=None, mask=None):
""" Compute spatial correlation between two images using Fourier transform.
Args:
img: first image
img2: second image. If None, becomes the first image (autocorrelation)
mask: mask spanning the region of interest
Returns:
A: 2d correlation matrix
"""
if mask is None:
mask = np.ones_like(img)
if img2 is None:
img2 = img
# (i) restrain mask and imgs to a bounding box around the roi defined by the mask
img, temp = utils.box_to_roi(img, mask)
img2, mask = utils.box_to_roi(img2, mask)
# (ii) compute the different terms
fmask = np.fft.rfft2(mask)
fmask_star = np.conjugate(fmask)
fimg = np.fft.rfft2(img)
fimg2_star = np.conjugate(np.fft.rfft2(img2))
# (iii) compute correlation
A = _spatial_correlation_fourier(fimg, fimg2_star, fmask, fmask_star)
return A
def remove_central_corr(A, r=0):
""" Remove the central part of the correlation, which is peaking to high. The range of data being removed
can be adjusted with the parameter r.
"""
i,j = np.unravel_index(np.argmax(A), A.shape)
A[i-r:i+1+r, j-r:j+1+r] = np.nan
return A
def correct_illumination(imgs, roi, kernel_size=5):
""" Correct the detector images for non-uniform illumination.
This implementation follows Part II in Duri et al. PHYS. REV. E 72, 051401 (2005).
Args:
imgs: stack of detector images
roi: region of interest to consider. Important so that the normalization of the correction
is ~unity for the specific roi
kernel_size: size of the kernel for box-average. Can be None, in which case no kernel is
applied. The kernel is used to smooth out remaining speckly structure in the intensity correction.
Returns:
imgs: corrected images, cropped to an extended box aroung the roi
roi: new roi for the cropped image
bp: correction factor
"""
if kernel_size is None:
extend = 10
else:
extend=2*kernel_size
imgs, roi = utils.box_to_roi_extend(imgs, roi, extend=extend)
if imgs.ndim==2:
imgs = imgs[None, ...]
bp = np.mean(imgs, axis=0)
if kernel_size is not None:
kernel = np.ones([kernel_size, kernel_size])/kernel_size/kernel_size
bp = ndimage.convolve(bp, kernel)
bp = bp / bp[roi].mean()
zero = bp==0
bp[zero] = 1e-6
imgs_corr = imgs/bp
return imgs_corr, roi, bp
def fit_correlation(A, rr=None, ax=None):
""" Fit a Gaussian + a constant to the horizontal and vertical cental
lineout cut of A.
Args:
A: autocorrelation image
rr: +/- number of pixel around the central point to consider. If None the entire
lineout is fitted
"""
xx = A.shape[0]//2
yy = A.shape[1]//2
if rr is None:
horiz = A[xx,:]
vert = A[:,yy]
else:
horiz = A[xx,yy-rr:yy+rr]
vert = A[xx-rr:xx+rr,yy]
data = [vert, horiz]
titles = ['vertical', 'horizontal']
if ax is None:
fig, ax = plt.subplots(nrows=2, figsize=(10,10))
for ii, dat in enumerate(data):
center = np.where(np.isnan(dat))[0][0]
gmodel = models.GaussianModel(nan_policy='omit')+models.ConstantModel(nan_policy='omit')
params = gmodel.make_params()
params['amplitude'].set(value=1.)
params['sigma'].set(value=1.)
params['center'].set(value=center)
params['c'].set(value=1.)
x = np.arange(dat.shape[0])
res = gmodel.fit(dat, params, x=x, method='leastsq') #, fit_kws={'ftol':1e-10, 'xtol':1e-10})
xfit = np.arange(0,2*center,0.1)
ax[ii].plot(xfit, res.eval(x=xfit), color='purple', linewidth=2,
label='sigma = {:.2f} +/- {:.2f}'.format(res.params['sigma'].value, res.params['sigma'].stderr))
ax[ii].plot(dat, 'o', color='orange')
ax[ii].legend(loc='upper right')
ax[ii].set_title(titles[ii])
ax[ii].set_xlabel('Pixel')
ax[ii].set_ylabel('Correlation')
print(res.fit_report())
print('\n')
plt.tight_layout()
plt.show()
return res