import unittest import numpy as np from ObservationSim.Instrument.Chip import Effects import galsim import matplotlib.pyplot as plt import os,sys,math,copy from numpy.random import Generator, PCG64 import warnings warnings.filterwarnings("ignore", '.*Numba.*',) width = 9216 height = 9232 if os.path.isdir('./output/'): pass else: os.mkdir('./output/') class DetTest(unittest.TestCase): def test_prnu(self): ''' Unit test for PRNU. Expected result: a randomized GS image contains PRNU with sigma=0.01, mean=1. ''' print('PRNU Test:') sigma = 0.01 seed = 20210911 prnuimg = Effects.PRNU_Img(width, height, sigma=sigma, seed=seed) meanval, stdval = np.mean(prnuimg.array), np.std(prnuimg.array) print(' Mean & STDDEV of PRNU image are %6.4f & %6.4f.' % (meanval, stdval)) print(' PRNU Image Array:') print(' ',prnuimg.array) self.assertTrue(np.abs(meanval-1)<1e-6) self.assertTrue(np.abs(stdval-sigma)<0.002) print('\nUnit test for PRNU has been passed.') del prnuimg def test_dark(self): ''' Test add dark current to image. Expected result: an image with dark current 3.4 e- and noise=1.844 e-. ''' rng_poisson = galsim.BaseDeviate(20210911) dark_noise = galsim.DeviateNoise(galsim.PoissonDeviate(rng_poisson, 0.02*(150+0.5*40))) img = galsim.Image(200,200,dtype=np.float32, init_value=0) print('Initial Mean & STD = %6.3f & %6.3f' % (np.mean(img.array), np.std(img.array))) img.addNoise(dark_noise) meanval = np.mean(img.array) stdval = np.std(img.array) print('Dark added Mean & STD = %6.3f & %6.3f' % (meanval, stdval)) self.assertTrue(np.abs(meanval-3.4)<0.05) self.assertTrue(np.abs(stdval-1.844)<0.02) print('\nUnit test for dark current has been passed.') del img def test_satu(self): ''' Test saturation and bleeding. Expected result: an image with bleeding effect. ''' img = galsim.Image(500,500,dtype=np.float32) star = galsim.Gaussian(flux=60e5,fwhm=3) img = star.drawImage(image=img,center=(150,200)) # gal = galsim.Sersic(n=1, half_light_radius=3,flux=50e5) # img = gal.drawImage(image=img,center=(350,300)) img.addNoise(galsim.GaussianNoise(sigma=7)) # plt.imshow(img.array) # plt.show() filename1 = os.path.join('output','test_satu_initimg.fits') img.write(filename1) newimg = Effects.SaturBloom(img, fullwell=9e4) # plt.imshow(newimg.array) # plt.show() filename2 = os.path.join('output','test_satu_bleedimg.fits') newimg.write(filename2) del img,newimg, star def test_nonlinear(self): ''' Test non-linear effect. Expected result: an image with non-linearity effect. ''' imgarr = np.arange(1,9e4,4).reshape((150,150)) img = galsim.Image(copy.deepcopy(imgarr)) filename1 = os.path.join('output','test_nonlinear_initimg.fits') img.write(filename1) newimg = Effects.NonLinearity(img, beta1=5E-7, beta2=0) filename2 = os.path.join('output','test_nonlinear_finalimg.fits') newimg.write(filename2) plt.scatter(imgarr.flatten(), newimg.array.flatten(), s=2, alpha=0.5) plt.plot([-1e3,9e4],[-1e3,9e4],color='black', lw=1, ls='--') plt.xlabel('input (e-)') plt.ylabel('output (e-)') plt.savefig('./output/test_nonlinearity.png', dpi=200) plt.show() del img,newimg,imgarr def test_badpixel_HtrDtr(self): img = galsim.Image(500,500,init_value=1000) rgbadpix = Generator(PCG64(20210911)) badfraction = 5E-5*(rgbadpix.random()*0.5+0.7) img = Effects.DefectivePixels(img, IfHotPix=True, IfDeadPix=True, fraction=badfraction, seed=20210911, biaslevel=0) img.write('./output/test_badpixel_HtrDtr.fits') del img def test_badpixel_HfsDtr(self): img = galsim.Image(500,500,init_value=1000) rgbadpix = Generator(PCG64(20210911)) badfraction = 5E-5*(rgbadpix.random()*0.5+0.7) img = Effects.DefectivePixels(img, IfHotPix=False, IfDeadPix=True, fraction=badfraction, seed=20210911, biaslevel=0) img.write('./output/test_badpixel_HfsDtr.fits') del img def test_badpixel_HtrDfs(self): img = galsim.Image(500,500,init_value=1000) rgbadpix = Generator(PCG64(20210911)) badfraction = 5E-5*(rgbadpix.random()*0.5+0.7) img = Effects.DefectivePixels(img, IfHotPix=True, IfDeadPix=False, fraction=badfraction, seed=20210911, biaslevel=0) img.write('./output/test_badpixel_HtrDfs.fits') del img def test_badpixel_HfsDfs(self): img = galsim.Image(500,500,init_value=1000) rgbadpix = Generator(PCG64(20210911)) badfraction = 5E-5*(rgbadpix.random()*0.5+0.7) img = Effects.DefectivePixels(img, IfHotPix=False, IfDeadPix=False, fraction=badfraction, seed=20210911, biaslevel=0) img.write('./output/test_badpixel_HfsDfs.fits') del img def test_badlines(self): img = galsim.Image(500,500,init_value=-1000) img.addNoise(galsim.GaussianNoise(sigma=7)) newimg = Effects.BadColumns(copy.deepcopy(img), seed=20210911) newimg.write('./output/test_badlines.fits') del newimg,img def test_cte(self): img = galsim.Image(200,200,init_value=1000) img.array[50,80] = 1e4 img.array[150,150] = 3e4 newimgcol = Effects.CTE_Effect(copy.deepcopy(img),direction='column') newimgrow = Effects.CTE_Effect(copy.deepcopy(img),direction='row') newimgcol.write('./output/test_ctecol.fits') newimgrow.write('./output/test_cterow.fits') del img,newimgcol,newimgrow def test_readnoise(self): img = galsim.Image(200,200,init_value=1000) seed = 20210911 rng_readout = galsim.BaseDeviate(seed) readout_noise = galsim.GaussianNoise(rng=rng_readout, sigma=5) img.addNoise(readout_noise) img.write('./output/test_readnoise.fits') stdval = np.std(img.array) self.assertTrue(np.abs(stdval-5)<0.01*5) print('\nUnit test for readout noise has been passed.') del img def test_addbias(self): img = galsim.Image(200,200,init_value=0) img = Effects.AddBiasNonUniform16(img,bias_level=500, nsecy = 2, nsecx=8,seed=20210911) img.write('./output/test_addbias.fits') del img def test_apply16gains(self): img = galsim.Image(500,500,init_value=100) img = Effects.ApplyGainNonUniform16(img, gain=1.5, nsecy=2, nsecx=8, seed=202102) img.write("./output/test_apply16gains.fits") rightedge = int(500/8)*8 print('gain=%6.2f' % 1.5) meanimg = np.mean(img.array[:,:rightedge]) sigmaimg = np.std(img.array[:,:rightedge]) print('mean, sigma = %6.2f, %6.2f' % (meanimg,sigmaimg)) self.assertTrue(np.abs(meanimg-100/1.5)<1) self.assertTrue(np.abs(sigmaimg/meanimg-0.01)<0.001) print('\nUnit test for applying 16 channel gains has been passed.') del img def test_cosmicray(self): attachedSizes = np.loadtxt('../ObservationSim/Instrument/Chip/wfc-cr-attachpixel.dat') cr_map = Effects.produceCR_Map( xLen=500, yLen=500, exTime=150+0.5*40, cr_pixelRatio=0.003*(1+0.5*40/150), gain=1, attachedSizes=attachedSizes, seed=20210911) crimg = galsim.Image(cr_map) crimg.write('./output/test_cosmicray.fits') del cr_map,crimg def test_shutter(self): img = galsim.Image(5000,5000,init_value=1000) shuttimg = Effects.ShutterEffectArr(img, t_exp=150, t_shutter=1.3, dist_bearing=735, dt=1E-3) # shutter effect normalized image for this chip img *= shuttimg img.write('./output/test_shutter.fits') del img def test_vignette(self): img = galsim.Image(2000,2000,init_value=1000) print(img.bounds) # # img.bounds = galsim.BoundsI(1, width, 1, height) img.setOrigin(10000,10000) flat_img = Effects.MakeFlatSmooth(img.bounds,20210911) flat_normal = flat_img / np.mean(flat_img.array) flat_normal.write('./output/test_vignette.fits') del flat_img,img,flat_normal if __name__ == '__main__': unittest.main()