Loading README.md +4 −0 Original line number Diff line number Diff line # CSST主巡天仿真软件 ## 重要更新或问题修复: * 2024.08.03: 更新至v3.1版本,内容包括: * 加入对导星稳像过程的仿真 * 加入银河系消光的仿真 * Bug修复:修复因滤光片漏光导致的仿真星等不吻合等bug * 2024.05.15: 更新至v3.0版本,新功能具体内容见[软件说明文档](https://kdocs.cn/l/cjyiU0SXGyn2)。 * 2023.07.29: 更新至v2.1版本,内容包括: * 加入杂散光模块,config文件中添加开关:enable_straylight_model: True/False Loading catalog/C9_Catalog.py +41 −3 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ from astropy.table import Table from scipy import interpolate from datetime import datetime from observation_sim.mock_objects import CatalogBase, Star, Galaxy, Quasar from observation_sim.mock_objects import CatalogBase, Star, Galaxy, Quasar, ExtinctionMW from observation_sim.mock_objects._util import tag_sed, getObservedSED, getABMAG, integrate_sed_bandpass, comoving_dist from observation_sim.astrometry.Astrometry_util import on_orbit_obs_position Loading Loading @@ -110,6 +110,16 @@ class Catalog(CatalogBase): self.max_size = 0. # [TODO] Milky Way extinction if "enable_mw_ext_gal" in config["catalog_options"] and config["catalog_options"]["enable_mw_ext_gal"]: if "planck_ebv_map" not in config["catalog_options"]: raise ValueError( "Planck dust map must be given to enable Milky Way extinction calculation for galaxies.") self.mw_ext = ExtinctionMW() self.mw_ext.init_ext_model(model_name="odonnell") self.mw_ext.load_Planck_ext( file_path=config["catalog_options"]["planck_ebv_map"]) if "star_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["star_cat"] and not config["catalog_options"]["galaxy_only"]: # Get the cloest star catalog file star_file_name = get_star_cat( Loading Loading @@ -248,6 +258,12 @@ class Catalog(CatalogBase): input_time_str=time_str ) # [TODO] get Milky Way extinction AVs if "enable_mw_ext_gal" in self.config["catalog_options"] and self.config["catalog_options"]["enable_mw_ext_gal"]: MW_Av_arr = self.mw_ext.Av_from_Planck(ra=ra_arr, dec=dec_arr) else: MW_Av_arr = np.zeros(len(ra_arr)) for igals in range(ngals): # # (TEST) # if igals > 100: Loading @@ -259,6 +275,9 @@ class Catalog(CatalogBase): param['ra_orig'] = gals['ra'][igals] param['dec_orig'] = gals['dec'][igals] # [TODO] get Milky Way extinction AVs param['mw_Av'] = MW_Av_arr[igals] if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): continue Loading Loading @@ -530,11 +549,30 @@ class Catalog(CatalogBase): speci = interpolate.interp1d(wave, flux) lamb = np.arange(2000, 11001+0.5, 0.5) y = speci(lamb) # [TODO] Apply Milky Way extinction if obj.type != 'star' and ("enable_mw_ext_gal" in self.config["catalog_options"] and self.config["catalog_options"]["enable_mw_ext_gal"]): y = self.mw_ext.apply_extinction(y, Av=obj.mw_Av) # erg/s/cm2/A --> photon/s/m2/A all_sed = y * lamb / (cons.h.value * cons.c.value) * 1e-13 sed = Table(np.array([lamb, all_sed]).T, names=('WAVELENGTH', 'FLUX')) if obj.type == 'quasar': # if obj.type == 'quasar': # # integrate to get the magnitudes # sed_photon = np.array([sed['WAVELENGTH'], sed['FLUX']]).T # sed_photon = galsim.LookupTable(x=np.array(sed_photon[:, 0]), f=np.array( # sed_photon[:, 1]), interpolant='nearest') # sed_photon = galsim.SED( # sed_photon, wave_type='A', flux_type='1', fast=False) # interFlux = integrate_sed_bandpass( # sed=sed_photon, bandpass=self.filt.bandpass_full) # obj.param['mag_use_normal'] = getABMAG( # interFlux, self.filt.bandpass_full) # # mag = getABMAG(interFlux, self.filt.bandpass_full) # # print("mag diff = %.3f"%(mag - obj.param['mag_use_normal'])) # integrate to get the magnitudes if obj.type == 'quasar' or obj.type == 'galaxy': sed_photon = np.array([sed['WAVELENGTH'], sed['FLUX']]).T sed_photon = galsim.LookupTable(x=np.array(sed_photon[:, 0]), f=np.array( sed_photon[:, 1]), interpolant='nearest') Loading config/config_overall.yaml +7 −3 Original line number Diff line number Diff line Loading @@ -11,7 +11,7 @@ # can add some of the command-line arguments here as well; # ok to pass either way or both, as long as they are consistent work_dir: "/public/home/fangyuedong/project/workplace/" run_name: "no_nonlinearity_test" run_name: "ext_on" # Project cycle and run counter are used to name the outputs project_cycle: 9 Loading Loading @@ -49,6 +49,10 @@ catalog_options: # rotate galaxy ellipticity rotateEll: 0. # [degree] # Whether to apply milky way extinction to galaxies enable_mw_ext_gal: YES planck_ebv_map: "/public/home/fangyuedong/project/ext_maps/planck/HFI_CompMap_ThermalDustModel_2048_R1.20.fits" ############################################### # Observation setting ############################################### Loading @@ -65,10 +69,10 @@ obs_setting: # - give a list of indexes of pointings: [ip_1, ip_2...] # - run all pointings: null # Note: only valid when a pointing list is specified run_pointings: [1] run_pointings: [0, 1, 2, 3, 4] # Whether to enable astrometric modeling enable_astrometric_model: True enable_astrometric_model: YES # Cut by saturation magnitude in which band? cut_in_band: "z" Loading config/obs_config_SCI.yaml +1 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ obs_id: "00000001" # this setting will only be used if pointing list file is not # Define list of chips # run_chips: [6,7,8,9,11,12,13,14,15,16,17,18,19,20,22,23,24,25] # Photometric chips #run_chips: [1,2,3,4,5,10,21,26,27,28,29,30] # Spectroscopic chips run_chips: [1] run_chips: [17, 22] # Define observation sequence call_sequence: Loading observation_sim/ObservationSim.py +38 −7 Original line number Diff line number Diff line Loading @@ -23,7 +23,7 @@ class Observation(object): self.filter_param = FilterParam() self.Catalog = Catalog def prepare_chip_for_exposure(self, chip, ra_cen, dec_cen, pointing, wcs_fp=None): def prepare_chip_for_exposure(self, chip, ra_cen, dec_cen, pointing, wcs_fp=None, slsPSFOptim=False): # Get WCS for the focal plane if wcs_fp == None: wcs_fp = self.focal_plane.getTanWCS( Loading @@ -34,6 +34,27 @@ class Observation(object): chip.img.setOrigin(chip.bound.xmin, chip.bound.ymin) chip.img.wcs = wcs_fp chip.slsPSFOptim = slsPSFOptim if chip.chipID in [1, 2, 3, 4, 5, 10, 21, 26, 27, 28, 29, 30] and slsPSFOptim: chip.img_stack = {} for id1 in np.arange(2): gn = chip_utils.getChipSLSGratingID(chip.chipID)[id1] orders = {} # for id2 in ['-2','-1','0','1','2']: for id2 in ['0', '1']: o_n = "order"+id2 allbands = {} for id3 in ['1', '2', '3', '4']: w_n = "w"+id3 allbands[w_n] = galsim.ImageF(chip.npix_x, chip.npix_y) allbands[w_n].setOrigin( chip.bound.xmin, chip.bound.ymin) allbands[w_n].wcs = wcs_fp orders[o_n] = allbands chip.img_stack[gn] = orders else: chip.img_stack = {} # Get random generators for this chip chip.rng_poisson, chip.poisson_noise = chip_utils.get_poisson( seed=int(self.config["random_seeds"]["seed_poisson"]) + pointing.id*30 + chip.chipID, sky_level=0.) Loading @@ -45,7 +66,7 @@ class Observation(object): chip.shutter_img = np.ones_like(chip.img.array) else: chip.shutter_img = effects.ShutterEffectArr( chip.img, t_shutter=1.3, dist_bearing=735, dt=1E-3) chip.img, t_exp=pointing.exp_time, t_shutter=1.3, dist_bearing=735, dt=1E-3) chip.prnu_img = effects.PRNU_Img(xsize=chip.npix_x, ysize=chip.npix_y, sigma=0.01, seed=int(self.config["random_seeds"]["seed_prnu"]+chip.chipID)) Loading Loading @@ -91,17 +112,24 @@ class Observation(object): input_date_str=date_str, input_time_str=time_str ) ra_cen, dec_cen = ra_cen[0], dec_cen[0] ra_offset, dec_offset = pointing.ra - \ ra_cen[0], pointing.dec - dec_cen[0] else: ra_offset, dec_offset = 0., 0. ra_cen = pointing.ra dec_cen = pointing.dec slsPSFOpt = False # Prepare necessary chip properties for simulation chip = self.prepare_chip_for_exposure(chip, ra_cen, dec_cen, pointing) chip = self.prepare_chip_for_exposure( chip, ra_cen, dec_cen, pointing, slsPSFOptim=slsPSFOpt) # Initialize SimSteps sim_steps = SimSteps(overall_config=self.config, chip_output=chip_output, all_filters=self.all_filters) chip_output=chip_output, all_filters=self.all_filters, ra_offset=ra_offset, dec_offset=dec_offset) for step in pointing.obs_param["call_sequence"]: if self.config["run_option"]["out_cat_only"]: Loading Loading @@ -130,6 +158,9 @@ class Observation(object): chip_output.Log_info("check running:1: pointing-%d chip-%d pid-%d memory-%6.2fGB" % (pointing.id, chip.chipID, os.getpid(), (psutil.Process(os.getpid()).memory_info().rss / 1024 / 1024 / 1024))) del chip.img del chip.flat_img del chip.prnu_img del chip.shutter_img def runExposure_MPI_PointingList(self, pointing_list, chips=None): comm = MPI.COMM_WORLD Loading Loading
README.md +4 −0 Original line number Diff line number Diff line # CSST主巡天仿真软件 ## 重要更新或问题修复: * 2024.08.03: 更新至v3.1版本,内容包括: * 加入对导星稳像过程的仿真 * 加入银河系消光的仿真 * Bug修复:修复因滤光片漏光导致的仿真星等不吻合等bug * 2024.05.15: 更新至v3.0版本,新功能具体内容见[软件说明文档](https://kdocs.cn/l/cjyiU0SXGyn2)。 * 2023.07.29: 更新至v2.1版本,内容包括: * 加入杂散光模块,config文件中添加开关:enable_straylight_model: True/False Loading
catalog/C9_Catalog.py +41 −3 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ from astropy.table import Table from scipy import interpolate from datetime import datetime from observation_sim.mock_objects import CatalogBase, Star, Galaxy, Quasar from observation_sim.mock_objects import CatalogBase, Star, Galaxy, Quasar, ExtinctionMW from observation_sim.mock_objects._util import tag_sed, getObservedSED, getABMAG, integrate_sed_bandpass, comoving_dist from observation_sim.astrometry.Astrometry_util import on_orbit_obs_position Loading Loading @@ -110,6 +110,16 @@ class Catalog(CatalogBase): self.max_size = 0. # [TODO] Milky Way extinction if "enable_mw_ext_gal" in config["catalog_options"] and config["catalog_options"]["enable_mw_ext_gal"]: if "planck_ebv_map" not in config["catalog_options"]: raise ValueError( "Planck dust map must be given to enable Milky Way extinction calculation for galaxies.") self.mw_ext = ExtinctionMW() self.mw_ext.init_ext_model(model_name="odonnell") self.mw_ext.load_Planck_ext( file_path=config["catalog_options"]["planck_ebv_map"]) if "star_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["star_cat"] and not config["catalog_options"]["galaxy_only"]: # Get the cloest star catalog file star_file_name = get_star_cat( Loading Loading @@ -248,6 +258,12 @@ class Catalog(CatalogBase): input_time_str=time_str ) # [TODO] get Milky Way extinction AVs if "enable_mw_ext_gal" in self.config["catalog_options"] and self.config["catalog_options"]["enable_mw_ext_gal"]: MW_Av_arr = self.mw_ext.Av_from_Planck(ra=ra_arr, dec=dec_arr) else: MW_Av_arr = np.zeros(len(ra_arr)) for igals in range(ngals): # # (TEST) # if igals > 100: Loading @@ -259,6 +275,9 @@ class Catalog(CatalogBase): param['ra_orig'] = gals['ra'][igals] param['dec_orig'] = gals['dec'][igals] # [TODO] get Milky Way extinction AVs param['mw_Av'] = MW_Av_arr[igals] if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): continue Loading Loading @@ -530,11 +549,30 @@ class Catalog(CatalogBase): speci = interpolate.interp1d(wave, flux) lamb = np.arange(2000, 11001+0.5, 0.5) y = speci(lamb) # [TODO] Apply Milky Way extinction if obj.type != 'star' and ("enable_mw_ext_gal" in self.config["catalog_options"] and self.config["catalog_options"]["enable_mw_ext_gal"]): y = self.mw_ext.apply_extinction(y, Av=obj.mw_Av) # erg/s/cm2/A --> photon/s/m2/A all_sed = y * lamb / (cons.h.value * cons.c.value) * 1e-13 sed = Table(np.array([lamb, all_sed]).T, names=('WAVELENGTH', 'FLUX')) if obj.type == 'quasar': # if obj.type == 'quasar': # # integrate to get the magnitudes # sed_photon = np.array([sed['WAVELENGTH'], sed['FLUX']]).T # sed_photon = galsim.LookupTable(x=np.array(sed_photon[:, 0]), f=np.array( # sed_photon[:, 1]), interpolant='nearest') # sed_photon = galsim.SED( # sed_photon, wave_type='A', flux_type='1', fast=False) # interFlux = integrate_sed_bandpass( # sed=sed_photon, bandpass=self.filt.bandpass_full) # obj.param['mag_use_normal'] = getABMAG( # interFlux, self.filt.bandpass_full) # # mag = getABMAG(interFlux, self.filt.bandpass_full) # # print("mag diff = %.3f"%(mag - obj.param['mag_use_normal'])) # integrate to get the magnitudes if obj.type == 'quasar' or obj.type == 'galaxy': sed_photon = np.array([sed['WAVELENGTH'], sed['FLUX']]).T sed_photon = galsim.LookupTable(x=np.array(sed_photon[:, 0]), f=np.array( sed_photon[:, 1]), interpolant='nearest') Loading
config/config_overall.yaml +7 −3 Original line number Diff line number Diff line Loading @@ -11,7 +11,7 @@ # can add some of the command-line arguments here as well; # ok to pass either way or both, as long as they are consistent work_dir: "/public/home/fangyuedong/project/workplace/" run_name: "no_nonlinearity_test" run_name: "ext_on" # Project cycle and run counter are used to name the outputs project_cycle: 9 Loading Loading @@ -49,6 +49,10 @@ catalog_options: # rotate galaxy ellipticity rotateEll: 0. # [degree] # Whether to apply milky way extinction to galaxies enable_mw_ext_gal: YES planck_ebv_map: "/public/home/fangyuedong/project/ext_maps/planck/HFI_CompMap_ThermalDustModel_2048_R1.20.fits" ############################################### # Observation setting ############################################### Loading @@ -65,10 +69,10 @@ obs_setting: # - give a list of indexes of pointings: [ip_1, ip_2...] # - run all pointings: null # Note: only valid when a pointing list is specified run_pointings: [1] run_pointings: [0, 1, 2, 3, 4] # Whether to enable astrometric modeling enable_astrometric_model: True enable_astrometric_model: YES # Cut by saturation magnitude in which band? cut_in_band: "z" Loading
config/obs_config_SCI.yaml +1 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ obs_id: "00000001" # this setting will only be used if pointing list file is not # Define list of chips # run_chips: [6,7,8,9,11,12,13,14,15,16,17,18,19,20,22,23,24,25] # Photometric chips #run_chips: [1,2,3,4,5,10,21,26,27,28,29,30] # Spectroscopic chips run_chips: [1] run_chips: [17, 22] # Define observation sequence call_sequence: Loading
observation_sim/ObservationSim.py +38 −7 Original line number Diff line number Diff line Loading @@ -23,7 +23,7 @@ class Observation(object): self.filter_param = FilterParam() self.Catalog = Catalog def prepare_chip_for_exposure(self, chip, ra_cen, dec_cen, pointing, wcs_fp=None): def prepare_chip_for_exposure(self, chip, ra_cen, dec_cen, pointing, wcs_fp=None, slsPSFOptim=False): # Get WCS for the focal plane if wcs_fp == None: wcs_fp = self.focal_plane.getTanWCS( Loading @@ -34,6 +34,27 @@ class Observation(object): chip.img.setOrigin(chip.bound.xmin, chip.bound.ymin) chip.img.wcs = wcs_fp chip.slsPSFOptim = slsPSFOptim if chip.chipID in [1, 2, 3, 4, 5, 10, 21, 26, 27, 28, 29, 30] and slsPSFOptim: chip.img_stack = {} for id1 in np.arange(2): gn = chip_utils.getChipSLSGratingID(chip.chipID)[id1] orders = {} # for id2 in ['-2','-1','0','1','2']: for id2 in ['0', '1']: o_n = "order"+id2 allbands = {} for id3 in ['1', '2', '3', '4']: w_n = "w"+id3 allbands[w_n] = galsim.ImageF(chip.npix_x, chip.npix_y) allbands[w_n].setOrigin( chip.bound.xmin, chip.bound.ymin) allbands[w_n].wcs = wcs_fp orders[o_n] = allbands chip.img_stack[gn] = orders else: chip.img_stack = {} # Get random generators for this chip chip.rng_poisson, chip.poisson_noise = chip_utils.get_poisson( seed=int(self.config["random_seeds"]["seed_poisson"]) + pointing.id*30 + chip.chipID, sky_level=0.) Loading @@ -45,7 +66,7 @@ class Observation(object): chip.shutter_img = np.ones_like(chip.img.array) else: chip.shutter_img = effects.ShutterEffectArr( chip.img, t_shutter=1.3, dist_bearing=735, dt=1E-3) chip.img, t_exp=pointing.exp_time, t_shutter=1.3, dist_bearing=735, dt=1E-3) chip.prnu_img = effects.PRNU_Img(xsize=chip.npix_x, ysize=chip.npix_y, sigma=0.01, seed=int(self.config["random_seeds"]["seed_prnu"]+chip.chipID)) Loading Loading @@ -91,17 +112,24 @@ class Observation(object): input_date_str=date_str, input_time_str=time_str ) ra_cen, dec_cen = ra_cen[0], dec_cen[0] ra_offset, dec_offset = pointing.ra - \ ra_cen[0], pointing.dec - dec_cen[0] else: ra_offset, dec_offset = 0., 0. ra_cen = pointing.ra dec_cen = pointing.dec slsPSFOpt = False # Prepare necessary chip properties for simulation chip = self.prepare_chip_for_exposure(chip, ra_cen, dec_cen, pointing) chip = self.prepare_chip_for_exposure( chip, ra_cen, dec_cen, pointing, slsPSFOptim=slsPSFOpt) # Initialize SimSteps sim_steps = SimSteps(overall_config=self.config, chip_output=chip_output, all_filters=self.all_filters) chip_output=chip_output, all_filters=self.all_filters, ra_offset=ra_offset, dec_offset=dec_offset) for step in pointing.obs_param["call_sequence"]: if self.config["run_option"]["out_cat_only"]: Loading Loading @@ -130,6 +158,9 @@ class Observation(object): chip_output.Log_info("check running:1: pointing-%d chip-%d pid-%d memory-%6.2fGB" % (pointing.id, chip.chipID, os.getpid(), (psutil.Process(os.getpid()).memory_info().rss / 1024 / 1024 / 1024))) del chip.img del chip.flat_img del chip.prnu_img del chip.shutter_img def runExposure_MPI_PointingList(self, pointing_list, chips=None): comm = MPI.COMM_WORLD Loading