MockObject.py 23.9 KB
Newer Older
Wei Chengliang's avatar
Wei Chengliang committed
1
import os
Fang Yuedong's avatar
Fang Yuedong committed
2
3
4
import galsim
import numpy as np
import astropy.constants as cons
Fang Yuedong's avatar
Fang Yuedong committed
5
from astropy import wcs
Fang Yuedong's avatar
Fang Yuedong committed
6
from astropy.table import Table
Wei Chengliang's avatar
Wei Chengliang committed
7
import astropy.io.fits as fitsio
8

Zhang Xin's avatar
Zhang Xin committed
9
from ObservationSim.MockObject._util import magToFlux, VC_A, convolveGaussXorders, convolveImg
10
11
from ObservationSim.MockObject._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, \
    getABMAG
12
from ObservationSim.MockObject.SpecDisperser import SpecDisperser
Fang Yuedong's avatar
Fang Yuedong committed
13

14

Fang Yuedong's avatar
Fang Yuedong committed
15
class MockObject(object):
16
    def __init__(self, param, logger=None):
Fang Yuedong's avatar
Fang Yuedong committed
17
        self.param = param
Fang Yuedong's avatar
Fang Yuedong committed
18
19
20
        for key in self.param:
            setattr(self, key, self.param[key])
        
Fang Yuedong's avatar
Fang Yuedong committed
21
22
23
24
25
26
        if self.param["star"] == 0:
            self.type = "galaxy"
        elif self.param["star"] == 1:
            self.type = "star"
        elif self.param["star"] == 2:
            self.type = "quasar"
Fang Yuedong's avatar
Fang Yuedong committed
27
28
29
30
        ###mock_stamp_START
        elif self.param["star"] == 3:
            self.type = "stamp"
        ###mock_stamp_END
Zhang Xin's avatar
Zhang Xin committed
31
32
33
34
35
        ###for calibration
        elif self.param["star"] == 4:
            self.type = "calib"
        ###END

36
        self.sed = None
37
        self.fd_shear = None
38
        # Place holder for outputs
39
        self.additional_output_str = ""
40
41
        self.logger = logger

Fang Yuedong's avatar
Fang Yuedong committed
42
43
44
    def getMagFilter(self, filt):
        if filt.filter_type in ["GI", "GV", "GU"]:
            return self.param["mag_use_normal"]
Fang Yuedong's avatar
Fang Yuedong committed
45
        return self.param["mag_%s" % filt.filter_type.lower()]
46

47
    def getFluxFilter(self, filt):
Fang Yuedong's avatar
Fang Yuedong committed
48
        return self.param["flux_%s" % filt.filter_type.lower()]
Fang Yuedong's avatar
Fang Yuedong committed
49
50

    def getNumPhotons(self, flux, tel, exptime=150.):
51
        pupil_area = tel.pupil_area * (100.) ** 2  # m^2 to cm^2
Fang Yuedong's avatar
Fang Yuedong committed
52
53
54
        return flux * pupil_area * exptime

    def getElectronFluxFilt(self, filt, tel, exptime=150.):
55
56
57
58
59
60
        # photonEnergy = filt.getPhotonE()
        # flux = magToFlux(self.getMagFilter(filt))
        # factor = 1.0e4 * flux/photonEnergy * VC_A * (1.0/filt.blue_limit - 1.0/filt.red_limit)
        # return factor * filt.efficiency * tel.pupil_area * exptime
        flux = self.getFluxFilter(filt)
        return flux * tel.pupil_area * exptime
Fang Yuedong's avatar
Fang Yuedong committed
61
62
63
64

    def getPosWorld(self):
        ra = self.param["ra"]
        dec = self.param["dec"]
65
        return galsim.CelestialCoord(ra=ra * galsim.degrees, dec=dec * galsim.degrees)
Fang Yuedong's avatar
Fang Yuedong committed
66

67
    def getPosImg_Offset_WCS(self, img, fdmodel=None, chip=None, verbose=True, chip_wcs=None, img_header=None):
Fang Yuedong's avatar
Fang Yuedong committed
68
69
        self.posImg = img.wcs.toImage(self.getPosWorld())
        self.localWCS = img.wcs.local(self.posImg)
70
        # Apply field distortion model
Fang Yuedong's avatar
Fang Yuedong committed
71
72
73
74
        if (fdmodel is not None) and (chip is not None):
            if verbose:
                print("\n")
                print("Before field distortion:\n")
75
                print("x = %.2f, y = %.2f\n" % (self.posImg.x, self.posImg.y), flush=True)
Fang Yuedong's avatar
Fang Yuedong committed
76
            self.posImg, self.fd_shear = fdmodel.get_distorted(chip=chip, pos_img=self.posImg)
Fang Yuedong's avatar
Fang Yuedong committed
77
78
            if verbose:
                print("After field distortion:\n")
79
                print("x = %.2f, y = %.2f\n" % (self.posImg.x, self.posImg.y), flush=True)
80
        
Fang Yuedong's avatar
Fang Yuedong committed
81
82
83
84
85
86
        x, y = self.posImg.x + 0.5, self.posImg.y + 0.5
        self.x_nominal = int(np.floor(x + 0.5))
        self.y_nominal = int(np.floor(y + 0.5))
        dx = x - self.x_nominal
        dy = y - self.y_nominal
        self.offset = galsim.PositionD(dx, dy)
87
        
88
        # Deal with chip rotation
89
        if chip_wcs is not None:
90
            self.chip_wcs = chip_wcs
91
        elif img_header is not None:
92
            self.chip_wcs = galsim.FitsWCS(header=img_header)
xin's avatar
xin committed
93
        else:
94
            self.chip_wcs = None
xin's avatar
xin committed
95

96
        return self.posImg, self.offset, self.localWCS, self.chip_wcs, self.fd_shear
xin's avatar
xin committed
97

98
    def getRealPos(self, img, global_x=0., global_y=0., img_real_wcs=None):
xin's avatar
xin committed
99
100
101
102
103
        img_global_pos = galsim.PositionD(global_x, global_y)
        cel_pos = img.wcs.toWorld(img_global_pos)
        realPos = img_real_wcs.toImage(cel_pos)
        return realPos

104
    def drawObj_multiband(self, tel, pos_img, psf_model, bandpass_list, filt, chip, nphotons_tot=None, g1=0, g2=0,
Fang Yuedong's avatar
Fang Yuedong committed
105
                          exptime=150., fd_shear=None):
Fang Yuedong's avatar
Fang Yuedong committed
106
107
108
109
110
111
112
113
        if nphotons_tot == None:
            nphotons_tot = self.getElectronFluxFilt(filt, tel, exptime)
        # print("nphotons_tot = ", nphotons_tot)

        try:
            full = integrate_sed_bandpass(sed=self.sed, bandpass=filt.bandpass_full)
        except Exception as e:
            print(e)
114
115
            if self.logger:
                self.logger.error(e)
Fang Yuedong's avatar
Fang Yuedong committed
116
            return 2, None
Fang Yuedong's avatar
Fang Yuedong committed
117

118
        # Set Galsim Parameters
Fang Yuedong's avatar
Fang Yuedong committed
119
120
121
122
123
        if self.getMagFilter(filt) <= 15:
            folding_threshold = 5.e-4
        else:
            folding_threshold = 5.e-3
        gsp = galsim.GSParams(folding_threshold=folding_threshold)
124
125
        
        # Get real image position of object (deal with chip rotation w.r.t its center)
126
        self.real_pos = self.getRealPos(chip.img, global_x=self.posImg.x, global_y=self.posImg.y,
127
                                        img_real_wcs=self.chip_wcs)
xin's avatar
xin committed
128
        x, y = self.real_pos.x + 0.5, self.real_pos.y + 0.5
xin's avatar
xin committed
129
130
131
132
133
        x_nominal = int(np.floor(x + 0.5))
        y_nominal = int(np.floor(y + 0.5))
        dx = x - x_nominal
        dy = y - y_nominal
        offset = galsim.PositionD(dx, dy)
134
135
136
        # Get real local wcs of object (deal with chip rotation w.r.t its center)
        chip_wcs_local = self.chip_wcs.local(self.real_pos)
        is_updated = 0
xin's avatar
xin committed
137

138
        # Loop over all sub-bandpasses
Fang Yuedong's avatar
Fang Yuedong committed
139
140
141
142
143
144
        for i in range(len(bandpass_list)):
            bandpass = bandpass_list[i]
            try:
                sub = integrate_sed_bandpass(sed=self.sed, bandpass=bandpass)
            except Exception as e:
                print(e)
145
146
                if self.logger:
                    self.logger.error(e)
Fang Yuedong's avatar
Fang Yuedong committed
147
                continue
148
            ratio = sub / full
Fang Yuedong's avatar
Fang Yuedong committed
149
150
151
152
            if not (ratio == -1 or (ratio != ratio)):
                nphotons = ratio * nphotons_tot
            else:
                continue
153
154

            # nphotons_sum += nphotons
Fang Yuedong's avatar
Fang Yuedong committed
155
            # print("nphotons_sub-band_%d = %.2f"%(i, nphotons))
156
157
            
            # Get PSF model
158
159
            psf, pos_shear = psf_model.get_PSF(chip=chip, pos_img=pos_img, bandpass=bandpass,
                                               folding_threshold=folding_threshold)
160
161
162
163
            # star = galsim.DeltaFunction(gsparams=gsp)
            # star = star.withFlux(nphotons)
            # star = galsim.Convolve(psf, star)
            star = psf.withFlux(nphotons)
Fang Yuedong's avatar
Fang Yuedong committed
164

165
166
167
168
169
170
171
172
173
174
175
            stamp = star.drawImage(wcs=chip_wcs_local, offset=offset)
            if np.sum(np.isnan(stamp.array)) > 0:
                continue
            stamp.setCenter(x_nominal, y_nominal)
            bounds = stamp.bounds & galsim.BoundsI(0, chip.npix_x - 1, 0, chip.npix_y - 1)
            if bounds.area() > 0:
                chip.img.setOrigin(0, 0)
                chip.img[bounds] += stamp[bounds]
                is_updated = 1
                chip.img.setOrigin(chip.bound.xmin, chip.bound.ymin)
                del stamp
Fang Yuedong's avatar
Fang Yuedong committed
176
        
177
178
        if is_updated == 0:
            # Return code 0: object has missed this detector
Fang Yuedong's avatar
Fang Yuedong committed
179
            print("obj %s missed"%(self.id))
180
181
            if self.logger:
                self.logger.info("obj %s missed"%(self.id))
Fang Yuedong's avatar
Fang Yuedong committed
182
183
            return 0, pos_shear
        return 1, pos_shear # Return code 1: draw sucesss
Fang Yuedong's avatar
Fang Yuedong committed
184

185
    def addSLStoChipImage(self, sdp=None, chip=None, xOrderSigPlus=None, local_wcs=None):
Xin Zhang's avatar
Xin Zhang committed
186
187
188
        spec_orders = sdp.compute_spec_orders()
        for k, v in spec_orders.items():
            img_s = v[0]
Fang Yuedong's avatar
Fang Yuedong committed
189
190
191
192
193
194
195
196
197
            #########################################################
            # DEBUG
            #########################################################
            # print("before convolveGaussXorders, img_s:", img_s)
            nan_ids = np.isnan(img_s)
            if img_s[nan_ids].shape[0] > 0:
                # img_s[nan_ids] = 0
                print("DEBUG: before convolveGaussXorders specImg nan num is", img_s[nan_ids].shape[0])
            #########################################################
Xin Zhang's avatar
Xin Zhang committed
198
199
200
            img_s, orig_off = convolveGaussXorders(img_s, xOrderSigPlus[k])
            origin_order_x = v[1] - orig_off
            origin_order_y = v[2] - orig_off
Fang Yuedong's avatar
Fang Yuedong committed
201
202
203
204
205
206
207
208
209
210

            #########################################################
            # DEBUG
            #########################################################
            # print("DEBUG: orig_off is", orig_off)
            nan_ids = np.isnan(img_s)
            if img_s[nan_ids].shape[0] > 0:
                img_s[nan_ids] = 0
                print("DEBUG: specImg nan num is", img_s[nan_ids].shape[0])
            #########################################################
Xin Zhang's avatar
Xin Zhang committed
211
212
213
214
215
216
217
218
            specImg = galsim.ImageF(img_s)
            photons = galsim.PhotonArray.makeFromImage(specImg)
            photons.x += origin_order_x
            photons.y += origin_order_y

            xlen_imf = int(specImg.xmax - specImg.xmin + 1)
            ylen_imf = int(specImg.ymax - specImg.ymin + 1)
            stamp = galsim.ImageF(xlen_imf, ylen_imf)
xin's avatar
xin committed
219
            stamp.wcs = local_wcs
Xin Zhang's avatar
Xin Zhang committed
220
221
            stamp.setOrigin(origin_order_x, origin_order_y)

222
            bounds = stamp.bounds & galsim.BoundsI(0, chip.npix_x - 1, 0, chip.npix_y - 1)
Xin Zhang's avatar
Xin Zhang committed
223
224
            if bounds.area() == 0:
                continue
xin's avatar
xin committed
225
            chip.img.setOrigin(0, 0)
Xin Zhang's avatar
Xin Zhang committed
226
227
228
            stamp[bounds] = chip.img[bounds]
            chip.sensor.accumulate(photons, stamp)
            chip.img[bounds] = stamp[bounds]
xin's avatar
xin committed
229
            chip.img.setOrigin(chip.bound.xmin, chip.bound.ymin)
Xin Zhang's avatar
Xin Zhang committed
230
231
232
            del stamp
        del spec_orders

Zhang Xin's avatar
Zhang Xin committed
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
    def addSLStoChipImageWithPSF(self, sdp=None, chip=None, pos_img_local = [1,1], psf_model=None, bandNo = 1, grating_split_pos=3685, local_wcs=None, pos_img=None):
        spec_orders = sdp.compute_spec_orders()
        for k, v in spec_orders.items():
            img_s = v[0]
            # print(bandNo,k)
            try:
                psf, pos_shear = psf_model.get_PSF(chip, pos_img_local = pos_img_local, bandNo = bandNo, galsimGSObject=True, g_order = k, grating_split_pos=grating_split_pos)
            except:
                psf, pos_shear = psf_model.get_PSF(chip=chip, pos_img=pos_img)

            psf_img = psf.drawImage(nx=100, ny=100, wcs = local_wcs)

            psf_img_m = psf_img.array

            #########################################################
            # DEBUG
            #########################################################
            # ids_p = psf_img_m < 0
            # psf_img_m[ids_p] = 0

            # from astropy.io import fits
            # fits.writeto(str(bandNo) + '_' + str(k) + '_psf.fits', psf_img_m)

            # print("DEBUG: orig_off is", orig_off)
            nan_ids = np.isnan(img_s)
            if img_s[nan_ids].shape[0] > 0:
                img_s[nan_ids] = 0
                print("DEBUG: specImg nan num is", img_s[nan_ids].shape[0])
            #########################################################
            img_s, orig_off = convolveImg(img_s, psf_img_m)
            origin_order_x = v[1] - orig_off[0]
            origin_order_y = v[2] - orig_off[1]


            specImg = galsim.ImageF(img_s)
            # photons = galsim.PhotonArray.makeFromImage(specImg)
            # photons.x += origin_order_x
            # photons.y += origin_order_y

            # xlen_imf = int(specImg.xmax - specImg.xmin + 1)
            # ylen_imf = int(specImg.ymax - specImg.ymin + 1)
            # stamp = galsim.ImageF(xlen_imf, ylen_imf)
            # stamp.wcs = local_wcs
            # stamp.setOrigin(origin_order_x, origin_order_y)

            specImg.wcs = local_wcs
            specImg.setOrigin(origin_order_x, origin_order_y)

            bounds = specImg.bounds & galsim.BoundsI(0, chip.npix_x - 1, 0, chip.npix_y - 1)
            if bounds.area() == 0:
                continue
            chip.img.setOrigin(0, 0)
            chip.img[bounds] = chip.img[bounds] + specImg[bounds]
            # stamp[bounds] = chip.img[bounds]
            # # chip.sensor.accumulate(photons, stamp)
            # chip.img[bounds] = stamp[bounds]
            chip.img.setOrigin(chip.bound.xmin, chip.bound.ymin)
            # del stamp
        del spec_orders
        return pos_shear

Fang Yuedong's avatar
Fang Yuedong committed
294
    def drawObj_slitless(self, tel, pos_img, psf_model, bandpass_list, filt, chip, nphotons_tot=None, g1=0, g2=0,
Fang Yuedong's avatar
Fang Yuedong committed
295
296
297
298
299
300
301
302
303
304
305
                         exptime=150., normFilter=None, grating_split_pos=3685, fd_shear=None):
        if normFilter is not None:
            norm_thr_rang_ids = normFilter['SENSITIVITY'] > 0.001
            sedNormFactor = getNormFactorForSpecWithABMAG(ABMag=self.param['mag_use_normal'], spectrum=self.sed,
                                                          norm_thr=normFilter,
                                                          sWave=np.floor(normFilter[norm_thr_rang_ids][0][0]),
                                                          eWave=np.ceil(normFilter[norm_thr_rang_ids][-1][0]))
            if sedNormFactor == 0:
                return 2, None
        else:
            sedNormFactor = 1.
Fang Yuedong's avatar
Fang Yuedong committed
306
307
308
309
310
311
312
313
314
315

        if self.getMagFilter(filt) <= 15:
            folding_threshold = 5.e-4
        else:
            folding_threshold = 5.e-3
        gsp = galsim.GSParams(folding_threshold=folding_threshold)

        normalSED = Table(np.array([self.sed['WAVELENGTH'], self.sed['FLUX'] * sedNormFactor]).T,
                          names=('WAVELENGTH', 'FLUX'))

316
        self.real_pos = self.getRealPos(chip.img, global_x=self.posImg.x, global_y=self.posImg.y,
317
                                        img_real_wcs=self.chip_wcs)
xin's avatar
xin committed
318
319
320
321
322
323
324
325

        x, y = self.real_pos.x + 0.5, self.real_pos.y + 0.5
        x_nominal = int(np.floor(x + 0.5))
        y_nominal = int(np.floor(y + 0.5))
        dx = x - x_nominal
        dy = y - y_nominal
        offset = galsim.PositionD(dx, dy)

326
        chip_wcs_local = self.chip_wcs.local(self.real_pos)
xin's avatar
xin committed
327

328
        flat_cube = chip.flat_cube
Zhang Xin's avatar
Zhang Xin committed
329

330
331
        xOrderSigPlus = {'A': 1.3909419820029296, 'B': 1.4760376591236062, 'C': 4.035447379743442,
                         'D': 5.5684364343742825, 'E': 16.260021029735388}
xin's avatar
xin committed
332
        grating_split_pos_chip = 0 + grating_split_pos
Zhang Xin's avatar
Zhang Xin committed
333
334
335
336
337
338
339
340
341
342
343
344
345
346

        branges = np.zeros([len(bandpass_list),2])

        if hasattr(psf_model,'bandranges'):
            if psf_model.bandranges is None:
                return 2, None
            if len(psf_model.bandranges) != len(bandpass_list):
                return 2, None
            branges = psf_model.bandranges
        else:
            for i in range(len(bandpass_list)):
                branges[i, 0] = bandpass_list[i].blue_limit * 10
                branges[i, 1] = bandpass_list[i].red_limit * 10

Fang Yuedong's avatar
Fang Yuedong committed
347
        for i in range(len(bandpass_list)):
Zhang Xin's avatar
Zhang Xin committed
348
349
350
351
352
            # bandpass = bandpass_list[i]
            brange = branges[i]

            # psf, pos_shear = psf_model.get_PSF(chip=chip, pos_img=pos_img, bandpass=bandpass,
            #                                    folding_threshold=folding_threshold)
Fang Yuedong's avatar
Fang Yuedong committed
353
354
            star = galsim.DeltaFunction(gsparams=gsp)
            star = star.withFlux(tel.pupil_area * exptime)
Zhang Xin's avatar
Zhang Xin committed
355
356
            psf_tmp = galsim.Gaussian(sigma=0.002)
            star = galsim.Convolve(psf_tmp, star)
Fang Yuedong's avatar
Fang Yuedong committed
357
            
Zhang Xin's avatar
Zhang Xin committed
358
            starImg = star.drawImage(nx=60, ny=60, wcs=chip_wcs_local, offset=offset)
Fang Yuedong's avatar
Fang Yuedong committed
359

xin's avatar
xin committed
360
361
            origin_star = [y_nominal - (starImg.center.y - starImg.ymin),
                           x_nominal - (starImg.center.x - starImg.xmin)]
Fang Yuedong's avatar
Fang Yuedong committed
362
            starImg.setOrigin(0,0)
Xin Zhang's avatar
Xin Zhang committed
363
364
365
366
367
368
369
370
371
            gal_origin = [origin_star[0], origin_star[1]]
            gal_end = [origin_star[0] + starImg.array.shape[0] - 1, origin_star[1] + starImg.array.shape[1] - 1]
            if gal_origin[1] < grating_split_pos_chip < gal_end[1]:
                subSlitPos = int(grating_split_pos_chip - gal_origin[1] + 1)
                ## part img disperse

                subImg_p1 = starImg.array[:, 0:subSlitPos]
                star_p1 = galsim.Image(subImg_p1)
                origin_p1 = origin_star
Fang Yuedong's avatar
Fang Yuedong committed
372
                star_p1.setOrigin(0,0)
373
374
                xcenter_p1 = min(x_nominal, grating_split_pos_chip - 1) - 0
                ycenter_p1 = y_nominal - 0
Xin Zhang's avatar
Xin Zhang committed
375
376

                sdp_p1 = SpecDisperser(orig_img=star_p1, xcenter=xcenter_p1,
377
378
                                       ycenter=ycenter_p1, origin=origin_p1,
                                       tar_spec=normalSED,
Zhang Xin's avatar
Zhang Xin committed
379
                                       band_start=brange[0], band_end=brange[1],
380
381
382
                                       conf=chip.sls_conf[0],
                                       isAlongY=0,
                                       flat_cube=flat_cube)
Xin Zhang's avatar
Xin Zhang committed
383

Zhang Xin's avatar
Zhang Xin committed
384
385
386
387
                # self.addSLStoChipImage(sdp=sdp_p1, chip=chip, xOrderSigPlus=xOrderSigPlus, local_wcs=chip_wcs_local)
                pos_shear=self.addSLStoChipImageWithPSF(sdp=sdp_p1, chip=chip, pos_img_local = [xcenter_p1,ycenter_p1],
                                              psf_model=psf_model, bandNo = i+1, grating_split_pos=grating_split_pos,
                                              local_wcs=chip_wcs_local, pos_img = pos_img)
Xin Zhang's avatar
Xin Zhang committed
388

389
                subImg_p2 = starImg.array[:, subSlitPos + 1:starImg.array.shape[1]]
Xin Zhang's avatar
Xin Zhang committed
390
                star_p2 = galsim.Image(subImg_p2)
Fang Yuedong's avatar
Fang Yuedong committed
391
                star_p2.setOrigin(0, 0)
Xin Zhang's avatar
Xin Zhang committed
392
                origin_p2 = [origin_star[0], grating_split_pos_chip]
xin's avatar
xin committed
393
394
                xcenter_p2 = max(x_nominal, grating_split_pos_chip - 1) - 0
                ycenter_p2 = y_nominal - 0
Xin Zhang's avatar
Xin Zhang committed
395
396
397
398

                sdp_p2 = SpecDisperser(orig_img=star_p2, xcenter=xcenter_p2,
                                       ycenter=ycenter_p2, origin=origin_p2,
                                       tar_spec=normalSED,
Zhang Xin's avatar
Zhang Xin committed
399
                                       band_start=brange[0], band_end=brange[1],
Xin Zhang's avatar
Xin Zhang committed
400
                                       conf=chip.sls_conf[1],
401
402
                                       isAlongY=0,
                                       flat_cube=flat_cube)
Xin Zhang's avatar
Xin Zhang committed
403

Zhang Xin's avatar
Zhang Xin committed
404
405
406
407
                # self.addSLStoChipImage(sdp=sdp_p2, chip=chip, xOrderSigPlus=xOrderSigPlus, local_wcs=chip_wcs_local)
                pos_shear=self.addSLStoChipImageWithPSF(sdp=sdp_p2, chip=chip, pos_img_local=[xcenter_p2, ycenter_p2],
                                              psf_model=psf_model, bandNo=i + 1, grating_split_pos=grating_split_pos,
                                              local_wcs=chip_wcs_local, pos_img = pos_img)
Xin Zhang's avatar
Xin Zhang committed
408
409
410

                del sdp_p1
                del sdp_p2
411
            elif grating_split_pos_chip <= gal_origin[1]:
xin's avatar
xin committed
412
413
                sdp = SpecDisperser(orig_img=starImg, xcenter=x_nominal - 0,
                                    ycenter=y_nominal - 0, origin=origin_star,
Xin Zhang's avatar
Xin Zhang committed
414
                                    tar_spec=normalSED,
Zhang Xin's avatar
Zhang Xin committed
415
                                    band_start=brange[0], band_end=brange[1],
Xin Zhang's avatar
Xin Zhang committed
416
                                    conf=chip.sls_conf[1],
417
418
                                    isAlongY=0,
                                    flat_cube=flat_cube)
Zhang Xin's avatar
Zhang Xin committed
419
420
421
422
                # self.addSLStoChipImage(sdp=sdp, chip=chip, xOrderSigPlus=xOrderSigPlus, local_wcs=chip_wcs_local)
                pos_shear=self.addSLStoChipImageWithPSF(sdp=sdp, chip=chip, pos_img_local=[x_nominal, y_nominal],
                                              psf_model=psf_model, bandNo=i + 1, grating_split_pos=grating_split_pos,
                                              local_wcs=chip_wcs_local, pos_img = pos_img)
Xin Zhang's avatar
Xin Zhang committed
423
                del sdp
424
            elif grating_split_pos_chip >= gal_end[1]:
xin's avatar
xin committed
425
426
                sdp = SpecDisperser(orig_img=starImg, xcenter=x_nominal - 0,
                                    ycenter=y_nominal - 0, origin=origin_star,
Xin Zhang's avatar
Xin Zhang committed
427
                                    tar_spec=normalSED,
Zhang Xin's avatar
Zhang Xin committed
428
                                    band_start=brange[0], band_end=brange[1],
Xin Zhang's avatar
Xin Zhang committed
429
                                    conf=chip.sls_conf[0],
430
431
                                    isAlongY=0,
                                    flat_cube=flat_cube)
Zhang Xin's avatar
Zhang Xin committed
432
433
434
435
                # self.addSLStoChipImage(sdp=sdp, chip=chip, xOrderSigPlus=xOrderSigPlus, local_wcs=chip_wcs_local)
                pos_shear=self.addSLStoChipImageWithPSF(sdp=sdp, chip=chip, pos_img_local=[x_nominal, y_nominal],
                                              psf_model=psf_model, bandNo=i + 1, grating_split_pos=grating_split_pos,
                                              local_wcs=chip_wcs_local, pos_img = pos_img)
Xin Zhang's avatar
Xin Zhang committed
436
                del sdp
Zhang Xin's avatar
Zhang Xin committed
437
            # del psf
Fang Yuedong's avatar
Fang Yuedong committed
438
        return 1, pos_shear
Fang Yuedong's avatar
Fang Yuedong committed
439
440
441
442
443
444
445
446
447
448

    def SNRestimate(self, img_obj, flux, noise_level=0.0, seed=31415):
        img_flux = img_obj.added_flux
        stamp = img_obj.copy() * 0.0
        rng = galsim.BaseDeviate(seed)
        gaussianNoise = galsim.GaussianNoise(rng, sigma=noise_level)
        stamp.addNoise(gaussianNoise)
        sig_obj = np.std(stamp.array)
        snr_obj = img_flux / sig_obj
        return snr_obj
Wei Chengliang's avatar
Wei Chengliang committed
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533



    def drawObj_PSF(self, tel, pos_img, psf_model, bandpass_list, filt, chip, nphotons_tot=None, g1=0, g2=0,
                          exptime=150., fd_shear=None, chip_output=None):
        if nphotons_tot == None:
            nphotons_tot = self.getElectronFluxFilt(filt, tel, exptime)
        # print("nphotons_tot = ", nphotons_tot)

        try:
            full = integrate_sed_bandpass(sed=self.sed, bandpass=filt.bandpass_full)
        except Exception as e:
            print(e)
            if self.logger:
                self.logger.error(e)
            return 2, None

        # Set Galsim Parameters
        if self.getMagFilter(filt) <= 15:
            folding_threshold = 5.e-4
        else:
            folding_threshold = 5.e-3
        gsp = galsim.GSParams(folding_threshold=folding_threshold)

        # Get real image position of object (deal with chip rotation w.r.t its center)
        self.real_pos = self.getRealPos(chip.img, global_x=self.posImg.x, global_y=self.posImg.y,
                                        img_real_wcs=self.chip_wcs)
        x, y = self.real_pos.x + 0.5, self.real_pos.y + 0.5
        x_nominal = int(np.floor(x + 0.5))
        y_nominal = int(np.floor(y + 0.5))
        dx = x - x_nominal
        dy = y - y_nominal
        offset = galsim.PositionD(dx, dy)
        # Get real local wcs of object (deal with chip rotation w.r.t its center)
        chip_wcs_local = self.chip_wcs.local(self.real_pos)
        is_updated = 0

        # Loop over all sub-bandpasses
        for i in range(len(bandpass_list)):
            bandpass = bandpass_list[i]
            try:
                sub = integrate_sed_bandpass(sed=self.sed, bandpass=bandpass)
            except Exception as e:
                print(e)
                if self.logger:
                    self.logger.error(e)
                continue
            ratio = sub / full
            if not (ratio == -1 or (ratio != ratio)):
                nphotons = ratio * nphotons_tot
            else:
                continue

            # Get PSF model
            psf, pos_shear = psf_model.get_PSF(chip=chip, pos_img=pos_img, bandpass=bandpass,
                                               folding_threshold=folding_threshold)
            star_temp = psf.withFlux(nphotons)

            if i==0:
                star = star_temp
            else:
                star = star+star_temp

        pixelScale = 0.074
        stamp = star.drawImage(wcs=chip_wcs_local, offset=offset)
        #stamp = star.drawImage(nx=256, ny=256, scale=pixelScale)
        if np.sum(np.isnan(stamp.array)) > 0:
            return None


        fn = chip_output.subdir + "/psfIDW"
        os.makedirs(fn, exist_ok=True)
        fn = fn + "/ccd_{:}".format(chip.chipID)+"_psf_"+str(self.param['id'])+".fits"
        if fn != None:
            if os.path.exists(fn):
                os.remove(fn)
        hdu = fitsio.PrimaryHDU()
        hdu.data = stamp.array
        hdu.header.set('name',      self.type)
        hdu.header.set('pixScale',  pixelScale)
        hdu.header.set('objID',     self.param['id'])
        hdu.writeto(fn)

        del stamp
        return None