test_effect_unit.py 9.28 KB
Newer Older
1
2
import unittest
import numpy as np
Fang Yuedong's avatar
Fang Yuedong committed
3
from observation_sim.instruments.chip import effects
4
5
import galsim
import matplotlib.pyplot as plt
Fang Yuedong's avatar
Fang Yuedong committed
6
7
8
9
import os
import sys
import math
import copy
10
11
from numpy.random import Generator, PCG64
import warnings
Zhang Xin's avatar
Zhang Xin committed
12
from astropy.io import fits
13
14
15
16
17
18

warnings.filterwarnings("ignore", '.*Numba.*',)

width = 9216
height = 9232

Fang Yuedong's avatar
Fang Yuedong committed
19

20
class DetTest(unittest.TestCase):
Zhang Xin's avatar
Zhang Xin committed
21
22

    def __init__(self, methodName='runTest'):
Fang Yuedong's avatar
Fang Yuedong committed
23
        super(DetTest, self).__init__(methodName)
Zhang Xin's avatar
Zhang Xin committed
24
        self.filePath('csst_msc_sim/test_sls_and_straylight')
Zhang Xin's avatar
Zhang Xin committed
25
26
27

    def filePath(self, file_name):
        self.datafn = os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), file_name)
Fang Yuedong's avatar
Fang Yuedong committed
28
        self.outDataFn = os.path.join(self.datafn, 'output')
Zhang Xin's avatar
Zhang Xin committed
29
30
31
32
33
        if os.path.isdir(self.outDataFn):
            pass
        else:
            os.mkdir(self.outDataFn)

34
35
36
37
38
39
40
    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
Fang Yuedong's avatar
Fang Yuedong committed
41
        prnuimg = effects.PRNU_Img(width, height, sigma=sigma, seed=seed)
42
        meanval, stdval = np.mean(prnuimg.array), np.std(prnuimg.array)
Fang Yuedong's avatar
Fang Yuedong committed
43
44
        print('  Mean & STDDEV of PRNU image are %6.4f & %6.4f.' %
              (meanval, stdval))
45
        print('  PRNU Image Array:')
Fang Yuedong's avatar
Fang Yuedong committed
46
47
48
        print('  ', prnuimg.array)
        self.assertTrue(np.abs(meanval-1) < 1e-6)
        self.assertTrue(np.abs(stdval-sigma) < 0.002)
49
50
51
52
53
54
55
56
        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)
Fang Yuedong's avatar
Fang Yuedong committed
57
58
59
60
61
        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)))
62
63
64
65
        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))
Fang Yuedong's avatar
Fang Yuedong committed
66
67
        self.assertTrue(np.abs(meanval-3.4) < 0.05)
        self.assertTrue(np.abs(stdval-1.844) < 0.02)
68
69
70
71
72
73
74
        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.
        '''
Fang Yuedong's avatar
Fang Yuedong committed
75
76
77
        img = galsim.Image(500, 500, dtype=np.float32)
        star = galsim.Gaussian(flux=60e5, fwhm=3)
        img = star.drawImage(image=img, center=(150, 200))
78
79
80
81
82
        # 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()
Fang Yuedong's avatar
Fang Yuedong committed
83
        filename1 = os.path.join(self.outDataFn, 'test_satu_initimg.fits')
84
        img.write(filename1)
Fang Yuedong's avatar
Fang Yuedong committed
85
        newimg = effects.SaturBloom(img, fullwell=9e4)
86
87
        # plt.imshow(newimg.array)
        # plt.show()
Fang Yuedong's avatar
Fang Yuedong committed
88
        filename2 = os.path.join(self.outDataFn, 'test_satu_bleedimg.fits')
89
        newimg.write(filename2)
Fang Yuedong's avatar
Fang Yuedong committed
90
        del img, newimg, star
91
92
93
94
95

    def test_nonlinear(self):
        '''
        Test non-linear effect. Expected result: an image with non-linearity effect.
        '''
Fang Yuedong's avatar
Fang Yuedong committed
96
        imgarr = np.arange(1, 9e4, 4).reshape((150, 150))
97
        img = galsim.Image(copy.deepcopy(imgarr))
Fang Yuedong's avatar
Fang Yuedong committed
98
        filename1 = os.path.join(self.outDataFn, 'test_nonlinear_initimg.fits')
99
        img.write(filename1)
Fang Yuedong's avatar
Fang Yuedong committed
100
101
102
        newimg = effects.NonLinearity(img, beta1=5E-7, beta2=0)
        filename2 = os.path.join(
            self.outDataFn, 'test_nonlinear_finalimg.fits')
103
104
        newimg.write(filename2)
        plt.scatter(imgarr.flatten(), newimg.array.flatten(), s=2, alpha=0.5)
Fang Yuedong's avatar
Fang Yuedong committed
105
        plt.plot([-1e3, 9e4], [-1e3, 9e4], color='black', lw=1, ls='--')
106
107
        plt.xlabel('input (e-)')
        plt.ylabel('output (e-)')
Fang Yuedong's avatar
Fang Yuedong committed
108
109
        plt.savefig(os.path.join(self.outDataFn,
                    'test_nonlinearity.png'), dpi=200)
110
        plt.show()
Fang Yuedong's avatar
Fang Yuedong committed
111
        del img, newimg, imgarr
112
113

    def test_badpixel_HtrDtr(self):
Fang Yuedong's avatar
Fang Yuedong committed
114
        img = galsim.Image(500, 500, init_value=1000)
115
116
        rgbadpix = Generator(PCG64(20210911))
        badfraction = 5E-5*(rgbadpix.random()*0.5+0.7)
Fang Yuedong's avatar
Fang Yuedong committed
117
118
119
        img = effects.DefectivePixels(
            img, IfHotPix=True, IfDeadPix=True, fraction=badfraction, seed=20210911, biaslevel=0)
        img.write(os.path.join(self.outDataFn, 'test_badpixel_HtrDtr.fits'))
120
        del img
Fang Yuedong's avatar
Fang Yuedong committed
121

122
    def test_badpixel_HfsDtr(self):
Fang Yuedong's avatar
Fang Yuedong committed
123
        img = galsim.Image(500, 500, init_value=1000)
124
125
        rgbadpix = Generator(PCG64(20210911))
        badfraction = 5E-5*(rgbadpix.random()*0.5+0.7)
Fang Yuedong's avatar
Fang Yuedong committed
126
127
128
        img = effects.DefectivePixels(
            img, IfHotPix=False, IfDeadPix=True, fraction=badfraction, seed=20210911, biaslevel=0)
        img.write(os.path.join(self.outDataFn, 'test_badpixel_HfsDtr.fits'))
129
        del img
Fang Yuedong's avatar
Fang Yuedong committed
130

131
    def test_badpixel_HtrDfs(self):
Fang Yuedong's avatar
Fang Yuedong committed
132
        img = galsim.Image(500, 500, init_value=1000)
133
134
        rgbadpix = Generator(PCG64(20210911))
        badfraction = 5E-5*(rgbadpix.random()*0.5+0.7)
Fang Yuedong's avatar
Fang Yuedong committed
135
136
137
        img = effects.DefectivePixels(
            img, IfHotPix=True, IfDeadPix=False, fraction=badfraction, seed=20210911, biaslevel=0)
        img.write(os.path.join(self.outDataFn, 'test_badpixel_HtrDfs.fits'))
138
        del img
Fang Yuedong's avatar
Fang Yuedong committed
139

140
    def test_badpixel_HfsDfs(self):
Fang Yuedong's avatar
Fang Yuedong committed
141
        img = galsim.Image(500, 500, init_value=1000)
142
143
        rgbadpix = Generator(PCG64(20210911))
        badfraction = 5E-5*(rgbadpix.random()*0.5+0.7)
Fang Yuedong's avatar
Fang Yuedong committed
144
145
146
        img = effects.DefectivePixels(
            img, IfHotPix=False, IfDeadPix=False, fraction=badfraction, seed=20210911, biaslevel=0)
        img.write(os.path.join(self.outDataFn, 'test_badpixel_HfsDfs.fits'))
147
148
149
        del img

    def test_badlines(self):
Fang Yuedong's avatar
Fang Yuedong committed
150
        img = galsim.Image(500, 500, init_value=-1000)
151
        img.addNoise(galsim.GaussianNoise(sigma=7))
Fang Yuedong's avatar
Fang Yuedong committed
152
153
154
        newimg = effects.BadColumns(copy.deepcopy(img), seed=20210911)
        newimg.write(os.path.join(self.outDataFn, 'test_badlines.fits'))
        del newimg, img
155

Zhang Xin's avatar
Zhang Xin committed
156
157
158
159
    # def test_cte(self):
    #     img = galsim.Image(200,200,init_value=1000)
    #     img.array[50,80] = 1e4
    #     img.array[150,150] = 3e4
Fang Yuedong's avatar
Fang Yuedong committed
160
161
    #     newimgcol = effects.CTE_Effect(copy.deepcopy(img),direction='column')
    #     newimgrow = effects.CTE_Effect(copy.deepcopy(img),direction='row')
Zhang Xin's avatar
Zhang Xin committed
162
163
164
    #     newimgcol.write(os.path.join(self.outDataFn,'test_ctecol.fits'))
    #     newimgrow.write(os.path.join(self.outDataFn,'test_cterow.fits'))
    #     del img,newimgcol,newimgrow
165
166

    def test_readnoise(self):
Fang Yuedong's avatar
Fang Yuedong committed
167
        img = galsim.Image(200, 200, init_value=1000)
168
169
170
171
        seed = 20210911
        rng_readout = galsim.BaseDeviate(seed)
        readout_noise = galsim.GaussianNoise(rng=rng_readout, sigma=5)
        img.addNoise(readout_noise)
Fang Yuedong's avatar
Fang Yuedong committed
172
        img.write(os.path.join(self.outDataFn, 'test_readnoise.fits'))
173
        stdval = np.std(img.array)
Fang Yuedong's avatar
Fang Yuedong committed
174
        self.assertTrue(np.abs(stdval-5) < 0.01*5)
175
176
177
178
        print('\nUnit test for readout noise has been passed.')
        del img

    def test_addbias(self):
Fang Yuedong's avatar
Fang Yuedong committed
179
180
181
        img = galsim.Image(200, 200, init_value=0)
        img = effects.AddBiasNonUniform16(
            img, bias_level=500, nsecy=2, nsecx=8, seed=20210911)
182
183
184
185
        img.write('./output/test_addbias.fits')
        del img

    def test_apply16gains(self):
Fang Yuedong's avatar
Fang Yuedong committed
186
187
188
189
        img = galsim.Image(500, 500, init_value=100)
        img, _ = effects.ApplyGainNonUniform16(
            img, gain=1.5, nsecy=2, nsecx=8, seed=202102)
        img.write(os.path.join(self.outDataFn, 'test_apply16gains.fits'))
190
191
        rightedge = int(500/8)*8
        print('gain=%6.2f' % 1.5)
Fang Yuedong's avatar
Fang Yuedong committed
192
193
194
195
196
        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)
197
198
199
200
        print('\nUnit test for applying 16 channel gains has been passed.')
        del img

    def test_cosmicray(self):
Fang Yuedong's avatar
Fang Yuedong committed
201
202
203
204
205
206
        attachedSizes = np.loadtxt(os.path.join(
            self.datafn, '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)
207
        crimg = galsim.Image(cr_map)
Fang Yuedong's avatar
Fang Yuedong committed
208
209
        crimg.write(os.path.join(self.outDataFn, 'test_cosmicray.fits'))
        del cr_map, crimg
210
211

    def test_shutter(self):
Fang Yuedong's avatar
Fang Yuedong committed
212
213
214
215
        img = galsim.Image(5000, 5000, init_value=1000)
        # shutter effect normalized image for this chip
        shuttimg = effects.ShutterEffectArr(
            img, t_exp=150, t_shutter=1.3, dist_bearing=735, dt=1E-3)
216
        img *= shuttimg
Fang Yuedong's avatar
Fang Yuedong committed
217
        img.write(os.path.join(self.outDataFn, 'test_shutter.fits'))
218
219
220
        del img

    def test_vignette(self):
Fang Yuedong's avatar
Fang Yuedong committed
221
        img = galsim.Image(2000, 2000, init_value=1000)
222
223
        print(img.bounds)
        # # img.bounds = galsim.BoundsI(1, width, 1, height)
Fang Yuedong's avatar
Fang Yuedong committed
224
225
        img.setOrigin(10000, 10000)
        flat_img = effects.MakeFlatSmooth(img.bounds, 20210911)
226
        flat_normal = flat_img / np.mean(flat_img.array)
Fang Yuedong's avatar
Fang Yuedong committed
227
228
        flat_normal.write(os.path.join(self.outDataFn, 'test_vignette.fits'))
        del flat_img, img, flat_normal
229
230
231


if __name__ == '__main__':
Fang Yuedong's avatar
Fang Yuedong committed
232
    unittest.main()