import ceo
%pylab inline
A 10th magnitude V band source:
n = 5
src = ceo.Source("V",resolution=(n+1,n+1))
src.magnitude = [10]
A single lenslet Shack-Hartmann WFS with $4\times 4$ pixel in the pupil plane and a Nyquist sampled focal plane with $8\times 8$ pixels:
wfs = ceo.ShackHartmann(1,n,1,N_PX_IMAGE=2*(n+1))
A 1m$^2$ square pupil:
tel = ceo.Mask(n+1,1)
for the source to go through
src.masked(tel)
Lets calibrate the WFS:
wfs.calibrate(src,1)
The WFS detector is reset, the source is propagated through the WFS and the WFS detector is read (the exposure time is 1ms):
src.magnitude = [10]
wfs.reset()
wfs.propagate(src)
wfs.readOut(1e-3,0)
frame = wfs.frame
imshow(frame.host(),interpolation='none')
colorbar()
np.sum(frame.host_data)
src.nPhoton*1e-3
The WFS detector frame is process to get the centroids:
wfs.process()
print wfs.c.host(units='arcsec')*1e3
def wfeVsNoise(magnitude,ron=0,exposure=1e-3):
src.magnitude = [magnitude]
nSample = 2500
cx = np.zeros(nSample)
cy = np.zeros(nSample)
for k in range(nSample):
wfs.reset()
wfs.propagate(src)
wfs.readOut(exposure,ron)
wfs.process()
c = wfs.c.host()
cx[k] = c[0,0]
cy[k] = c[0,1]
return src.nPhoton*exposure, cx.var(), cy.var()
def photonNoise(nPh,fwhm):
return ((fwhm**2/(4*math.log(2)))/nPh)
magnitude = np.linspace(0,14,15)
print magnitude
cex = np.zeros(magnitude.size)
cey = np.zeros(magnitude.size)
nPh = np.zeros(magnitude.size)
for x in range(magnitude.size):
nPh[x], cex[x],cey[x] = wfeVsNoise(x)
print nPh
px_scale = 0.55e-6/2
fwhm = 2*px_scale
i_nPh = 1.0/nPh
u = cex/fwhm**2
v = cey/fwhm**2
px = polyfit(i_nPh , u,1)
py = polyfit(i_nPh , v,1)
print px, py
fig, ax = plt.subplots()
ax.plot(i_nPh,u,'.',label='x data')
ax.plot(i_nPh,v,'.',label='y data')
ax.plot(i_nPh,px[0]/nPh + px[1],label='x fit')
ax.plot(i_nPh,py[0]/nPh + py[1],label='y fit')
ax.plot(i_nPh,photonNoise(nPh,fwhm)/fwhm**2,label='analytic')
ax,grid()
ax.set_xlabel('1/Nph')
ax.legend(loc=0)
def readOutNoise(ron,pxScale,nPh,Ns):
return (pxScale*ron/nPh)**2*Ns**4/12
ron = np.linspace(0,10,11)
print ron
cex = np.zeros(ron.size)
cey = np.zeros(ron.size)
nPh = np.zeros(ron.size)
for x in range(ron.size):
nPh[x], cex[x],cey[x] = wfeVsNoise(8,ron=x)
u = nPh[0]**2*cex/px_scale**2
v = nPh[0]**2*cey/px_scale**2
ron2 = ron**2
px = polyfit(ron2 , u,1)
py = polyfit(ron2 , v,1)
print px, py
fig, ax = plt.subplots()
ax.plot(ron2,u,'.',label='x data')
ax.plot(ron2,v,'.',label='y data')
ax.plot(ron2,px[0]*ron2 + px[1],label='x fit')
ax.plot(ron2,py[0]*ron2 + py[1],label='y fit')
ax.plot(ron2,nPh[0]**2*readOutNoise(ron,px_scale,nPh[0],(n+1)*2)/px_scale**2+0.5*(px[1]+py[1]),'--',label='analytic')
ax.grid()
ax.set_xlabel('ron$^2$')
ax.legend(loc=0)
0.25/math.log(2)
(2*n)**4/12