ObservationSim.py 15.4 KB
Newer Older
1
2
3
4
5
6
import sys
import os

from ObservationSim.Config import ConfigDir, ChipOutput
from ObservationSim.Config.Header import generatePrimaryHeader, generateExtensionHeader
from ObservationSim.Instrument import Telescope, Filter, FilterParam, FocalPlane, Chip
7
from ObservationSim.MockObject import calculateSkyMap_split_g
8
9
10
from ObservationSim.PSF import PSFGauss, FieldDistortion, PSFInterp
from ObservationSim._util import getShearFiled, makeSubDir_PointingList

Fang Yuedong's avatar
Fang Yuedong committed
11
from astropy.io import fits
Fang Yuedong's avatar
Fang Yuedong committed
12
from datetime import datetime
Fang Yuedong's avatar
Fang Yuedong committed
13
14
15
16
17
18
19
import numpy as np
import mpi4py.MPI as MPI
import galsim
import logging
import psutil

class Observation(object):
20
    def __init__(self, config, Catalog, work_dir=None, data_dir=None):
Fang Yuedong's avatar
Fang Yuedong committed
21
22
23
        self.path_dict = ConfigDir(config=config, work_dir=work_dir, data_dir=data_dir)
        # self.config = ReadConfig(self.path_dict["config_file"])
        self.config = config
Fang Yuedong's avatar
Fang Yuedong committed
24
        self.tel = Telescope(optEffCurve_path=self.path_dict["mirror_file"]) # Currently the default values are hard coded in
Fang Yuedong's avatar
Fang Yuedong committed
25
        self.focal_plane = FocalPlane(survey_type=self.config["obs_setting"]["survey_type"]) # Currently the default values are hard coded in
Fang Yuedong's avatar
Fang Yuedong committed
26
27
28
        self.filter_param = FilterParam(filter_dir=self.path_dict["filter_dir"]) # Currently the default values are hard coded in
        self.chip_list = []
        self.filter_list = []
29
        self.Catalog = Catalog
Fang Yuedong's avatar
Fang Yuedong committed
30
31

        # if we want to apply field distortion?
Fang Yuedong's avatar
Fang Yuedong committed
32
        if self.config["ins_effects"]["field_dist"] == True:
Fang Yuedong's avatar
Fang Yuedong committed
33
            self.fd_model = FieldDistortion(fdModel_path=self.path_dict["fd_path"])
Fang Yuedong's avatar
Fang Yuedong committed
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
        else:
            self.fd_model = None

        # Construct chips & filters:
        nchips = self.focal_plane.nchip_x*self.focal_plane.nchip_y
        for i in range(nchips):
            chipID = i + 1
            if self.focal_plane.isIgnored(chipID=chipID):
                continue

            # Make Chip & Filter lists
            chip = Chip(chipID, ccdEffCurve_dir=self.path_dict["ccd_dir"], CRdata_dir=self.path_dict["CRdata_dir"], normalize_dir=self.path_dict["normalize_dir"], sls_dir=self.path_dict["sls_dir"], config=self.config) # currently there is no config file for chips
            filter_id, filter_type = chip.getChipFilter()
            filt = Filter(filter_id=filter_id, filter_type=filter_type, filter_param=self.filter_param, ccd_bandpass=chip.effCurve)
            self.chip_list.append(chip)
            self.filter_list.append(filt)

        # Read catalog and shear(s)
        self.g1_field, self.g2_field, self.nshear = getShearFiled(config=self.config)


Fang Yuedong's avatar
Fang Yuedong committed
55
    def runOneChip(self, chip, filt, chip_output, wcs_fp=None, psf_model=None, pointing_ID=0, ra_cen=None, dec_cen=None, img_rot=None, exptime=150., timestamp_obs=1621915200, pointing_type="MS", shear_cat_file=None, cat_dir=None, sed_dir=None):
Fang Yuedong's avatar
Fang Yuedong committed
56
57

        if (ra_cen is None) or (dec_cen is None):
Fang Yuedong's avatar
Fang Yuedong committed
58
59
            ra_cen = self.config["obs_setting"]["ra_center"]
            dec_cen = self.config["obs_setting"]["dec_center"]
Fang Yuedong's avatar
Fang Yuedong committed
60
        if img_rot is None:
Fang Yuedong's avatar
Fang Yuedong committed
61
            img_rot = self.config["obs_setting"]["image_rot"]
Fang Yuedong's avatar
Fang Yuedong committed
62

Fang Yuedong's avatar
Fang Yuedong committed
63
        if self.config["psf_setting"]["psf_model"] == "Gauss":
Fang Yuedong's avatar
Fang Yuedong committed
64
            psf_model = PSFGauss(chip=chip)
Fang Yuedong's avatar
Fang Yuedong committed
65
        elif self.config["psf_setting"]["psf_model"] == "Interp":
Fang Yuedong's avatar
Fang Yuedong committed
66
            psf_model = PSFInterp(chip=chip, PSF_data_file=self.path_dict["psf_dir"])
Fang Yuedong's avatar
Fang Yuedong committed
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
        else:
            print("unrecognized PSF model type!!", flush=True)

        # Get (extra) shear fields
        if shear_cat_file is not None:
            self.g1_field, self.g2_field, self.nshear = getShearFiled(config=self.config, shear_cat_file=shear_cat_file)

        # Get WCS for the focal plane
        if wcs_fp == None:
            wcs_fp = self.focal_plane.getTanWCS(ra_cen, dec_cen, img_rot, chip.pix_scale)

        # Create chip Image
        chip.img = galsim.ImageF(chip.npix_x, chip.npix_y)
        chip.img.setOrigin(chip.bound.xmin, chip.bound.ymin)
        chip.img.wcs = wcs_fp
        if chip.survey_type == "photometric":
            sky_map = None
        elif chip.survey_type == "spectroscopic":
Fang Yuedong's avatar
Fang Yuedong committed
85
            sky_map = calculateSkyMap_split_g(xLen=chip.npix_x, yLen=chip.npix_y, blueLimit=filt.blue_limit, redLimit=filt.red_limit, skyfn=self.path_dict["sky_file"], conf=chip.sls_conf, pixelSize=chip.pix_scale, isAlongY=0)
Fang Yuedong's avatar
Fang Yuedong committed
86

Fang Yuedong's avatar
Fang Yuedong committed
87
88
        if pointing_type == 'MS':
            # Load catalogues and templates
89
            self.cat = self.Catalog(config=self.config, chip=chip, cat_dir=cat_dir, sed_dir=sed_dir)
Fang Yuedong's avatar
Fang Yuedong committed
90
91
92
93
94
95
96
            self.nobj = len(self.cat.objs)

            # Loop over objects
            missed_obj = 0
            bright_obj = 0
            dim_obj = 0
            for j in range(self.nobj):
97
                # if j >= 100:
Fang Yuedong's avatar
Fang Yuedong committed
98
99
                #     break
                obj = self.cat.objs[j]
100
101
102
103
104
105
                if obj.type == 'star' and self.config["galaxy_only"]:
                    continue
                elif obj.type == 'galaxy' and self.config["star_only"]:
                    continue
                elif obj.type == 'quasar' and self.config["star_only"]:
                    continue
Fang Yuedong's avatar
Fang Yuedong committed
106

107
108
109
110
111
112
113
114
115
116
117
118
119
                # load SED
                try:
                    sed_data = self.cat.load_sed(obj)
                    norm_filt = self.cat.load_norm_filt(obj)
                    obj.sed, obj.param["mag_%s"%filt.filter_type] = self.cat.convert_sed(
                        mag=obj.param["mag_use_normal"],
                        sed=sed_data,
                        target_filt=filt, 
                        norm_filt=norm_filt,
                    )
                except Exception as e:
                    print(e)
                    continue
Fang Yuedong's avatar
Fang Yuedong committed
120
121
122
123
124
125
126
127
128
129
130

                # Exclude very bright/dim objects (for now)
                if filt.is_too_bright(mag=obj.getMagFilter(filt)):
                    # print("obj too birght!!", flush=True)
                    if obj.type != 'galaxy':
                        bright_obj += 1
                        obj.unload_SED()
                        continue
                if filt.is_too_dim(mag=obj.getMagFilter(filt)):
                    # print("obj too dim!!", flush=True)
                    dim_obj += 1
Fang Yuedong's avatar
Fang Yuedong committed
131
                    obj.unload_SED()
Fang Yuedong's avatar
Fang Yuedong committed
132
                    # print(obj.getMagFilter(filt))
Fang Yuedong's avatar
Fang Yuedong committed
133
134
                    continue

Fang Yuedong's avatar
Fang Yuedong committed
135
                if self.config["shear_setting"]["shear_type"] == "constant":
Fang Yuedong's avatar
Fang Yuedong committed
136
137
138
139
                    if obj.type == 'star':
                        g1, g2 = 0, 0
                    else:
                        g1, g2 = self.g1_field, self.g2_field
Fang Yuedong's avatar
Fang Yuedong committed
140
141
142
143
144
145
146
                elif self.config["shear_setting"]["shear_type"] == "extra":
                    try:
                        # TODO: every object with individual shear from input catalog(s)
                        g1, g2 = self.g1_field[j], self.g2_field[j]
                    except:
                        print("failed to load external shear.")
                        pass
147
148
149
150
                elif self.config["shear_setting"]["shear_type"] == "catalog":
                    pass
                else:
                    raise ValueError("Unknown shear input")
Fang Yuedong's avatar
Fang Yuedong committed
151
152
153
154
155
156
157
158

                pos_img, offset, local_wcs = obj.getPosImg_Offset_WCS(img=chip.img, fdmodel=self.fd_model, chip=chip, verbose=False)
                if pos_img.x == -1 or pos_img.y == -1:
                    # Exclude object which is outside the chip area (after field distortion)
                    # print("obj missed!!")
                    missed_obj += 1
                    obj.unload_SED()
                    continue
Fang Yuedong's avatar
Fang Yuedong committed
159

Fang Yuedong's avatar
Fang Yuedong committed
160
161
                # Draw object & update output catalog
                try:
Fang Yuedong's avatar
Fang Yuedong committed
162
163
164
                    if self.config["out_cat_only"]:
                        isUpdated = True
                    if chip.survey_type == "photometric" and not self.config["out_cat_only"]:
Fang Yuedong's avatar
Fang Yuedong committed
165
166
167
168
169
170
171
172
173
174
                        isUpdated, pos_shear = obj.drawObj_multiband(
                            tel=self.tel,
                            pos_img=pos_img, 
                            psf_model=psf_model, 
                            bandpass_list=filt.bandpass_sub_list, 
                            filt=filt, 
                            chip=chip, 
                            g1=g1, 
                            g2=g2, 
                            exptime=exptime)
Fang Yuedong's avatar
Fang Yuedong committed
175
                    elif chip.survey_type == "spectroscopic" and not self.config["out_cat_only"]:
Fang Yuedong's avatar
Fang Yuedong committed
176
177
178
179
180
181
182
183
184
185
                        isUpdated, pos_shear = obj.drawObj_slitless(
                            tel=self.tel, 
                            pos_img=pos_img, 
                            psf_model=psf_model, 
                            bandpass_list=filt.bandpass_sub_list, 
                            filt=filt, 
                            chip=chip, 
                            g1=g1, 
                            g2=g2, 
                            exptime=exptime, 
186
187
188
                            # normFilter=normF,
                            normFilter=norm_filt,
                            )
Fang Yuedong's avatar
Fang Yuedong committed
189
190
191
192
193
194
195
196
197
                    if isUpdated:
                        # TODO: add up stats
                        chip_output.cat_add_obj(obj, pos_img, pos_shear, g1, g2)
                        pass
                    else:
                        # print("object omitted", flush=True)
                        continue
                except Exception as e:
                    print(e)
Fang Yuedong's avatar
Fang Yuedong committed
198
                    pass
Fang Yuedong's avatar
Fang Yuedong committed
199
200
201
                # Unload SED:
                obj.unload_SED()
                del obj
Fang Yuedong's avatar
Fang Yuedong committed
202

Fang Yuedong's avatar
Fang Yuedong committed
203
204
            del psf_model
            del self.cat
Fang Yuedong's avatar
Fang Yuedong committed
205
206
207
208
209

        print("check running:1: pointing-{:} chip-{:} pid-{:} memory-{:6.2}GB".format(pointing_ID, chip.chipID, os.getpid(), (psutil.Process(os.getpid()).memory_info().rss / 1024 / 1024 / 1024) ), flush=True)

        # Detector Effects
        # ===========================================================
Fang Yuedong's avatar
Fang Yuedong committed
210
211
212
213
214
215
216
217
218
219
220
221

        # whether to output zero, dark, flat calibration images.
        chip.img = chip.addEffects(
            config=self.config, 
            img=chip.img, 
            chip_output=chip_output, 
            filt=filt, 
            ra_cen=ra_cen, 
            dec_cen=dec_cen,
            img_rot=img_rot,
            pointing_ID=pointing_ID,
            timestamp_obs=timestamp_obs,
222
            pointing_type=pointing_type,
Zhang Xin's avatar
Zhang Xin committed
223
            sky_map=sky_map, tel = self.tel)
Fang Yuedong's avatar
Fang Yuedong committed
224
        
Fang Yuedong's avatar
Fang Yuedong committed
225
226
227
228
229
230
231
232
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
        if pointing_type == 'MS':
            datetime_obs = datetime.fromtimestamp(timestamp_obs)
            date_obs = datetime_obs.strftime("%y%m%d")
            time_obs = datetime_obs.strftime("%H%M%S")
            h_prim = generatePrimaryHeader(
                xlen=chip.npix_x, 
                ylen=chip.npix_y, 
                pointNum = str(pointing_ID),
                ra=ra_cen, 
                dec=dec_cen, 
                psize=chip.pix_scale, 
                row_num=chip.rowID, 
                col_num=chip.colID,
                # date=self.config["date_obs"],
                # time_obs=self.config["time_obs"],
                date=date_obs,
                time_obs=time_obs,
                im_type='MS')
            h_ext = generateExtensionHeader(
                xlen=chip.npix_x, 
                ylen=chip.npix_y, 
                ra=ra_cen, 
                dec=dec_cen, 
                pa=img_rot.deg, 
                gain=chip.gain, 
                readout=chip.read_noise, 
                dark=chip.dark_noise, 
                saturation=90000, 
                psize=chip.pix_scale, 
                row_num=chip.rowID, 
                col_num=chip.colID,
                extName='raw')
            chip.img = galsim.Image(chip.img.array, dtype=np.uint16)
Fang Yuedong's avatar
Fang Yuedong committed
258
            # chip.img = galsim.Image(chip.img.array, dtype=np.uint32)
Fang Yuedong's avatar
Fang Yuedong committed
259
260
261
262
263
264
265
266
            hdu1 = fits.PrimaryHDU(header=h_prim)
            hdu2 = fits.ImageHDU(chip.img.array, header=h_ext)
            hdu1 = fits.HDUList([hdu1, hdu2])
            fname = os.path.join(chip_output.subdir, h_prim['FILENAME'] + '.fits')
            hdu1.writeto(fname, output_verify='ignore', overwrite=True)
            print("# objects that are too bright %d out of %d"%(bright_obj, self.nobj))
            print("# objects that are too dim %d out of %d"%(dim_obj, self.nobj))
            print("# objects that are missed %d out of %d"%(missed_obj, self.nobj))
Fang Yuedong's avatar
Fang Yuedong committed
267
268
269
270
        del chip.img

        print("check running:2: pointing-{:} chip-{:} pid-{:} memory-{:6.2}GB".format(pointing_ID, chip.chipID, os.getpid(), (psutil.Process(os.getpid()).memory_info().rss / 1024 / 1024 / 1024) ), flush=True)

Fang Yuedong's avatar
Fang Yuedong committed
271
272
273
274
275
    def runExposure_MPI_PointingList(self, ra_cen=None, dec_cen=None, pRange=None, timestamp_obs=np.array([1621915200]), pointing_type=np.array(['MS']), img_rot=None, exptime=150., shear_cat_file=None, chips=None, use_mpi=False):
        if use_mpi:
            comm = MPI.COMM_WORLD
            ind_thread = comm.Get_rank()
            num_thread = comm.Get_size()
Fang Yuedong's avatar
Fang Yuedong committed
276

Fang Yuedong's avatar
Fang Yuedong committed
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
        if chips is None:
            nchips_per_fp = len(self.chip_list)
            run_chips = self.chip_list
            run_filts = self.filter_list
        else:
            # Only run a particular set of chips
            run_chips = []
            run_filts = []
            nchips_per_fp = len(chips)
            for ichip in range(len(self.chip_list)):
                chip = self.chip_list[ichip]
                filt = self.filter_list[ichip]
                if chip.chipID in chips:
                    run_chips.append(chip)
                    run_filts.append(filt)
Fang Yuedong's avatar
Fang Yuedong committed
292

293
294
295
296
297
        # TEMP
        if len(timestamp_obs) == 1:
            timestamp_obs = np.tile(timestamp_obs, len(ra_cen))
            pointing_type = np.tile(pointing_type, len(ra_cen))
        
298
299
300
301
302
        if pRange is not None:
            timestamp_obs = timestamp_obs[pRange]
            pointing_type = pointing_type[pRange]
            ra_cen = ra_cen[pRange]
            dec_cen = dec_cen[pRange]
Fang Yuedong's avatar
Fang Yuedong committed
303
304
305
306
307
308
309
310
311
312

        # The Starting pointing ID
        if pRange is not None:
            pStart = pRange[0]
        else:
            pStart = 0

        for ipoint in range(len(ra_cen)):
            for ichip in range(nchips_per_fp):
                i = ipoint*nchips_per_fp + ichip
Fang Yuedong's avatar
Fang Yuedong committed
313
314
315
316
                if pRange is None:
                    pointing_ID = pStart + ipoint
                else:
                    pointing_ID = pRange[ipoint]
Fang Yuedong's avatar
Fang Yuedong committed
317
318
319
                if use_mpi:
                    if i % num_thread != ind_thread:
                        continue
Fang Yuedong's avatar
Fang Yuedong committed
320
321
322
323
324

                pid = os.getpid()

                sub_img_dir, prefix = makeSubDir_PointingList(path_dict=self.path_dict, config=self.config, pointing_ID=pointing_ID)

Fang Yuedong's avatar
Fang Yuedong committed
325
326
327
328
                # chip = self.chip_list[ichip]
                # filt = self.filter_list[ichip]
                chip = run_chips[ichip]
                filt = run_filts[ichip]
Fang Yuedong's avatar
Fang Yuedong committed
329
330
331
332
333
334
335
                print("running pointing#%d, chip#%d, at PID#%d..."%(pointing_ID, chip.chipID, pid), flush=True)
                chip_output = ChipOutput(
                    config=self.config, 
                    focal_plane=self.focal_plane, 
                    chip=chip, 
                    filt=filt,  
                    exptime=exptime,
Fang Yuedong's avatar
Fang Yuedong committed
336
                    pointing_type=pointing_type[ipoint],
Fang Yuedong's avatar
Fang Yuedong committed
337
338
339
340
341
342
343
344
345
346
347
                    pointing_ID=pointing_ID,  
                    subdir=sub_img_dir,
                    prefix=prefix)
                self.runOneChip(
                    chip=chip, 
                    filt=filt, 
                    chip_output=chip_output, 
                    pointing_ID = pointing_ID,
                    ra_cen=ra_cen[ipoint], 
                    dec_cen=dec_cen[ipoint], 
                    img_rot=img_rot, 
Fang Yuedong's avatar
Fang Yuedong committed
348
349
350
                    exptime=exptime,
                    timestamp_obs=timestamp_obs[ipoint],
                    pointing_type=pointing_type[ipoint],
Fang Yuedong's avatar
Fang Yuedong committed
351
                    cat_dir=self.path_dict["cat_dir"])
Zhang Xin's avatar
Zhang Xin committed
352
                print("finished running chip#%d..."%(chip.chipID), flush=True)