Newer
Older
import numpy as np
import galsim
from astropy.table import Table
from observation_sim.mock_objects._util import eObs, integrate_sed_bandpass, getNormFactorForSpecWithABMAG
from observation_sim.mock_objects.SpecDisperser import SpecDisperser
from observation_sim.mock_objects.MockObject import MockObject
# import tracemalloc
class Galaxy(MockObject):
def __init__(self, param, logger=None):
super().__init__(param, logger=logger)
if not hasattr(self, "disk_sersic_idx"):
self.disk_sersic_idx = 1.
if not hasattr(self, "bulge_sersic_idx"):
self.bulge_sersic_idx = 4.
if not hasattr(self, "mu"):
if hasattr(self, "detA"):
self.mu = 1./self.detA
else:
self.mu = 1.
def unload_SED(self):
"""(Test) free up SED memory
"""
del self.sed
def getGSObj_multiband(self, tel, psf_list, bandpass_list, filt, nphotons_tot=None, g1=0, g2=0, exptime=150., fd_shear=None):
if len(psf_list) != len(bandpass_list):
raise ValueError(
"!!!The number of PSF profiles and the number of bandpasses must be equal.")
objs = []
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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 -1
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)
return -1
ratio = sub/full
if not (ratio == -1 or (ratio != ratio)):
nphotons = ratio * nphotons_tot
else:
return -1
psf = psf_list[i]
disk = galsim.Sersic(n=self.disk_sersic_idx,
half_light_radius=self.hlr_disk, flux=1.0)
disk_shape = galsim.Shear(g1=self.e1_disk, g2=self.e2_disk)
disk = disk.shear(disk_shape)
bulge = galsim.Sersic(n=self.bulge_sersic_idx,
half_light_radius=self.hlr_bulge, flux=1.0)
bulge_shape = galsim.Shear(g1=self.e1_bulge, g2=self.e2_bulge)
bulge = bulge.shear(bulge_shape)
if self.bfrac == 0:
gal = disk
elif self.bfrac == 1:
gal = bulge
else:
gal = self.bfrac * bulge + (1.0 - self.bfrac) * disk
if fd_shear is not None:
g1 += fd_shear.g1
g2 += fd_shear.g2
gal_shear = galsim.Shear(g1=g1, g2=g2)
gal = gal.shear(gal_shear)
# Magnification
gal = gal.magnify(self.mu)
gal = galsim.Convolve(psf, gal)
gal = gal.withFlux(nphotons)
objs.append(gal)
final = galsim.Sum(objs)
return final
def drawObj_multiband(self, tel, pos_img, psf_model, bandpass_list, filt, chip, nphotons_tot=None, g1=0, g2=0, exptime=150., fd_shear=None):
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
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
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
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
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
# # [C6 TEST]
# print('hlr_disk = %.4f, hlr_bulge = %.4f'%(self.hlr_disk, self.hlr_bulge))
# tracemalloc.start()
big_galaxy = False
if self.hlr_disk > 3.0 or self.hlr_bulge > 3.0: # Very big galaxy
big_galaxy = True
# Set Galsim Parameters
if self.getMagFilter(filt) <= 15 and (not big_galaxy):
folding_threshold = 5.e-4
else:
folding_threshold = 5.e-3
gsp = galsim.GSParams(folding_threshold=folding_threshold)
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
# Model the galaxy as disk + bulge
disk = galsim.Sersic(
n=self.disk_sersic_idx, half_light_radius=self.hlr_disk, flux=1.0, gsparams=gsp)
disk_shape = galsim.Shear(g1=self.e1_disk, g2=self.e2_disk)
disk = disk.shear(disk_shape)
bulge = galsim.Sersic(
n=self.bulge_sersic_idx, half_light_radius=self.hlr_bulge, flux=1.0, gsparams=gsp)
bulge_shape = galsim.Shear(g1=self.e1_bulge, g2=self.e2_bulge)
bulge = bulge.shear(bulge_shape)
# Get shear and deal with shear induced by field distortion
if fd_shear:
g1 += fd_shear.g1
g2 += fd_shear.g2
gal_shear = galsim.Shear(g1=g1, g2=g2)
# 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
# nphotons_sum += nphotons
# # [C6 TEST]
# print("nphotons_sub-band_%d = %.2f"%(i, nphotons))
# Get PSF model
psf, pos_shear = psf_model.get_PSF(
chip=chip, pos_img=pos_img, bandpass=bandpass, folding_threshold=folding_threshold)
if self.bfrac == 0:
gal_temp = disk
elif self.bfrac == 1:
gal_temp = bulge
else:
gal_temp = self.bfrac * bulge + (1.0 - self.bfrac) * disk
gal_temp = gal_temp.shear(gal_shear)
# Magnification
gal_temp = gal_temp.magnify(self.mu)
if not big_galaxy: # Not apply PSF for very big galaxy
gal_temp = galsim.Convolve(psf, gal_temp)
gal_temp = gal_temp.withFlux(nphotons)
if i == 0:
gal = gal_temp
else:
gal = gal + gal_temp
# (TEST) Random knots
# knots = galsim.RandomKnots(npoints=100, profile=disk)
# kfrac = np.random.random()*(1.0 - self.bfrac)
# gal = self.bfrac * bulge + (1.0 - self.bfrac - kfrac) * disk + kfrac * knots
# stamp = gal.drawImage(wcs=chip_wcs_local, method='phot', offset=offset, save_photons=True)
stamp = gal.drawImage(wcs=chip_wcs_local, offset=offset)
if np.sum(np.isnan(stamp.array)) > 0:
# ERROR happens
return 2, pos_shear
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
if is_updated == 0:
# Return code 0: object photons missed this detector
print("obj %s missed" % (self.id))
if self.logger:
self.logger.info("obj %s missed" % (self.id))
return 0, pos_shear
# # [C6 TEST]
# print("nphotons_sum = ", nphotons_sum)
return 1, pos_shear
def drawObj_slitless(self, tel, pos_img, psf_model, bandpass_list, filt, chip, nphotons_tot=None, g1=0, g2=0,
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.
normalSED = Table(np.array([self.sed['WAVELENGTH'], self.sed['FLUX'] * sedNormFactor]).T,
names=('WAVELENGTH', 'FLUX'))
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)
chip_wcs_local = self.chip_wcs.local(self.real_pos)
big_galaxy = False
if self.hlr_disk > 3.0 or self.hlr_bulge > 3.0: # Very big galaxy
big_galaxy = True
if self.getMagFilter(filt) <= 15 and (not big_galaxy):
folding_threshold = 5.e-4
else:
folding_threshold = 5.e-3
gsp = galsim.GSParams(folding_threshold=folding_threshold)
# nphotons_sum = 0
flat_cube = chip.flat_cube
xOrderSigPlus = {'A': 1.3909419820029296, 'B': 1.4760376591236062,
'C': 4.035447379743442, 'D': 5.5684364343742825, 'E': 16.260021029735388}
grating_split_pos_chip = 0 + grating_split_pos
branges = np.zeros([len(bandpass_list), 2])
# print(hasattr(psf_model, 'bandranges'))
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
for i in range(len(bandpass_list)):
# 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)
disk = galsim.Sersic(
n=self.disk_sersic_idx, half_light_radius=self.hlr_disk, flux=1.0, gsparams=gsp)
disk_shape = galsim.Shear(g1=self.e1_disk, g2=self.e2_disk)
disk = disk.shear(disk_shape)
bulge = galsim.Sersic(
n=self.bulge_sersic_idx, half_light_radius=self.hlr_bulge, flux=1.0, gsparams=gsp)
bulge_shape = galsim.Shear(g1=self.e1_bulge, g2=self.e2_bulge)
bulge = bulge.shear(bulge_shape)
if self.bfrac == 0:
gal = disk
elif self.bfrac == 1:
gal = bulge
else:
gal = self.bfrac * bulge + (1.0 - self.bfrac) * disk
# (TEST) Random knots
# knots = galsim.RandomKnots(npoints=100, profile=disk)
# kfrac = np.random.random()*(1.0 - self.bfrac)
# gal = self.bfrac * bulge + (1.0 - self.bfrac - kfrac) * disk + kfrac * knots
if fd_shear:
g1 += fd_shear.g1
g2 += fd_shear.g2
gal_shear = galsim.Shear(g1=g1, g2=g2)
gal = gal.shear(gal_shear)
gal = gal.magnify(self.mu)
gal = gal.withFlux(tel.pupil_area * exptime)
# gal = galsim.Convolve(psf, gal)
# if not big_galaxy: # Not apply PSF for very big galaxy
# gal = galsim.Convolve(psf, gal)
# # if fd_shear is not None:
# # gal = gal.shear(fd_shear)
Zhang Xin
committed
galImg_List = []
try:
Zhang Xin
committed
x_start = chip.x_cen/chip.pix_size - chip.npix_x / 2.
y_start = chip.y_cen/chip.pix_size - chip.npix_y / 2.
pos_img_local[0] = pos_img.x - x_start
pos_img_local[1] = pos_img.y - y_start
nnx = 0
nny = 0
Zhang Xin
committed
psf, pos_shear = psf_model.get_PSF(
chip, pos_img_local=pos_img_local, bandNo=i+1, galsimGSObject=True, g_order=order, grating_split_pos=grating_split_pos)
star_p = galsim.Convolve(psf, gal)
if nnx == 0:
Zhang Xin
committed
nnx = galImg.xmax - galImg.xmin + 1
nny = galImg.ymax - galImg.ymin + 1
else:
galImg = star_p.drawImage(
nx=nnx, ny=nny, wcs=chip_wcs_local, offset=offset)
Zhang Xin
committed
galImg.setOrigin(0, 0)
# n1 = np.sum(np.isinf(galImg.array))
# n2 = np.sum(np.isnan(galImg.array))
# if n1>0 or n2 > 0:
# print("DEBUG: Galaxy, inf:%d, nan:%d"%(n1, n2))
if np.sum(np.isnan(galImg.array)) > 0:
# ERROR happens
return 2, pos_shear
galImg_List.append(galImg)
Zhang Xin
committed
galImg_List.append(galImg)
except:
psf, pos_shear = psf_model.get_PSF(chip=chip, pos_img=pos_img)
star_p = galsim.Convolve(psf, gal)
galImg = star_p.drawImage(wcs=chip_wcs_local, offset=offset)
galImg.setOrigin(0, 0)
if np.sum(np.isnan(galImg.array)) > 0:
# ERROR happens
return 2, pos_shear
Zhang Xin
committed
galImg_List.append(galImg)
# starImg = gal.drawImage(
# wcs=chip_wcs_local, offset=offset, method='real_space')
origin_star = [y_nominal - (galImg.center.y - galImg.ymin),
x_nominal - (galImg.center.x - galImg.xmin)]
galImg.setOrigin(0, 0)
Zhang Xin
committed
gal_end = [origin_star[0] + galImg.array.shape[0] -
1, origin_star[1] + galImg.array.shape[1] - 1]
if gal_origin[1] < grating_split_pos_chip < gal_end[1]:
subSlitPos = int(grating_split_pos_chip - gal_origin[1])
Zhang Xin
committed
for galImg in galImg_List:
subImg_p1 = galImg.array[:, 0:subSlitPos]
star_p1 = galsim.Image(subImg_p1)
star_p1.setOrigin(0, 0)
star_p1s.append(star_p1)
origin_p1 = origin_star
xcenter_p1 = min(x_nominal, grating_split_pos_chip-1) - 0
ycenter_p1 = y_nominal-0
Zhang Xin
committed
sdp_p1 = SpecDisperser(orig_img=star_p1s, xcenter=xcenter_p1,
ycenter=ycenter_p1, origin=origin_p1,
tar_spec=normalSED,
band_start=brange[0], band_end=brange[1],
conf=chip.sls_conf[0],
isAlongY=0,
flat_cube=flat_cube)
self.addSLStoChipImage(
sdp=sdp_p1, chip=chip, xOrderSigPlus=xOrderSigPlus, local_wcs=chip_wcs_local)
Zhang Xin
committed
# 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)
Zhang Xin
committed
for galImg in galImg_List:
Zhang Xin
committed
subImg_p2 = galImg.array[:,
Zhang Xin
committed
star_p2 = galsim.Image(subImg_p2)
star_p2.setOrigin(0, 0)
star_p2s.append(star_p2)
xcenter_p2 = max(x_nominal, grating_split_pos_chip) - 0
Zhang Xin
committed
sdp_p2 = SpecDisperser(orig_img=star_p2s, xcenter=xcenter_p2,
ycenter=ycenter_p2, origin=origin_p2,
tar_spec=normalSED,
band_start=brange[0], band_end=brange[1],
conf=chip.sls_conf[1],
isAlongY=0,
flat_cube=flat_cube)
self.addSLStoChipImage(
sdp=sdp_p2, chip=chip, xOrderSigPlus=xOrderSigPlus, local_wcs=chip_wcs_local)
Zhang Xin
committed
# 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)
del sdp_p1
del sdp_p2
elif grating_split_pos_chip <= gal_origin[1]:
Zhang Xin
committed
sdp = SpecDisperser(orig_img=galImg_List, xcenter=x_nominal - 0,
ycenter=y_nominal - 0, origin=origin_star,
tar_spec=normalSED,
band_start=brange[0], band_end=brange[1],
conf=chip.sls_conf[1],
isAlongY=0,
flat_cube=flat_cube)
self.addSLStoChipImage(
sdp=sdp, chip=chip, xOrderSigPlus=xOrderSigPlus, local_wcs=chip_wcs_local)
Zhang Xin
committed
# 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)
Zhang Xin
committed
sdp = SpecDisperser(orig_img=galImg_List, xcenter=x_nominal - 0,
ycenter=y_nominal - 0, origin=origin_star,
tar_spec=normalSED,
band_start=brange[0], band_end=brange[1],
conf=chip.sls_conf[0],
isAlongY=0,
flat_cube=flat_cube)
self.addSLStoChipImage(
sdp=sdp, chip=chip, xOrderSigPlus=xOrderSigPlus, local_wcs=chip_wcs_local)
Zhang Xin
committed
# 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)
del sdp
# print(self.y_nominal, starImg.center.y, starImg.ymin)
# del psf
return 1, pos_shear
def getGSObj(self, psf, g1=0, g2=0, flux=None, filt=None, tel=None, exptime=150.):
flux = self.getElectronFluxFilt(filt, tel, exptime)
disk = galsim.Sersic(n=self.disk_sersic_idx,
half_light_radius=self.hlr_disk, flux=1.0)
disk_shape = galsim.Shear(g1=self.e1_disk, g2=self.e2_disk)
disk = disk.shear(disk_shape)
bulge = galsim.Sersic(n=self.bulge_sersic_idx,
half_light_radius=self.hlr_bulge, flux=1.0)
bulge_shape = galsim.Shear(g1=self.e1_bulge, g2=self.e2_bulge)
bulge = bulge.shear(bulge_shape)
gal = self.bfrac * bulge + (1.0 - self.bfrac) * disk
gal = gal.withFlux(flux)
gal_shear = galsim.Shear(g1=g1, g2=g2)
gal = gal.shear(gal_shear)
final = galsim.Convolve(psf, gal)
return final
def getObservedEll(self, g1=0, g2=0):
e1_obs, e2_obs, e_obs, theta = eObs(
self.e1_total, self.e2_total, g1, g2)
return self.e1_total, self.e2_total, g1, g2, e1_obs, e2_obs