Commit 3226117c authored by Zhang Xin's avatar Zhang Xin
Browse files

Merge branch 'develop' into 'release_v2.0'

version 2.1.0

See merge request csst_sim/csst-simulation!16
parents 81589f9d f540664f
import numpy as np import numpy as np
import galsim import galsim
import copy import copy
import cmath
from astropy.table import Table from astropy.table import Table
from abc import abstractmethod, ABCMeta from abc import abstractmethod, ABCMeta
...@@ -73,6 +74,16 @@ class CatalogBase(metaclass=ABCMeta): ...@@ -73,6 +74,16 @@ class CatalogBase(metaclass=ABCMeta):
} }
return param return param
@staticmethod
def rotate_ellipticity(e1, e2, rotation=0., unit='radians'):
if unit == 'degree':
rotation = np.radians(rotation)
e_total = np.sqrt(e1**2 + e2**2)
phi = cmath.phase(complex(e1, e2))
e1 = e_total * np.cos(phi + 2*rotation)
e2 = e_total * np.sin(phi + 2*rotation)
return e1, e2, e_total
@staticmethod @staticmethod
def convert_sed(mag, sed, target_filt, norm_filt=None): def convert_sed(mag, sed, target_filt, norm_filt=None):
bandpass = target_filt.bandpass_full bandpass = target_filt.bandpass_full
......
...@@ -12,7 +12,7 @@ from ObservationSim.MockObject.MockObject import MockObject ...@@ -12,7 +12,7 @@ from ObservationSim.MockObject.MockObject import MockObject
# import tracemalloc # import tracemalloc
class Galaxy(MockObject): class Galaxy(MockObject):
def __init__(self, param, rotation=None, logger=None): def __init__(self, param, logger=None):
super().__init__(param, logger=logger) super().__init__(param, logger=logger)
# self.thetaR = self.param["theta"] # self.thetaR = self.param["theta"]
# self.bfrac = self.param["bfrac"] # self.bfrac = self.param["bfrac"]
...@@ -27,8 +27,6 @@ class Galaxy(MockObject): ...@@ -27,8 +27,6 @@ class Galaxy(MockObject):
# self.e1_bulge, self.e2_bulge = self.e_bulge.g1, self.e_bulge.g2 # self.e1_bulge, self.e2_bulge = self.e_bulge.g1, self.e_bulge.g2
# self.e1_total, self.e2_total = self.e_total.g1, self.e_total.g2 # self.e1_total, self.e2_total = self.e_total.g1, self.e_total.g2
if rotation is not None:
self.rotateEllipticity(rotation)
if not hasattr(self, "disk_sersic_idx"): if not hasattr(self, "disk_sersic_idx"):
self.disk_sersic_idx = 1. self.disk_sersic_idx = 1.
if not hasattr(self, "bulge_sersic_idx"): if not hasattr(self, "bulge_sersic_idx"):
...@@ -51,6 +49,7 @@ class Galaxy(MockObject): ...@@ -51,6 +49,7 @@ class Galaxy(MockObject):
full = integrate_sed_bandpass(sed=self.sed, bandpass=filt.bandpass_full) full = integrate_sed_bandpass(sed=self.sed, bandpass=filt.bandpass_full)
except Exception as e: except Exception as e:
print(e) print(e)
if self.logger:
self.logger.error(e) self.logger.error(e)
return -1 return -1
for i in range(len(bandpass_list)): for i in range(len(bandpass_list)):
...@@ -59,6 +58,7 @@ class Galaxy(MockObject): ...@@ -59,6 +58,7 @@ class Galaxy(MockObject):
sub = integrate_sed_bandpass(sed=self.sed, bandpass=bandpass) sub = integrate_sed_bandpass(sed=self.sed, bandpass=bandpass)
except Exception as e: except Exception as e:
print(e) print(e)
if self.logger:
self.logger.error(e) self.logger.error(e)
return -1 return -1
...@@ -78,12 +78,13 @@ class Galaxy(MockObject): ...@@ -78,12 +78,13 @@ class Galaxy(MockObject):
gal = self.bfrac * bulge + (1.0 - self.bfrac) * disk gal = self.bfrac * bulge + (1.0 - self.bfrac) * disk
gal = gal.withFlux(nphotons) gal = gal.withFlux(nphotons)
if fd_shear is not None:
g1 += fd_shear.g1
g2 += fd_shear.g2
gal_shear = galsim.Shear(g1=g1, g2=g2) gal_shear = galsim.Shear(g1=g1, g2=g2)
gal = gal.shear(gal_shear) gal = gal.shear(gal_shear)
gal = galsim.Convolve(psf, gal) gal = galsim.Convolve(psf, gal)
if fd_shear is not None:
gal = gal.shear(fd_shear)
objs.append(gal) objs.append(gal)
final = galsim.Sum(objs) final = galsim.Sum(objs)
return final return final
...@@ -97,6 +98,7 @@ class Galaxy(MockObject): ...@@ -97,6 +98,7 @@ class Galaxy(MockObject):
full = integrate_sed_bandpass(sed=self.sed, bandpass=filt.bandpass_full) full = integrate_sed_bandpass(sed=self.sed, bandpass=filt.bandpass_full)
except Exception as e: except Exception as e:
print(e) print(e)
if self.logger:
self.logger.error(e) self.logger.error(e)
return 2, None return 2, None
...@@ -131,6 +133,18 @@ class Galaxy(MockObject): ...@@ -131,6 +133,18 @@ class Galaxy(MockObject):
real_wcs_local = self.real_wcs.local(self.real_pos) real_wcs_local = self.real_wcs.local(self.real_pos)
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 fd_shear:
g1 += fd_shear.g1
g2 += fd_shear.g2
gal_shear = galsim.Shear(g1=g1, g2=g2)
for i in range(len(bandpass_list)): for i in range(len(bandpass_list)):
bandpass = bandpass_list[i] bandpass = bandpass_list[i]
...@@ -138,6 +152,7 @@ class Galaxy(MockObject): ...@@ -138,6 +152,7 @@ class Galaxy(MockObject):
sub = integrate_sed_bandpass(sed=self.sed, bandpass=bandpass) sub = integrate_sed_bandpass(sed=self.sed, bandpass=bandpass)
except Exception as e: except Exception as e:
print(e) print(e)
if self.logger:
self.logger.error(e) self.logger.error(e)
# return False # return False
continue continue
...@@ -153,41 +168,24 @@ class Galaxy(MockObject): ...@@ -153,41 +168,24 @@ class Galaxy(MockObject):
# print("nphotons_sub-band_%d = %.2f"%(i, nphotons)) # print("nphotons_sub-band_%d = %.2f"%(i, nphotons))
psf, pos_shear = psf_model.get_PSF(chip=chip, pos_img=pos_img, bandpass=bandpass, folding_threshold=folding_threshold) 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)
gal = self.bfrac * bulge + (1.0 - self.bfrac) * disk gal_temp = self.bfrac * bulge + (1.0 - self.bfrac) * disk
gal_temp = gal_temp.shear(gal_shear)
gal_temp = gal_temp.withFlux(nphotons)
if not big_galaxy: # Not apply PSF for very big galaxy
gal_temp = galsim.Convolve(psf, gal_temp)
if i == 0:
gal = gal_temp
else:
gal = gal + gal_temp
# (TEST) Random knots # (TEST) Random knots
# knots = galsim.RandomKnots(npoints=100, profile=disk) # knots = galsim.RandomKnots(npoints=100, profile=disk)
# kfrac = np.random.random()*(1.0 - self.bfrac) # kfrac = np.random.random()*(1.0 - self.bfrac)
# gal = self.bfrac * bulge + (1.0 - self.bfrac - kfrac) * disk + kfrac * knots # gal = self.bfrac * bulge + (1.0 - self.bfrac - kfrac) * disk + kfrac * knots
gal = gal.withFlux(nphotons)
gal_shear = galsim.Shear(g1=g1, g2=g2)
gal = gal.shear(gal_shear)
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)
# Use (explicit) stamps to draw
stamp = gal.drawImage(wcs=real_wcs_local, method='phot', offset=offset, save_photons=True)
xmax = max(xmax, stamp.xmax - stamp.xmin)
ymax = max(ymax, stamp.ymax - stamp.ymin)
photons = stamp.photons
photons.x += x_nominal
photons.y += y_nominal
photons_list.append(photons)
del gal
# # [C6 TEST] # # [C6 TEST]
# print('xmax = %d, ymax = %d '%(xmax, ymax)) # print('xmax = %d, ymax = %d '%(xmax, ymax))
# # Output memory usage # # Output memory usage
...@@ -196,7 +194,12 @@ class Galaxy(MockObject): ...@@ -196,7 +194,12 @@ class Galaxy(MockObject):
# for stat in top_stats[:10]: # for stat in top_stats[:10]:
# print(stat) # print(stat)
stamp = galsim.ImageF(int(xmax * 1.1), int(ymax * 1.1)) stamp = gal.drawImage(wcs=real_wcs_local, method='phot', offset=offset, save_photons=True)
photons = stamp.photons
photons.x += x_nominal
photons.y += y_nominal
photons_list.append(photons)
stamp.wcs = real_wcs_local stamp.wcs = real_wcs_local
stamp.setCenter(x_nominal, y_nominal) stamp.setCenter(x_nominal, y_nominal)
bounds = stamp.bounds & galsim.BoundsI(0, chip.npix_x - 1, 0, chip.npix_y - 1) bounds = stamp.bounds & galsim.BoundsI(0, chip.npix_x - 1, 0, chip.npix_y - 1)
...@@ -226,6 +229,7 @@ class Galaxy(MockObject): ...@@ -226,6 +229,7 @@ class Galaxy(MockObject):
else: else:
# Return code 0: object photons missed this detector # Return code 0: object photons missed this detector
print("obj %s missed"%(self.id)) print("obj %s missed"%(self.id))
if self.logger:
self.logger.info("obj %s missed"%(self.id)) self.logger.info("obj %s missed"%(self.id))
return 0, pos_shear return 0, pos_shear
...@@ -297,14 +301,17 @@ class Galaxy(MockObject): ...@@ -297,14 +301,17 @@ class Galaxy(MockObject):
# gal = self.bfrac * bulge + (1.0 - self.bfrac - kfrac) * disk + kfrac * knots # gal = self.bfrac * bulge + (1.0 - self.bfrac - kfrac) * disk + kfrac * knots
gal = gal.withFlux(tel.pupil_area * exptime) gal = gal.withFlux(tel.pupil_area * exptime)
if fd_shear:
g1 += fd_shear.g1
g2 += fd_shear.g2
gal_shear = galsim.Shear(g1=g1, g2=g2) gal_shear = galsim.Shear(g1=g1, g2=g2)
gal = gal.shear(gal_shear) gal = gal.shear(gal_shear)
gal = galsim.Convolve(psf, gal) gal = galsim.Convolve(psf, gal)
if not big_galaxy: # Not apply PSF for very big galaxy if not big_galaxy: # Not apply PSF for very big galaxy
gal = galsim.Convolve(psf, gal) gal = galsim.Convolve(psf, gal)
if fd_shear is not None: # if fd_shear is not None:
gal = gal.shear(fd_shear) # gal = gal.shear(fd_shear)
starImg = gal.drawImage(wcs=real_wcs_local, offset=offset) starImg = gal.drawImage(wcs=real_wcs_local, offset=offset)
...@@ -397,14 +404,6 @@ class Galaxy(MockObject): ...@@ -397,14 +404,6 @@ class Galaxy(MockObject):
final = galsim.Convolve(psf, gal) final = galsim.Convolve(psf, gal)
return final return final
def rotateEllipticity(self, rotation):
if rotation == 1:
self.e1_disk, self.e2_disk, self.e1_bulge, self.e2_bulge, self.e1_total, self.e2_total = -self.e2_disk, self.e1_disk, -self.e2_bulge, self.e1_bulge, -self.e2_total, self.e1_total
if rotation == 2:
self.e1_disk, self.e2_disk, self.e1_bulge, self.e2_bulge, self.e1_total, self.e2_total = -self.e1_disk, -self.e2_disk, -self.e1_bulge, -self.e2_bulge, -self.e1_total, -self.e2_total
if rotation == 3:
self.e1_disk, self.e2_disk, self.e1_bulge, self.e2_bulge, self.e1_total, self.e2_total = self.e2_disk, -self.e1_disk, self.e2_bulge, -self.e1_bulge, self.e2_total, -self.e1_total
def drawObject(self, img, final, noise_level=0.0, flux=None, filt=None, tel=None, exptime=150.): def drawObject(self, img, final, noise_level=0.0, flux=None, filt=None, tel=None, exptime=150.):
""" Override the method in parent class """ Override the method in parent class
Need to constrain the size of image stamp for extended objects Need to constrain the size of image stamp for extended objects
......
...@@ -32,6 +32,7 @@ class MockObject(object): ...@@ -32,6 +32,7 @@ class MockObject(object):
# Place holder for outputs # Place holder for outputs
self.additional_output_str = "" self.additional_output_str = ""
self.fd_shear = None self.fd_shear = None
self.logger = logger self.logger = logger
...@@ -61,7 +62,7 @@ class MockObject(object): ...@@ -61,7 +62,7 @@ class MockObject(object):
dec = self.param["dec"] dec = self.param["dec"]
return galsim.CelestialCoord(ra=ra * galsim.degrees, dec=dec * galsim.degrees) return galsim.CelestialCoord(ra=ra * galsim.degrees, dec=dec * galsim.degrees)
def getPosImg_Offset_WCS(self, img, fdmodel=None, chip=None, verbose=True, img_header=None): def getPosImg_Offset_WCS(self, img, fdmodel=None, chip=None, verbose=True, chip_wcs=None, img_header=None):
self.posImg = img.wcs.toImage(self.getPosWorld()) self.posImg = img.wcs.toImage(self.getPosWorld())
self.localWCS = img.wcs.local(self.posImg) self.localWCS = img.wcs.local(self.posImg)
if (fdmodel is not None) and (chip is not None): if (fdmodel is not None) and (chip is not None):
...@@ -80,7 +81,9 @@ class MockObject(object): ...@@ -80,7 +81,9 @@ class MockObject(object):
dy = y - self.y_nominal dy = y - self.y_nominal
self.offset = galsim.PositionD(dx, dy) self.offset = galsim.PositionD(dx, dy)
if img_header is not None: if chip_wcs is not None:
self.real_wcs = chip_wcs
elif img_header is not None:
self.real_wcs = galsim.FitsWCS(header=img_header) self.real_wcs = galsim.FitsWCS(header=img_header)
else: else:
self.real_wcs = None self.real_wcs = None
...@@ -132,6 +135,7 @@ class MockObject(object): ...@@ -132,6 +135,7 @@ class MockObject(object):
full = integrate_sed_bandpass(sed=self.sed, bandpass=filt.bandpass_full) full = integrate_sed_bandpass(sed=self.sed, bandpass=filt.bandpass_full)
except Exception as e: except Exception as e:
print(e) print(e)
if self.logger:
self.logger.error(e) self.logger.error(e)
return 2, None return 2, None
...@@ -164,6 +168,7 @@ class MockObject(object): ...@@ -164,6 +168,7 @@ class MockObject(object):
sub = integrate_sed_bandpass(sed=self.sed, bandpass=bandpass) sub = integrate_sed_bandpass(sed=self.sed, bandpass=bandpass)
except Exception as e: except Exception as e:
print(e) print(e)
if self.logger:
self.logger.error(e) self.logger.error(e)
# return False # return False
continue continue
...@@ -214,6 +219,7 @@ class MockObject(object): ...@@ -214,6 +219,7 @@ class MockObject(object):
else: else:
# Return code 0: object photons missed this detector # Return code 0: object photons missed this detector
print("obj %s missed"%(self.id)) print("obj %s missed"%(self.id))
if self.logger:
self.logger.info("obj %s missed"%(self.id)) self.logger.info("obj %s missed"%(self.id))
return 0, pos_shear return 0, pos_shear
......
...@@ -122,7 +122,7 @@ class SpecDisperser(object): ...@@ -122,7 +122,7 @@ class SpecDisperser(object):
beam=beam) beam=beam)
### Account for pixel centering of the trace ### Account for pixel centering of the trace
yfrac_beam = ytrace_beam - floor(ytrace_beam) yfrac_beam = ytrace_beam - floor(ytrace_beam+0.5)
ysens = lam_beam * 0 ysens = lam_beam * 0
lam_index = argsort(lam_beam) lam_index = argsort(lam_beam)
...@@ -155,7 +155,7 @@ class SpecDisperser(object): ...@@ -155,7 +155,7 @@ class SpecDisperser(object):
sensitivity_beam = ysens sensitivity_beam = ysens
len_spec_x = len(dx) len_spec_x = len(dx)
len_spec_y = int(ceil(yfrac_beam[-1]) - floor(yfrac_beam[0]) + 1) len_spec_y = int(ceil(ytrace_beam[-1]) - floor(ytrace_beam[0]) + 1)
beam_sh = (self.img_sh[0] + len_spec_y, self.img_sh[1] + len_spec_x) beam_sh = (self.img_sh[0] + len_spec_y, self.img_sh[1] + len_spec_x)
modelf = zeros(product(beam_sh), dtype=float) modelf = zeros(product(beam_sh), dtype=float)
...@@ -165,9 +165,15 @@ class SpecDisperser(object): ...@@ -165,9 +165,15 @@ class SpecDisperser(object):
dxpix = dx - dx[0] + x0[1] dxpix = dx - dx[0] + x0[1]
dyc = cast[int](ytrace_beam) dyc = cast[int](np.floor(ytrace_beam+0.5))
dypix = cast[int](np.floor(ytrace_beam - dyc[0] + x0[0] + 0.5))
frac_ids = yfrac_beam<0
dypix[frac_ids] = dypix[frac_ids] - 1
yfrac_beam[frac_ids] = 1+yfrac_beam[frac_ids]
dypix = dyc - dyc[0] + x0[0]
flat_index = idx[dypix, dxpix] flat_index = idx[dypix, dxpix]
nonz = sensitivity_beam != 0 nonz = sensitivity_beam != 0
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment