Chip.py 38.3 KB
Newer Older
Fang Yuedong's avatar
Fang Yuedong committed
1
2
3
import galsim
import os
import numpy as np
Fang Yuedong's avatar
Fang Yuedong committed
4
5
import pickle
import json
6
import ObservationSim.Instrument._util as _util
Fang Yuedong's avatar
Fang Yuedong committed
7
8
from astropy.table import Table
from numpy.random import Generator, PCG64
Fang Yuedong's avatar
Fang Yuedong committed
9
10
from astropy.io import fits
from datetime import datetime
Fang Yuedong's avatar
Fang Yuedong committed
11

12
13
14
from ObservationSim.Instrument.Chip import Effects as effects
from ObservationSim.Instrument.FocalPlane import FocalPlane
from ObservationSim.Config.Header import generatePrimaryHeader, generateExtensionHeader
Fang Yuedong's avatar
Fang Yuedong committed
15
from ObservationSim.Instrument._util import rotate_conterclockwise
16
from ObservationSim.Instrument.Chip import ChipUtils as chip_utils
17

Fang Yuedong's avatar
Fang Yuedong committed
18
19
20
21
22
23
try:
    import importlib.resources as pkg_resources
except ImportError:
    # Try backported to PY<37 'importlib_resources'
    import importlib_resources as pkg_resources

Fang Yuedong's avatar
Fang Yuedong committed
24
class Chip(FocalPlane):
25
    def __init__(self, chipID, ccdEffCurve_dir=None, CRdata_dir=None, sls_dir=None, config=None, treering_func=None, logger=None):
Fang Yuedong's avatar
Fang Yuedong committed
26
27
        # Get focal plane (instance of paraent class) info
        super().__init__()
28
29
30
        self.nsecy = 2
        self.nsecx = 8
        self.gain_channel = np.ones(self.nsecy* self.nsecx)
Fang Yuedong's avatar
Fang Yuedong committed
31
        self._set_attributes_from_config(config)
Fang Yuedong's avatar
Fang Yuedong committed
32

33
34
        self.logger = logger

Fang Yuedong's avatar
Fang Yuedong committed
35
36
        # A chip ID must be assigned
        self.chipID = int(chipID)
Fang Yuedong's avatar
Fang Yuedong committed
37
        self.chip_name = str(chipID).rjust(2, '0')
Fang Yuedong's avatar
Fang Yuedong committed
38
39
40
41
42

        # Get corresponding filter info
        self.filter_id, self.filter_type = self.getChipFilter()
        self.survey_type = self._getSurveyType()

Fang Yuedong's avatar
Fang Yuedong committed
43
44
45
        if self.filter_type != "FGS":
            self._getChipRowCol()

46
        # Set the relavent specs for detectors
Fang Yuedong's avatar
Fang Yuedong committed
47
48
49
50
51
52
53
54
55
56
        try:
            with pkg_resources.files('ObservationSim.Instrument.data.ccd').joinpath("chip_definition.json") as chip_definition:
                with open(chip_definition, "r") as f:
                    chip_dict = json.load(f)[str(self.chipID)]
        except AttributeError:
            with pkg_resources.path('ObservationSim.Instrument.data.ccd', "chip_definition.json") as chip_definition:
                with open(chip_definition, "r") as f:
                    chip_dict = json.load(f)[str(self.chipID)]
        for key in chip_dict:
            setattr(self, key, chip_dict[key])
57
        
Fang Yuedong's avatar
Fang Yuedong committed
58
        if self.filter_type == "FGS":
59
            if ("field_dist" in config) and (config["ins_effects"]["field_dist"]) == False:
Fang Yuedong's avatar
Fang Yuedong committed
60
61
62
63
64
65
66
67
68
69
70
71
72
                self.fdModel = None
            else:
                fgs_name = self.chip_name[0:4]
                try:
                    with pkg_resources.files('ObservationSim.Instrument.data.field_distortion').joinpath("FieldDistModelGlobal_pr4_%s.pickle"%(fgs_name.lower())) as field_distortion:
                        with open(field_distortion, "rb") as f:
                            self.fdModel = pickle.load(f)
                except AttributeError:
                    with pkg_resources.path('ObservationSim.Instrument.data.field_distortion', "FieldDistModelGlobal_pr4_%s.pickle"%(fgs_name.lower())) as field_distortion:
                        with open(field_distortion, "rb") as f:
                            self.fdModel = pickle.load(f)
        else:
            # Get the corresponding field distortion model
73
            if ("field_dist" in config) and (config["ins_effects"]["field_dist"] == False):
Fang Yuedong's avatar
Fang Yuedong committed
74
75
76
                self.fdModel = None
            else:
                try:
77
                    with pkg_resources.files('ObservationSim.Instrument.data.field_distortion').joinpath("FieldDistModel_v2.0.pickle") as field_distortion:
Fang Yuedong's avatar
Fang Yuedong committed
78
79
80
81
82
83
84
                        with open(field_distortion, "rb") as f:
                            self.fdModel = pickle.load(f)
                except AttributeError:
                    with pkg_resources.path('ObservationSim.Instrument.data.field_distortion', "FieldDistModelGlobal_mainFP_v1.0.pickle") as field_distortion:
                        with open(field_distortion, "rb") as f:
                            self.fdModel = pickle.load(f)

Fang Yuedong's avatar
Fang Yuedong committed
85
86
        # Get boundary (in pix)
        self.bound = self.getChipLim()
87
        
Fang Yuedong's avatar
Fang Yuedong committed
88
89
        self.ccdEffCurve_dir = ccdEffCurve_dir
        self.CRdata_dir = CRdata_dir
90
91
        
        slsconfs = chip_utils.getChipSLSConf(chipID=self.chipID)
Fang Yuedong's avatar
Fang Yuedong committed
92
        if np.size(slsconfs) == 1:
93
94
95
96
97
98
            try:
                with pkg_resources.files('ObservationSim.Instrument.data.sls_conf').joinpath(slsconfs) as conf_path:
                    self.sls_conf = str(conf_path)
            except AttributeError:
                with pkg_resources.path('ObservationSim.Instrument.data.sls_conf', slsconfs) as conf_path:
                    self.sls_conf = str(conf_path)
Fang Yuedong's avatar
Fang Yuedong committed
99
        else:
Fang Yuedong's avatar
Fang Yuedong committed
100
101
            # self.sls_conf = [os.path.join(self.sls_dir, slsconfs[0]), os.path.join(self.sls_dir, slsconfs[1])]
            self.sls_conf = []
102
103
104
105
106
107
108
109
110
111
112
113
            try:
                with pkg_resources.files('ObservationSim.Instrument.data.sls_conf').joinpath(slsconfs[0]) as conf_path:
                    self.sls_conf.append(str(conf_path))
            except AttributeError:
                with pkg_resources.path('ObservationSim.Instrument.data.sls_conf', slsconfs[0]) as conf_path:
                    self.sls_conf.append(str(conf_path))
            try:
                with pkg_resources.files('ObservationSim.Instrument.data.sls_conf').joinpath(slsconfs[1]) as conf_path:
                    self.sls_conf.append(str(conf_path))
            except AttributeError:
                with pkg_resources.path('ObservationSim.Instrument.data.sls_conf', slsconfs[1]) as conf_path:
                    self.sls_conf.append(str(conf_path))
Fang Yuedong's avatar
Fang Yuedong committed
114
115
116
117
        
        self.effCurve = self._getChipEffCurve(self.filter_type)
        self._getCRdata()

Fang Yuedong's avatar
Fang Yuedong committed
118
        # Define the sensor model
119
        if "bright_fatter" in config["ins_effects"] and config["ins_effects"]["bright_fatter"] == True and self.survey_type == "photometric":
Fang Yuedong's avatar
Fang Yuedong committed
120
            self.sensor = galsim.SiliconSensor(strength=self.df_strength, treering_func=treering_func)
Fang Yuedong's avatar
Fang Yuedong committed
121
122
123
        else:
            self.sensor = galsim.Sensor()

124
125
        self.flat_cube = None # for spectroscopic flat field cube simulation

Fang Yuedong's avatar
Fang Yuedong committed
126
127
128
129
130
131
132
133
134
135
136
    def _set_attributes_from_config(self, config):
        # Default setting
        self.read_noise = 5.0   # e/pix
        self.dark_noise = 0.02  # e/pix/s
        self.rotate_angle = 0.
        self.overscan   = 1000
        # Override default values
        for key in ["gain", "bias_level, dark_exptime", "flat_exptime", "readout_time", "full_well", "read_noise", "dark_noise", "overscan"]:
            if key in config["ins_effects"]:
                setattr(self, key, config["ins_effects"][key])

Fang Yuedong's avatar
Fang Yuedong committed
137
138
139
140
141
142
143
144
145
    def _getChipRowCol(self):
        self.rowID, self.colID = self.getChipRowCol(self.chipID)

    def getChipRowCol(self, chipID):
        rowID = ((chipID - 1) % 5) + 1
        colID = 6 - ((chipID - 1) // 5)
        return rowID, colID

    def _getSurveyType(self):
146
        if self.filter_type in _util.SPEC_FILTERS:
Fang Yuedong's avatar
Fang Yuedong committed
147
            return "spectroscopic"
148
        elif self.filter_type in _util.PHOT_FILTERS:
Fang Yuedong's avatar
Fang Yuedong committed
149
            return "photometric"
Fang Yuedong's avatar
Fang Yuedong committed
150
151
        # elif self.filter_type in ["FGS"]:
        #     return "FGS"
Fang Yuedong's avatar
Fang Yuedong committed
152
153
154

    def _getChipEffCurve(self, filter_type):
        # CCD efficiency curves
155
        if filter_type in ['NUV', 'u', 'GU']: filename = 'UV0.txt'
Fang Yuedong's avatar
Fang Yuedong committed
156
        if filter_type in ['g', 'r', 'GV', 'FGS']: filename = 'Astro_MB.txt' # TODO, need to switch to the right efficiency curvey for FGS CMOS
Fang Yuedong's avatar
Fang Yuedong committed
157
        if filter_type in ['i', 'z', 'y', 'GI']: filename = 'Basic_NIR.txt'
158
159
160
161
162
163
        try:
            with pkg_resources.files('ObservationSim.Instrument.data.ccd').joinpath(filename) as ccd_path:
                table = Table.read(ccd_path, format='ascii')
        except AttributeError:
            with pkg_resources.path('ObservationSim.Instrument.data.ccd', filename) as ccd_path:
                table = Table.read(ccd_path, format='ascii')
164
        throughput = galsim.LookupTable(x=table['col1'], f=table['col2'], interpolant='linear')
Fang Yuedong's avatar
Fang Yuedong committed
165
166
167
168
        bandpass = galsim.Bandpass(throughput, wave_type='nm')
        return bandpass

    def _getCRdata(self):
169
170
171
172
173
174
        try:
            with pkg_resources.files('ObservationSim.Instrument.data').joinpath("wfc-cr-attachpixel.dat") as cr_path:
                self.attachedSizes = np.loadtxt(cr_path)
        except AttributeError:
            with pkg_resources.path('ObservationSim.Instrument.data', "wfc-cr-attachpixel.dat") as cr_path:
                self.attachedSizes = np.loadtxt(cr_path)
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
    
    def loadSLSFLATCUBE(self, flat_fn='flat_cube.fits'):
        try:
            with pkg_resources.files('ObservationSim.Instrument.data').joinpath(flat_fn) as data_path:
                flat_fits = fits.open(data_path, ignore_missing_simple=True)
        except AttributeError:
            with pkg_resources.path('ObservationSim.Instrument.data', flat_fn) as data_path:
                flat_fits = fits.open(data_path, ignore_missing_simple=True)

        fl = len(flat_fits)
        fl_sh = flat_fits[0].data.shape
        assert fl == 4, 'FLAT Field Cube is Not 4 layess!!!!!!!'
        self.flat_cube = np.zeros([fl, fl_sh[0], fl_sh[1]])
        for i in np.arange(0, fl, 1):
            self.flat_cube[i] = flat_fits[i].data
Fang Yuedong's avatar
Fang Yuedong committed
190

191
    def getChipFilter(self, chipID=None):
Fang Yuedong's avatar
Fang Yuedong committed
192
193
        """Return the filter index and type for a given chip #(chipID)
        """
194
        filter_type_list = _util.ALL_FILTERS
Fang Yuedong's avatar
Fang Yuedong committed
195
196
197
198
        if chipID == None:
            chipID = self.chipID

        # updated configurations
Fang Yuedong's avatar
Fang Yuedong committed
199
200
        if chipID>42 or chipID<1: raise ValueError("!!! Chip ID: [1,42]")
        if chipID in [6, 15, 16, 25]:  filter_type = "y"
Fang Yuedong's avatar
Fang Yuedong committed
201
        if chipID in [11, 20]:         filter_type = "z"
Fang Yuedong's avatar
Fang Yuedong committed
202
        if chipID in [7, 24]:          filter_type = "i"
Fang Yuedong's avatar
Fang Yuedong committed
203
        if chipID in [14, 17]:         filter_type = "u"
Fang Yuedong's avatar
Fang Yuedong committed
204
        if chipID in [9, 22]:          filter_type = "r"
205
        if chipID in [12, 13, 18, 19]: filter_type = "NUV"
Fang Yuedong's avatar
Fang Yuedong committed
206
207
208
209
210
        if chipID in [8, 23]:          filter_type = "g"
        if chipID in [1, 10, 21, 30]:  filter_type = "GI"
        if chipID in [2, 5, 26, 29]:   filter_type = "GV"
        if chipID in [3, 4, 27, 28]:   filter_type = "GU"
        if chipID in range(31, 43):    filter_type = 'FGS'
Fang Yuedong's avatar
Fang Yuedong committed
211
212
213
214
215
216
        filter_id = filter_type_list.index(filter_type)

        return filter_id, filter_type

    def getChipLim(self, chipID=None):
        """Calculate the edges in pixel for a given CCD chip on the focal plane
Fang Yuedong's avatar
Fang Yuedong committed
217
        NOTE: There are 5*4 CCD chips in the focus plane for photometric / spectroscopic observation.
Fang Yuedong's avatar
Fang Yuedong committed
218
219
220
221
222
223
        Parameters:
            chipID:         int
                            the index of the chip
        Returns:
            A galsim BoundsD object
        """
224
225
226
227
228
229
230
231
        xmin, xmax, ymin, ymax = 1e10, -1e10, 1e10, -1e10
        xcen = self.x_cen / self.pix_size
        ycen = self.y_cen / self.pix_size
        sign_x = [-1., 1., -1., 1.]
        sign_y = [-1., -1., 1., 1.]
        for i in range(4):
            x = xcen + sign_x[i] * self.npix_x / 2.
            y = ycen + sign_y[i] * self.npix_y / 2.
232
            x, y = _util.rotate_conterclockwise(x0=xcen, y0=ycen, x=x, y=y, angle=self.rotate_angle)
233
234
235
            xmin, xmax = min(xmin, x), max(xmax, x)
            ymin, ymax = min(ymin, y), max(ymax, y)
        return galsim.BoundsD(xmin, xmax, ymin, ymax)
Fang Yuedong's avatar
Fang Yuedong committed
236
237
238
239



    def getSkyCoverage(self, wcs):
Fang Yuedong's avatar
Fang Yuedong committed
240
        # print("In getSkyCoverage: xmin = %.3f, xmax = %.3f, ymin = %.3f, ymax = %.3f"%(self.bound.xmin, self.bound.xmax, self.bound.ymin, self.bound.ymax))
Fang Yuedong's avatar
Fang Yuedong committed
241
242
243
244
245
246
247
248
249
250
        return super().getSkyCoverage(wcs, self.bound.xmin, self.bound.xmax, self.bound.ymin, self.bound.ymax)


    def getSkyCoverageEnlarged(self, wcs, margin=0.5):
        """The enlarged sky coverage of the chip
        """
        margin /= 60.0
        bound = self.getSkyCoverage(wcs)
        return galsim.BoundsD(bound.xmin - margin, bound.xmax + margin, bound.ymin - margin, bound.ymax + margin)

Fang Yuedong's avatar
Fang Yuedong committed
251
    def isContainObj(self, ra_obj=None, dec_obj=None, x_image=None, y_image=None, wcs=None, margin=1):
Fang Yuedong's avatar
Fang Yuedong committed
252
        # magin in number of pix
Fang Yuedong's avatar
Fang Yuedong committed
253
254
255
256
257
258
259
260
        if (ra_obj is not None) and (dec_obj is not None):
            if wcs is None:
                wcs = self.img.wcs
            pos_obj = wcs.toImage(galsim.CelestialCoord(ra=ra_obj*galsim.degrees, dec=dec_obj*galsim.degrees))
            x_image, y_image = pos_obj.x, pos_obj.y
        elif (x_image is None) or (y_image is None):
            raise ValueError("Either (ra_obj, dec_obj) or (x_image, y_image) should be given")

Fang Yuedong's avatar
Fang Yuedong committed
261
262
        xmin, xmax = self.bound.xmin - margin, self.bound.xmax + margin
        ymin, ymax = self.bound.ymin - margin, self.bound.ymax + margin
Fang Yuedong's avatar
Fang Yuedong committed
263
        if (x_image - xmin) * (x_image - xmax) > 0.0 or (y_image - ymin) * (y_image - ymax) > 0.0:
Fang Yuedong's avatar
Fang Yuedong committed
264
265
266
267
268
269
270
            return False
        return True

    def getChipNoise(self, exptime=150.0):
        noise = self.dark_noise * exptime + self.read_noise**2
        return noise

Zhang Xin's avatar
Zhang Xin committed
271
    def addEffects(self, config, img, chip_output, filt, ra_cen, dec_cen, img_rot, exptime=150., pointing_ID=0, timestamp_obs=1621915200, pointing_type='SCI', sky_map=None, post_flash_map=None, tel=None, logger=None):
272
        # Set random seeds
Fang Yuedong's avatar
Fang Yuedong committed
273
274
275
276
277
278
        SeedGainNonuni=int(config["random_seeds"]["seed_gainNonUniform"])
        SeedBiasNonuni=int(config["random_seeds"]["seed_biasNonUniform"])
        SeedRnNonuni = int(config["random_seeds"]["seed_rnNonUniform"])
        SeedBadColumns = int(config["random_seeds"]["seed_badcolumns"])
        SeedDefective = int(config["random_seeds"]["seed_defective"])
        SeedCosmicRay = int(config["random_seeds"]["seed_CR"])
Fang Yuedong's avatar
Fang Yuedong committed
279
        fullwell = int(self.full_well)
Fang Yuedong's avatar
Fang Yuedong committed
280
        if config["ins_effects"]["add_hotpixels"] == True:
Fang Yuedong's avatar
Fang Yuedong committed
281
282
283
            BoolHotPix = True
        else:
            BoolHotPix = False
Fang Yuedong's avatar
Fang Yuedong committed
284
        if config["ins_effects"]["add_deadpixels"]== True:
Fang Yuedong's avatar
Fang Yuedong committed
285
286
287
            BoolDeadPix = True
        else:
            BoolDeadPix = False
288
        self.logger = logger
Fang Yuedong's avatar
Fang Yuedong committed
289

290
        # Get Poisson noise generator
291
292
        rng_poisson, poisson_noise = chip_utils.get_poisson(
            seed=int(config["random_seeds"]["seed_poisson"]) + pointing_ID*30 + self.chipID, sky_level=0.)
293

294
        # Add sky background
Fang Yuedong's avatar
Fang Yuedong committed
295
        if config["ins_effects"]["add_back"] == True:
296
297
            img, sky_map = chip_utils.add_sky_background(img=img, filt=filt, exptime=exptime, sky_map=sky_map, tel=tel)
            del sky_map
298

Fang Yuedong's avatar
Fang Yuedong committed
299
        # Apply flat-field large scale structure for one chip
Fang Yuedong's avatar
Fang Yuedong committed
300
        if config["ins_effects"]["flat_fielding"] == True:
301
302
303
            chip_utils.log_info(msg="  Creating and applying Flat-Fielding", logger=self.logger)
            chip_utils.log_info(msg=str(img.bounds), logger=self.logger)
            flat_img, flat_normal = chip_utils.get_flat(img=img, seed=int(config["random_seeds"]["seed_flat"]))
304
305
            if self.survey_type == "photometric":
                img *= flat_normal
Fang Yuedong's avatar
Fang Yuedong committed
306
            del flat_normal
Fang Yuedong's avatar
Fang Yuedong committed
307
            if config["output_setting"]["flat_output"] == False:
Fang Yuedong's avatar
Fang Yuedong committed
308
309
                del flat_img

Zhang Xin's avatar
Zhang Xin committed
310
311
312
        if post_flash_map is not None:
            img = img + post_flash_map

Fang Yuedong's avatar
Fang Yuedong committed
313
        # Apply Shutter-effect for one chip
Fang Yuedong's avatar
Fang Yuedong committed
314
        if config["ins_effects"]["shutter_effect"] == True:
315
            chip_utils.log_info(msg="  Apply shutter effect", logger=self.logger)
Fang Yuedong's avatar
Fang Yuedong committed
316
            shuttimg = effects.ShutterEffectArr(img, t_shutter=1.3, dist_bearing=735, dt=1E-3)    # shutter effect normalized image for this chip
317
318
            if self.survey_type == "photometric":
                img *= shuttimg
Fang Yuedong's avatar
Fang Yuedong committed
319
            if config["output_setting"]["shutter_output"] == True:    # output 16-bit shutter effect image with pixel value <=65535
Fang Yuedong's avatar
Fang Yuedong committed
320
321
322
323
                shutt_gsimg = galsim.ImageUS(shuttimg*6E4)
                shutt_gsimg.write("%s/ShutterEffect_%s_1.fits" % (chip_output.subdir, self.chipID))
                del shutt_gsimg
            del shuttimg
324
325
326
327
328
        # # Add Poisson noise to the resulting images
        # # (NOTE): this can only applied to the slitless image
        # # since it dose not use photon shooting to draw stamps
        # if self.survey_type == "spectroscopic":
        #     img.addNoise(poisson_noise)
Fang Yuedong's avatar
Fang Yuedong committed
329
330

        # Add cosmic-rays
331
        if config["ins_effects"]["cosmic_ray"] == True and pointing_type=='SCI':
332
333
334
335
336
            chip_utils.log_info(msg="  Adding Cosmic-Ray", logger=self.logger)
            img, crmap_gsimg, cr_event_num = chip_utils.add_cosmic_rays(img=img, chip=self, exptime=exptime, 
                                                    seed=SeedCosmicRay+pointing_ID*30+self.chipID)
            chip_utils.outputCal(
                chip=self,
Fang Yuedong's avatar
Fang Yuedong committed
337
338
339
340
341
342
343
                img=crmap_gsimg,
                ra_cen=ra_cen,
                dec_cen=dec_cen,
                img_rot=img_rot,
                im_type='CRS',
                pointing_ID=pointing_ID,
                output_dir=chip_output.subdir,
344
                exptime=exptime,
345
346
                project_cycle=config["project_cycle"],
                run_counter=config["run_counter"],
347
                timestamp=timestamp_obs)
Fang Yuedong's avatar
Fang Yuedong committed
348
349
            del crmap_gsimg

350
        # Apply PRNU effect and output PRNU flat file:
Fang Yuedong's avatar
Fang Yuedong committed
351
        if config["ins_effects"]["prnu_effect"] == True:
352
353
354
            chip_utils.log_info(msg="  Applying PRNU effect", logger=self.logger)
            img, prnu_img = chip_utils.add_PRNU(img=img, chip=self, 
                                seed=int(config["random_seeds"]["seed_prnu"]+self.chipID))
Fang Yuedong's avatar
Fang Yuedong committed
355
            if config["output_setting"]["prnu_output"] == True:
356
                prnu_img.write("%s/FlatImg_PRNU_%s.fits" % (chip_output.subdir,self.chipID))
Fang Yuedong's avatar
Fang Yuedong committed
357
            if config["output_setting"]["flat_output"] == False:
358
359
                del prnu_img

360
361
362
363
364
365
        # # Add dark current
        # if config["ins_effects"]["add_dark"] == True:
        #     dark_noise = galsim.DeviateNoise(galsim.PoissonDeviate(rng_poisson, self.dark_noise*(exptime+0.5*self.readout_time)))
        #     img.addNoise(dark_noise)

        # Add dark current & Poisson noise
366
        InputDark = False
Fang Yuedong's avatar
Fang Yuedong committed
367
        if config["ins_effects"]["add_dark"] == True:
368
369
370
371
            if InputDark:
                img = chip_utils.add_inputdark(img=img, chip=self, exptime=exptime)
            else:
                img, _ = chip_utils.add_poisson(img=img, chip=self, exptime=exptime, poisson_noise=poisson_noise)
372
373
374
375
376
377
        else:
            img, _ = chip_utils.add_poisson(img=img, chip=self, exptime=exptime, poisson_noise=poisson_noise, dark_noise=0.)

        # Add diffusion & brighter-fatter effects
        if config["ins_effects"]["bright_fatter"] == True:
            img = chip_utils.add_brighter_fatter(img=img)
378
379
380
381
382
383
384

        # Add Hot Pixels or/and Dead Pixels
        rgbadpix = Generator(PCG64(int(SeedDefective+self.chipID)))
        badfraction = 5E-5*(rgbadpix.random()*0.5+0.7)
        img = effects.DefectivePixels(img, IfHotPix=BoolHotPix, IfDeadPix=BoolDeadPix, fraction=badfraction, seed=SeedDefective+self.chipID, biaslevel=0)

        # Apply Bad lines 
Fang Yuedong's avatar
Fang Yuedong committed
385
        if config["ins_effects"]["add_badcolumns"] == True:
386
            img = effects.BadColumns(img, seed=SeedBadColumns, chipid=self.chipID, logger=self.logger)
387
388

        # Apply Nonlinearity on the chip image
Fang Yuedong's avatar
Fang Yuedong committed
389
        if config["ins_effects"]["non_linear"] == True:
390
            chip_utils.log_info(msg="  Applying Non-Linearity on the chip image", logger=self.logger)
391
392
393
            img = effects.NonLinearity(GSImage=img, beta1=5.e-7, beta2=0)

        # Apply CCD Saturation & Blooming
Fang Yuedong's avatar
Fang Yuedong committed
394
        if config["ins_effects"]["saturbloom"] == True:
395
            chip_utils.log_info(msg="  Applying CCD Saturation & Blooming", logger=self.logger)
396
397
398
            img = effects.SaturBloom(GSImage=img, nsect_x=1, nsect_y=1, fullwell=fullwell)

        # Apply CTE Effect
Fang Yuedong's avatar
Fang Yuedong committed
399
        if config["ins_effects"]["cte_trail"] == True:
400
            chip_utils.log_info(msg="  Apply CTE Effect", logger=self.logger)
401
            img = effects.CTE_Effect(GSImage=img, threshold=27)
402
403
404
405
406
407
408
409
410
411
412

        ### prescan & overscan
        if config["ins_effects"]["add_prescan"] == True:
            img = chip_utils.AddPreScan(GSImage=img, pre1=27, pre2=4, over1=71, over2=80)
        ### 1*16 output
        if config["ins_effects"]["format_output"] == True:
            img = chip_utils.formatOutput(GSImage=img)
            self.nsecy = 1
            self.nsecx = 16
                    

413
414
        # Add Bias level
        if config["ins_effects"]["add_bias"] == True:
415
            chip_utils.log_info(msg="  Adding Bias level and 16-channel non-uniformity", logger=self.logger)
416
417
418
            if config["ins_effects"]["bias_16channel"] == True:
                img = effects.AddBiasNonUniform16(img, 
                    bias_level=float(self.bias_level), 
419
                    nsecy = self.nsecy, nsecx=self.nsecx, 
420
421
422
423
                    seed=SeedBiasNonuni+self.chipID,
                    logger=self.logger)
            elif config["ins_effects"]["bias_16channel"] == False:
                img += self.bias_level
424
425

        # Add Read-out Noise
Fang Yuedong's avatar
Fang Yuedong committed
426
427
        if config["ins_effects"]["add_readout"] == True:
            seed = int(config["random_seeds"]["seed_readout"]) + pointing_ID*30 + self.chipID
428
429
430
431
432
            rng_readout = galsim.BaseDeviate(seed)
            readout_noise = galsim.GaussianNoise(rng=rng_readout, sigma=self.read_noise)
            img.addNoise(readout_noise)

        # Apply Gain & Quantization
433
        chip_utils.log_info(msg="  Applying Gain (and 16 channel non-uniformity) & Quantization", logger=self.logger)
434
        if config["ins_effects"]["gain_16channel"] == True:
435
            img, self.gain_channel = effects.ApplyGainNonUniform16(
436
                img, gain=self.gain, 
437
                nsecy = self.nsecy, nsecx=self.nsecx, 
438
439
440
441
442
                seed=SeedGainNonuni+self.chipID,
                logger=self.logger)
        elif config["ins_effects"]["gain_16channel"] == False:
            img /= self.gain
            
443
444
445
446
447
448
449
        img.array[img.array > 65535] = 65535
        img.replaceNegative(replace_value=0)
        img.quantize()

        ######################################################################################
        # Output images for calibration pointing
        ######################################################################################
Fang Yuedong's avatar
Fang Yuedong committed
450
        # Bias output
451
        if config["ins_effects"]["add_bias"] == True and config["output_setting"]["bias_output"] == True and pointing_type=='CAL':
452
453
454
455
            if self.logger is not None:
                self.logger.info("  Output N frame Bias files")
            else:
                print("  Output N frame Bias files", flush=True)
Fang Yuedong's avatar
Fang Yuedong committed
456
            NBias = int(config["output_setting"]["NBias"])
Fang Yuedong's avatar
Fang Yuedong committed
457
458
459
            for i in range(NBias):
                BiasCombImg, BiasTag = effects.MakeBiasNcomb(
                    self.npix_x, self.npix_y, 
Fang Yuedong's avatar
Fang Yuedong committed
460
                    bias_level=float(self.bias_level), 
Fang Yuedong's avatar
Fang Yuedong committed
461
                    ncombine=1, read_noise=self.read_noise, gain=1,
462
463
                    seed=SeedBiasNonuni+self.chipID,
                    logger=self.logger)
464
                # Readout noise for Biases is not generated with random seeds. So readout noise for bias images can't be reproduced.
Fang Yuedong's avatar
Fang Yuedong committed
465
466
467
                if config["ins_effects"]["cosmic_ray"] == True:
                    if config["ins_effects"]["cray_differ"] == True:
                        cr_map, cr_event_num = effects.produceCR_Map(
Fang Yuedong's avatar
Fang Yuedong committed
468
469
                            xLen=self.npix_x, yLen=self.npix_y, 
                            exTime=0.01, 
Fang Yuedong's avatar
Fang Yuedong committed
470
                            cr_pixelRatio=0.003*(0.01+0.5*self.readout_time)/150., 
Fang Yuedong's avatar
Fang Yuedong committed
471
472
473
474
475
476
477
                            gain=self.gain, 
                            attachedSizes=self.attachedSizes,
                            seed=SeedCosmicRay+pointing_ID*30+self.chipID+1)
                            # seed: obj-imaging:+0; bias:+1; dark:+2; flat:+3;
                    BiasCombImg += cr_map
                    del cr_map

Fang Yuedong's avatar
Fang Yuedong committed
478
                # Non-Linearity for Bias
Fang Yuedong's avatar
Fang Yuedong committed
479
                if config["ins_effects"]["non_linear"] == True:
480
481
482
483
                    if self.logger is not None:
                        self.logger.info("  Applying Non-Linearity on the Bias image")
                    else:
                        print("  Applying Non-Linearity on the Bias image", flush=True)
484
485
486
                    BiasCombImg = effects.NonLinearity(GSImage=BiasCombImg, beta1=5.e-7, beta2=0)

                # Apply Bad lines 
Fang Yuedong's avatar
Fang Yuedong committed
487
                if config["ins_effects"]["add_badcolumns"] == True:
Fang Yuedong's avatar
Fang Yuedong committed
488
                    BiasCombImg = effects.BadColumns(BiasCombImg-float(self.bias_level)+5, seed=SeedBadColumns, chipid=self.chipID, logger=self.logger) + float(self.bias_level)-5
Fang Yuedong's avatar
Fang Yuedong committed
489

490
                BiasCombImg, self.gain_channel = effects.ApplyGainNonUniform16(BiasCombImg, gain=self.gain,
Fang Yuedong's avatar
Fang Yuedong committed
491
                    nsecy = 2, nsecx=8, 
492
493
                    seed=SeedGainNonuni+self.chipID,
                    logger=self.logger)
Fang Yuedong's avatar
Fang Yuedong committed
494
495
                # BiasCombImg = effects.AddOverscan(
                #     BiasCombImg, 
Fang Yuedong's avatar
Fang Yuedong committed
496
                #     overscan=float(config["ins_effects"]["bias_level"])-2, gain=self.gain, 
Fang Yuedong's avatar
Fang Yuedong committed
497
498
499
500
                #     widthl=27, widthr=27, widtht=8, widthb=8)
                BiasCombImg.replaceNegative(replace_value=0)
                BiasCombImg.quantize()
                BiasCombImg = galsim.ImageUS(BiasCombImg)
501
                timestamp_obs += 10 * 60
502
503
                chip_utils.outputCal(
                    chip=self,
Fang Yuedong's avatar
Fang Yuedong committed
504
505
506
507
                    img=BiasCombImg,
                    ra_cen=ra_cen,
                    dec_cen=dec_cen,
                    img_rot=img_rot,
Xin Zhang's avatar
Xin Zhang committed
508
                    im_type='BIAS',
Fang Yuedong's avatar
Fang Yuedong committed
509
510
                    pointing_ID=pointing_ID,
                    output_dir=chip_output.subdir,
511
                    exptime=0.0,
512
513
                    project_cycle=config["project_cycle"],
                    run_counter=config["run_counter"],
514
                    timestamp=timestamp_obs)
Fang Yuedong's avatar
Fang Yuedong committed
515
516
517
            del BiasCombImg

        # Export combined (ncombine, Vignetting + PRNU) & single vignetting flat-field file
518
        if config["ins_effects"]["flat_fielding"] == True and config["output_setting"]["flat_output"] == True and pointing_type=='CAL':
519
520
521
522
            if self.logger is not None:
                self.logger.info("  Output N frame Flat-Field files")
            else:
                print("  Output N frame Flat-Field files", flush=True)
Fang Yuedong's avatar
Fang Yuedong committed
523
            NFlat = int(config["output_setting"]["NFlat"])
Fang Yuedong's avatar
Fang Yuedong committed
524
            if config["ins_effects"]["add_bias"] == True:
Fang Yuedong's avatar
Fang Yuedong committed
525
526
                biaslevel = self.bias_level
                overscan = biaslevel-2
527
            elif config["ins_effects"]["add_bias"] == False:
Fang Yuedong's avatar
Fang Yuedong committed
528
529
                biaslevel = 0
                overscan = 0
530
            darklevel = self.dark_noise*(self.flat_exptime+0.5*self.readout_time)
Fang Yuedong's avatar
Fang Yuedong committed
531
532
533
534
535
536
537
538
            for i in range(NFlat):
                FlatSingle = flat_img * prnu_img + darklevel
                FlatCombImg, FlatTag = effects.MakeFlatNcomb(
                    flat_single_image=FlatSingle, 
                    ncombine=1, 
                    read_noise=self.read_noise,
                    gain=1, 
                    overscan=overscan, 
539
                    biaslevel=0,
540
541
                    seed_bias=SeedDefective+self.chipID,
                    logger=self.logger
Fang Yuedong's avatar
Fang Yuedong committed
542
                    )
Fang Yuedong's avatar
Fang Yuedong committed
543
544
545
                if config["ins_effects"]["cosmic_ray"] == True:
                    if config["ins_effects"]["cray_differ"] == True:
                        cr_map, cr_event_num = effects.produceCR_Map(
Fang Yuedong's avatar
Fang Yuedong committed
546
                            xLen=self.npix_x, yLen=self.npix_y, 
547
                            exTime=self.flat_exptime+0.5*self.readout_time, 
Fang Yuedong's avatar
Fang Yuedong committed
548
                            cr_pixelRatio=0.003*(self.flat_exptime+0.5*self.readout_time)/150., 
Fang Yuedong's avatar
Fang Yuedong committed
549
550
551
552
                            gain=self.gain, 
                            attachedSizes=self.attachedSizes,
                            seed=SeedCosmicRay+pointing_ID*30+self.chipID+3)
                            # seed: obj-imaging:+0; bias:+1; dark:+2; flat:+3;
Fang Yuedong's avatar
Fang Yuedong committed
553
                    FlatCombImg += cr_map
Fang Yuedong's avatar
Fang Yuedong committed
554
                    del cr_map
Fang Yuedong's avatar
Fang Yuedong committed
555

Fang Yuedong's avatar
Fang Yuedong committed
556
                if config["ins_effects"]["non_linear"] == True:
557
558
559
560
                    if self.logger is not None:
                        self.logger.info("  Applying Non-Linearity on the Flat image")
                    else:
                        print("  Applying Non-Linearity on the Flat image", flush=True)
561
                    FlatCombImg = effects.NonLinearity(GSImage=FlatCombImg, beta1=5.e-7, beta2=0)
Fang Yuedong's avatar
Fang Yuedong committed
562

Fang Yuedong's avatar
Fang Yuedong committed
563
                if config["ins_effects"]["cte_trail"] == True:
Fang Yuedong's avatar
Fang Yuedong committed
564
565
                    FlatCombImg = effects.CTE_Effect(GSImage=FlatCombImg, threshold=3)

566
567
568
569
570
                # Add Hot Pixels or/and Dead Pixels
                rgbadpix = Generator(PCG64(int(SeedDefective+self.chipID)))
                badfraction = 5E-5*(rgbadpix.random()*0.5+0.7)
                FlatCombImg = effects.DefectivePixels(FlatCombImg, IfHotPix=BoolHotPix, IfDeadPix=BoolDeadPix, fraction=badfraction, seed=SeedDefective+self.chipID, biaslevel=0)

Fang Yuedong's avatar
Fang Yuedong committed
571
                # Apply Bad lines 
Fang Yuedong's avatar
Fang Yuedong committed
572
                if config["ins_effects"]["add_badcolumns"] == True:
573
                    FlatCombImg = effects.BadColumns(FlatCombImg, seed=SeedBadColumns, chipid=self.chipID, logger=self.logger)
Fang Yuedong's avatar
Fang Yuedong committed
574

575
                # Add Bias level
Fang Yuedong's avatar
Fang Yuedong committed
576
                if config["ins_effects"]["add_bias"] == True:
577
578
579
580
                    if self.logger is not None:
                        self.logger.info("  Adding Bias level and 16-channel non-uniformity")
                    else:
                        print("  Adding Bias level and 16-channel non-uniformity")
Fang Yuedong's avatar
Fang Yuedong committed
581
                    # img += float(config["ins_effects"]["bias_level"])
582
583
584
                    FlatCombImg = effects.AddBiasNonUniform16(FlatCombImg, 
                        bias_level=biaslevel, 
                        nsecy = 2, nsecx=8, 
585
586
                        seed=SeedBiasNonuni+self.chipID,
                        logger=self.logger)
587
588
                
                # Add Read-out Noise
Fang Yuedong's avatar
Fang Yuedong committed
589
                if config["ins_effects"]["add_readout"] == True:
590
                    seed = int(config["random_seeds"]["seed_readout"]) + pointing_ID*30 + self.chipID + 3
591
592
593
                    rng_readout = galsim.BaseDeviate(seed)
                    readout_noise = galsim.GaussianNoise(rng=rng_readout, sigma=self.read_noise)
                    FlatCombImg.addNoise(readout_noise)
Fang Yuedong's avatar
Fang Yuedong committed
594

595
                FlatCombImg, self.gain_channel = effects.ApplyGainNonUniform16(FlatCombImg, gain=self.gain,
Fang Yuedong's avatar
Fang Yuedong committed
596
                    nsecy = 2, nsecx=8, 
597
598
                    seed=SeedGainNonuni+self.chipID,
                    logger=self.logger)
Fang Yuedong's avatar
Fang Yuedong committed
599
600
601
602
                # FlatCombImg = effects.AddOverscan(FlatCombImg, overscan=overscan, gain=self.gain, widthl=27, widthr=27, widtht=8, widthb=8)
                FlatCombImg.replaceNegative(replace_value=0)
                FlatCombImg.quantize()
                FlatCombImg = galsim.ImageUS(FlatCombImg)
603
                timestamp_obs += 10 * 60
604
605
                chip_utils.outputCal(
                    chip=self,
Fang Yuedong's avatar
Fang Yuedong committed
606
607
608
609
                    img=FlatCombImg,
                    ra_cen=ra_cen,
                    dec_cen=dec_cen,
                    img_rot=img_rot,
Xin Zhang's avatar
Xin Zhang committed
610
                    im_type='FLAT',
Fang Yuedong's avatar
Fang Yuedong committed
611
612
                    pointing_ID=pointing_ID,
                    output_dir=chip_output.subdir,
613
                    exptime=self.flat_exptime,
614
615
                    project_cycle=config["project_cycle"],
                    run_counter=config["run_counter"],
616
                    timestamp=timestamp_obs)
Fang Yuedong's avatar
Fang Yuedong committed
617

Fang Yuedong's avatar
Fang Yuedong committed
618
619
620
621
622
623
624
            del FlatCombImg, FlatSingle, prnu_img
            # flat_img.replaceNegative(replace_value=0)
            # flat_img.quantize()
            # galsim.ImageUS(flat_img).write("%s/FlatImg_Vignette_%s.fits" % (chip_output.subdir, self.chipID))
            del flat_img

        # Export Dark current images
625
        if config["ins_effects"]["add_dark"] == True and config["output_setting"]["dark_output"] == True and pointing_type=='CAL':
626
627
628
629
            if self.logger is not None:
                self.logger.info("  Output N frame Dark Current files")
            else:
                print("  Output N frame Dark Current files", flush=True)
Fang Yuedong's avatar
Fang Yuedong committed
630
            NDark = int(config["output_setting"]["NDark"])
Fang Yuedong's avatar
Fang Yuedong committed
631
            if config["ins_effects"]["add_bias"] == True:
Fang Yuedong's avatar
Fang Yuedong committed
632
633
                biaslevel = self.bias_level
                overscan = biaslevel-2
634
            elif config["ins_effects"]["add_bias"] == False:
Fang Yuedong's avatar
Fang Yuedong committed
635
636
637
638
639
                biaslevel = 0
                overscan = 0
            for i in range(NDark):
                DarkCombImg, DarkTag = effects.MakeDarkNcomb(
                    self.npix_x, self.npix_y, 
640
                    overscan=overscan, bias_level=0, darkpsec=0.02, exptime=self.dark_exptime+0.5*self.readout_time,
Fang Yuedong's avatar
Fang Yuedong committed
641
                    ncombine=1, read_noise=self.read_noise, 
642
643
                    gain=1, seed_bias=SeedBiasNonuni+self.chipID,
                    logger=self.logger)
Fang Yuedong's avatar
Fang Yuedong committed
644
645
646
                if config["ins_effects"]["cosmic_ray"] == True:
                    if config["ins_effects"]["cray_differ"] == True:
                        cr_map, cr_event_num = effects.produceCR_Map(
Fang Yuedong's avatar
Fang Yuedong committed
647
                            xLen=self.npix_x, yLen=self.npix_y, 
648
                            exTime=self.dark_exptime+0.5*self.readout_time, 
Fang Yuedong's avatar
Fang Yuedong committed
649
                            cr_pixelRatio=0.003*(self.dark_exptime+0.5*self.readout_time)/150., 
Fang Yuedong's avatar
Fang Yuedong committed
650
651
652
653
                            gain=self.gain, 
                            attachedSizes=self.attachedSizes,
                            seed=SeedCosmicRay+pointing_ID*30+self.chipID+2)
                            # seed: obj-imaging:+0; bias:+1; dark:+2; flat:+3;
Fang Yuedong's avatar
Fang Yuedong committed
654
                    DarkCombImg += cr_map
Fang Yuedong's avatar
Fang Yuedong committed
655
656
657
658
                    cr_map[cr_map > 65535] = 65535
                    cr_map[cr_map < 0] = 0
                    crmap_gsimg = galsim.Image(cr_map, dtype=np.uint16)
                    del cr_map
659
660
                    chip_utils.outputCal(
                        chip=self,
Fang Yuedong's avatar
Fang Yuedong committed
661
662
663
664
665
666
667
                        img=crmap_gsimg,
                        ra_cen=ra_cen,
                        dec_cen=dec_cen,
                        img_rot=img_rot,
                        im_type='CRD',
                        pointing_ID=pointing_ID,
                        output_dir=chip_output.subdir,
668
                        exptime=self.dark_exptime,
669
670
                        project_cycle=config["project_cycle"],
                        run_counter=config["run_counter"],
671
                        timestamp=timestamp_obs)
Fang Yuedong's avatar
Fang Yuedong committed
672
                    del crmap_gsimg
Fang Yuedong's avatar
Fang Yuedong committed
673
674

                # Non-Linearity for Dark
Fang Yuedong's avatar
Fang Yuedong committed
675
                if config["ins_effects"]["non_linear"] == True:
676
677
678
679
                    if self.logger is not None:
                        self.logger.info("  Applying Non-Linearity on the Dark image")
                    else:
                        print("  Applying Non-Linearity on the Dark image", flush=True)
680
                    DarkCombImg = effects.NonLinearity(GSImage=DarkCombImg, beta1=5.e-7, beta2=0)
Fang Yuedong's avatar
Fang Yuedong committed
681

Fang Yuedong's avatar
Fang Yuedong committed
682
                if config["ins_effects"]["cte_trail"] == True:
Fang Yuedong's avatar
Fang Yuedong committed
683
684
                    DarkCombImg = effects.CTE_Effect(GSImage=DarkCombImg, threshold=3)

685
686
687
688
689
                # Add Hot Pixels or/and Dead Pixels
                rgbadpix = Generator(PCG64(int(SeedDefective+self.chipID)))
                badfraction = 5E-5*(rgbadpix.random()*0.5+0.7)
                DarkCombImg = effects.DefectivePixels(DarkCombImg, IfHotPix=BoolHotPix, IfDeadPix=BoolDeadPix, fraction=badfraction, seed=SeedDefective+self.chipID, biaslevel=0)

Fang Yuedong's avatar
Fang Yuedong committed
690
                # Apply Bad lines 
Fang Yuedong's avatar
Fang Yuedong committed
691
                if config["ins_effects"]["add_badcolumns"] == True:
692
                    DarkCombImg = effects.BadColumns(DarkCombImg, seed=SeedBadColumns, chipid=self.chipID, logger=self.logger)
Fang Yuedong's avatar
Fang Yuedong committed
693

694
                # Add Bias level
Fang Yuedong's avatar
Fang Yuedong committed
695
                if config["ins_effects"]["add_bias"] == True:
696
697
698
699
                    if self.logger is not None:
                        self.logger.info("  Adding Bias level and 16-channel non-uniformity")
                    else:
                        print("  Adding Bias level and 16-channel non-uniformity")
Fang Yuedong's avatar
Fang Yuedong committed
700
                    # img += float(config["ins_effects"]["bias_level"])
701
702
703
                    DarkCombImg = effects.AddBiasNonUniform16(DarkCombImg, 
                        bias_level=biaslevel, 
                        nsecy = 2, nsecx=8, 
704
705
                        seed=SeedBiasNonuni+self.chipID,
                        logger=self.logger)
706
707

                # Add Read-out Noise
Fang Yuedong's avatar
Fang Yuedong committed
708
                if config["ins_effects"]["add_readout"] == True:
709
                    seed = int(config["random_seeds"]["seed_readout"]) + pointing_ID*30 + self.chipID + 2
710
711
712
                    rng_readout = galsim.BaseDeviate(seed)
                    readout_noise = galsim.GaussianNoise(rng=rng_readout, sigma=self.read_noise)
                    DarkCombImg.addNoise(readout_noise)
Fang Yuedong's avatar
Fang Yuedong committed
713

714
                DarkCombImg, self.gain_channel = effects.ApplyGainNonUniform16(
Fang Yuedong's avatar
Fang Yuedong committed
715
716
                    DarkCombImg, gain=self.gain, 
                    nsecy = 2, nsecx=8, 
717
718
                    seed=SeedGainNonuni+self.chipID,
                    logger=self.logger)
Fang Yuedong's avatar
Fang Yuedong committed
719
720
721
722
723
724
725
                # DarkCombImg = effects.AddOverscan(
                #     DarkCombImg, 
                #     overscan=overscan, gain=self.gain, 
                #     widthl=27, widthr=27, widtht=8, widthb=8)
                DarkCombImg.replaceNegative(replace_value=0)
                DarkCombImg.quantize()
                DarkCombImg = galsim.ImageUS(DarkCombImg)
726
                timestamp_obs += 10 * 60
727
728
                chip_utils.outputCal(
                    chip=chip,
Fang Yuedong's avatar
Fang Yuedong committed
729
730
731
732
                    img=DarkCombImg,
                    ra_cen=ra_cen,
                    dec_cen=dec_cen,
                    img_rot=img_rot,
Xin Zhang's avatar
Xin Zhang committed
733
                    im_type='DARK',
Fang Yuedong's avatar
Fang Yuedong committed
734
735
                    pointing_ID=pointing_ID,
                    output_dir=chip_output.subdir,
736
                    exptime=self.dark_exptime,
737
738
                    project_cycle=config["project_cycle"],
                    run_counter=config["run_counter"],
739
                    timestamp = timestamp_obs)
Fang Yuedong's avatar
Fang Yuedong committed
740
741
742
743
            del DarkCombImg
        # img = galsim.ImageUS(img)

        # # 16 output channel, with each a single image file
Fang Yuedong's avatar
Fang Yuedong committed
744
        # if config["ins_effects"]["readout16"] == True:
Fang Yuedong's avatar
Fang Yuedong committed
745
746
747
748
749
750
751
752
753
754
755
756
        #     print("  16 Output Channel simulation")
        #     for coli in [0, 1]:
        #         for rowi in range(8):
        #             sub_img = effects.readout16(
        #                 GSImage=img, 
        #                 rowi=rowi, 
        #                 coli=coli, 
        #                 overscan_value=self.overscan)
        #             rowcoltag = str(rowi) + str(coli)
        #             img_name_root = chip_output.img_name.split(".")[0]
        #             sub_img.write("%s/%s_%s.fits" % (chip_output.subdir, img_name_root, rowcoltag))
        #     del sub_img
Zhang Xin's avatar
Zhang Xin committed
757
        return img
758