rconan / CEO

Cuda-Engined Adaptive Optics
zlib License
24 stars 18 forks source link

Sky background not implemented properly #56

Closed mvandam closed 3 years ago

mvandam commented 3 years ago

Here is an example that shows that the sky background is not implemented properly in CEO (at least, for Shack-Hartmann WFSs). I will try to fix it at some point.

calculate the background

import warnings warnings.filterwarnings("ignore") import sys import os import ceo import numpy as np import matplotlib.pyplot as plt

pupil_size = 25.5 threshold = 0.01 # subaperture flux threshold vismag = np.array([1000.]) zen = np.array([0.]) azi = np.array([0.]) gmt = ceo.GMT_MX()

N_SIDE_LENSLET = 24 # The linear size of the lenslet array (>=1). N_PX_LENSLET = 30 # The sampling in pixel of one lenslet. d = pupil_size/N_SIDE_LENSLET # The lenslet pitch [m]. DFT_osf = 2 # [2] optional The oversampling factor for the DFT N_PX_IMAGE = 48 # int, optional The sampling in pixel of the imagelet [N_PX_LENSLET] BIN_IMAGE = 6 # optional The binning factor of the imagelet [1] N_GS = 1 # optional The number of guide stars [1] exposureTime = 1. readOutNoiseRms = 0 photoElectronGain = 1 # The photon to electron conversion gain of the camera [1] noiseFactor = 1 fudgeFactor = 0.000550

background photometry

need to understand if this is for binned or unbinned pixels

sky_magnitude = 19

wfs_prms = {'N_SIDE_LENSLET':N_SIDE_LENSLET,'N_PX_LENSLET':N_PX_LENSLET,'d':d,'DFT_osf':DFT_osf,'N_PX_IMAGE':N_PX_IMAGE,'BIN_IMAGE':BIN_IMAGE,'N_GS': N_GS,'readOutNoiseRms':readOutNoiseRms,'noiseFactor':noiseFactor,'photoElectronGain':photoElectronGain, 'exposureTime':exposureTime,'intensityThreshold':-10000.0} wfs = ceo.ShackHartmann(**wfs_prms)

gs = ceo.Source(photometric_band="R+I",zenith=zen,azimuth=azi,magnitude=vismag,rays_box_size=pupil_size,rays_box_sampling=N_SIDE_LENSLET*N_PX_LENSLET+1,rays_origin=[0,0,25])

to do: overwrite the photometry and noise (but ignore for now)

to do: convert geometric to physical optics WFS

~gmt gs.reset() gmt.reset() gmt.propagate(gs) wfs.calibrate(gs,threshold) gs>>(gmt,wfs)

wfs.camera.nBackgroundPhoton = gs.nBackgroundPhoton(sky_magnitude)*fudgeFactor # fudge factor to get the right values

~wfs gs>>(gmt,wfs) +gs +wfs

plt.ion() plt.figure(1) plt.clf() frame = np.array(wfs.camera.ghost_frame[:wfs.N_PX_FRAME,:]) plt.imshow(frame,interpolation='none',cmap='viridis')

print("expected variance", 24.46e9*(pupil_size/N_SIDE_LENSLET)2*2.512*(-sky_magnitude)(wfs.camera.pixelScaleArcsec(gs)2)exposureTimewfs.camera.noiseFactor*2wfs.camera.photoelectron_gain) print("actual variance", np.var(frame))

rconan commented 3 years ago

Thanks @mvandam, I understand the confusion , nBackgroundPhoton is ill defined , it should be: nBackgroundPhoton is the mean number of background photon per detector pixel and with that definition we got: nBackgroundPhoton=np.mean(frame)=np.var(frame)

mvandam commented 3 years ago

There were two reasons why the background was not working for me. The first is that the background is computed per arcsecond, not per pixel. The second is that the WFS needs to be initialized/calibrated before computing the background. The background should be set in the following way: (this is an NGS tip-tilt sensor)

In [4]: ngswfs_prms = {'N_SIDE_LENSLET':1,'N_PX_LENSLET':NT,'d':D,'DFT_osf':2,'N_PX_IMAGE':ngs_px_image,'BIN_IMAGE':ngs_binning,'N_GS':N_NGS,'readOutNoiseRms':ngs_
   ...: readoutnoise,'noiseFactor':ngs_noisefactor,'photoElectronGain':ngs_photoelectrongain, 'exposureTime':exposureTime,'intensityThreshold':0.0}
   ...: ngswfs = ceo.ShackHartmann(**ngswfs_prms)
   ...: 
   ...: ~gmt
   ...: ~ngs
   ...: gmt.propagate(ngs)
   ...: ngswfs.calibrate(ngs)
   ...: ngswfs.camera.nBackgroundPhoton = ngs.nBackgroundPhoton(ngs_sky_magnitude)*ngswfs.pixel_scale_arcsec**2 + ngs_darkcurrent*ngs_binning**2/ngs_photoelectrongain
   ...: 
   ...