Loading Catalog/C3Catalog.py +17 −5 Original line number Diff line number Diff line Loading @@ -28,6 +28,11 @@ class C3Catalog(CatalogBase): self.cat_dir = os.path.join(config["data_dir"], config["input_path"]["cat_dir"]) self.seed_Av = config["random_seeds"]["seed_Av"] if "logger" in kwargs: self.logger = kwargs["logger"] else: self.logger = None with pkg_resources.path('Catalog.data', 'SLOAN_SDSS.g.fits') as filter_path: self.normF_star = Table.read(str(filter_path)) with pkg_resources.path('Catalog.data', 'lsst_throuput_g.fits') as filter_path: Loading Loading @@ -63,6 +68,10 @@ class C3Catalog(CatalogBase): dec = np.deg2rad(np.array([dec_max, dec_max, dec_min, dec_min])) vertices = spherical_to_cartesian(1., dec, ra) self.pix_list = hp.query_polygon(NSIDE, np.array(vertices).T, inclusive=True) if self.logger is not None: msg = str(("HEALPix List: ", self.pix_list)) self.logger.info(msg) else: print("HEALPix List: ", self.pix_list) def load_norm_filt(self, obj): Loading Loading @@ -169,10 +178,10 @@ class C3Catalog(CatalogBase): param['id'] = gals['galaxyID'][igals] if param['star'] == 0: obj = Galaxy(param, self.rotation) obj = Galaxy(param, self.rotation, logger=self.logger) self.objs.append(obj) if param['star'] == 2: obj = Quasar(param) obj = Quasar(param, logger=self.logger) self.objs.append(obj) def _load_stars(self, stars, pix_id=None): Loading Loading @@ -230,7 +239,7 @@ class C3Catalog(CatalogBase): param['feh'] = stars['feh'][istars] param['z'] = 0.0 param['star'] = 1 # Star obj = Star(param) obj = Star(param, logger=self.logger) self.objs.append(obj) def _load(self, **kwargs): Loading @@ -250,6 +259,9 @@ class C3Catalog(CatalogBase): gals = gals_cat[str(pix)] self._load_gals(gals, pix_id=pix) del gals if self.logger is not None: self.logger.info("number of objects in catalog: %d"%(len(self.objs))) else: print("number of objects in catalog: ", len(self.objs)) del self.avGal Loading Catalog/NGPCatalog.py 0 → 100644 +304 −0 Original line number Diff line number Diff line import os import galsim import random import numpy as np import h5py as h5 import healpy as hp import astropy.constants as cons from astropy.coordinates import spherical_to_cartesian from astropy.table import Table from scipy import interpolate from datetime import datetime from ObservationSim.MockObject import CatalogBase, Star, Galaxy, Quasar from ObservationSim.MockObject._util import seds, sed_assign, extAv, tag_sed, getObservedSED from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position try: import importlib.resources as pkg_resources except ImportError: # Try backported to PY<37 'importlib_resources' import importlib_resources as pkg_resources NSIDE = 128 class NGPCatalog(CatalogBase): def __init__(self, config, chip, pointing, **kwargs): super().__init__() self.cat_dir = os.path.join(config["data_dir"], config["input_path"]["cat_dir"]) self.seed_Av = config["random_seeds"]["seed_Av"] if "logger" in kwargs: self.logger = kwargs["logger"] else: self.logger = None with pkg_resources.path('Catalog.data', 'SLOAN_SDSS.g.fits') as filter_path: self.normF_star = Table.read(str(filter_path)) with pkg_resources.path('Catalog.data', 'lsst_throuput_g.fits') as filter_path: self.normF_galaxy = Table.read(str(filter_path)) self.config = config self.chip = chip self.pointing = pointing if "star_cat" in config["input_path"] and config["input_path"]["star_cat"] and not config["run_option"]["galaxy_only"]: star_file = config["input_path"]["star_cat"] star_SED_file = config["SED_templates_path"]["star_SED"] self.star_path = os.path.join(self.cat_dir, star_file) self.star_SED_path = os.path.join(config["data_dir"], star_SED_file) self._load_SED_lib_star() if "galaxy_cat" in config["input_path"] and config["input_path"]["galaxy_cat"] and not config["run_option"]["star_only"]: galaxy_file = config["input_path"]["galaxy_cat"] self.galaxy_path = os.path.join(self.cat_dir, galaxy_file) self.galaxy_SED_path = os.path.join(config["data_dir"], config["SED_templates_path"]["galaxy_SED"]) self._load_SED_lib_gals() if "rotateEll" in config["shear_setting"]: self.rotation = float(int(config["shear_setting"]["rotateEll"]/45.)) else: self.rotation = 0. self._get_healpix_list() self._load() def _get_healpix_list(self): self.sky_coverage = self.chip.getSkyCoverageEnlarged(self.chip.img.wcs, margin=0.2) ra_min, ra_max, dec_min, dec_max = self.sky_coverage.xmin, self.sky_coverage.xmax, self.sky_coverage.ymin, self.sky_coverage.ymax ra = np.deg2rad(np.array([ra_min, ra_max, ra_max, ra_min])) dec = np.deg2rad(np.array([dec_max, dec_max, dec_min, dec_min])) vertices = spherical_to_cartesian(1., dec, ra) self.pix_list = hp.query_polygon(NSIDE, np.array(vertices).T, inclusive=True) if self.logger is not None: msg = str(("HEALPix List: ", self.pix_list)) self.logger.info(msg) else: print("HEALPix List: ", self.pix_list) def load_norm_filt(self, obj): if obj.type == "star": return self.normF_star elif obj.type == "galaxy" or obj.type == "quasar": return self.normF_galaxy else: return None def _load_SED_lib_star(self): self.tempSED_star = h5.File(self.star_SED_path,'r') def _load_SED_lib_gals(self): self.tempSed_gal, self.tempRed_gal = seds("galaxy.list", seddir=self.galaxy_SED_path) def _load_gals(self, gals, pix_id=None): ngals = len(gals['galaxyID']) self.rng_sedGal = random.Random() self.rng_sedGal.seed(pix_id) # Use healpix index as the random seed self.ud = galsim.UniformDeviate(pix_id) # Apply astrometric modeling # in C3 case only aberration ra_arr = gals['ra_true'][:] dec_arr = gals['dec_true'][:] if self.config["obs_setting"]["enable_astrometric_model"]: ra_list = ra_arr.tolist() dec_list = dec_arr.tolist() pmra_list = np.zeros(ngals).tolist() pmdec_list = np.zeros(ngals).tolist() rv_list = np.zeros(ngals).tolist() parallax_list = [1e-9] * ngals dt = datetime.fromtimestamp(self.pointing.timestamp) date_str = dt.date().isoformat() time_str = dt.time().isoformat() ra_arr, dec_arr = on_orbit_obs_position( input_ra_list=ra_list, input_dec_list=dec_list, input_pmra_list=pmra_list, input_pmdec_list=pmdec_list, input_rv_list=rv_list, input_parallax_list=parallax_list, input_nstars=ngals, input_x=self.pointing.sat_x, input_y=self.pointing.sat_y, input_z=self.pointing.sat_z, input_vx=self.pointing.sat_vx, input_vy=self.pointing.sat_vy, input_vz=self.pointing.sat_vz, input_epoch="J2015.5", input_date_str=date_str, input_time_str=time_str ) for igals in range(ngals): param = self.initialize_param() param['ra'] = ra_arr[igals] param['dec'] = dec_arr[igals] param['ra_orig'] = gals['ra_true'][igals] param['dec_orig'] = gals['dec_true'][igals] if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): continue param['mag_use_normal'] = gals['mag_true_g_lsst'][igals] if param['mag_use_normal'] >= 26.5: continue param['z'] = gals['redshift_true'][igals] param['model_tag'] = 'None' param['gamma1'] = 0 param['gamma2'] = 0 param['kappa'] = 0 param['delta_ra'] = 0 param['delta_dec'] = 0 # sersicB = gals['sersic_bulge'][igals] hlrMajB = gals['size_bulge_true'][igals] hlrMinB = gals['size_minor_bulge_true'][igals] # sersicD = gals['sersic_disk'][igals] hlrMajD = gals['size_disk_true'][igals] hlrMinD = gals['size_minor_disk_true'][igals] aGal = gals['size_true'][igals] bGal = gals['size_minor_true'][igals] param['bfrac'] = gals['bulge_to_total_ratio_i'][igals] param['theta'] = gals['position_angle_true'][igals] param['hlr_bulge'] = np.sqrt(hlrMajB * hlrMinB) param['hlr_disk'] = np.sqrt(hlrMajD * hlrMinD) param['ell_bulge'] = (hlrMajB - hlrMinB)/(hlrMajB + hlrMinB) param['ell_disk'] = (hlrMajD - hlrMinD)/(hlrMajD + hlrMinD) param['ell_tot'] = (aGal - bGal) / (aGal + bGal) # Assign each galaxy a template SED param['sed_type'] = sed_assign(phz=param['z'], btt=param['bfrac'], rng=self.rng_sedGal) param['redden'] = self.tempRed_gal[param['sed_type']] param['av'] = self.avGal[int(self.ud()*self.nav)] if param['sed_type'] <= 5: param['av'] = 0.0 param['redden'] = 0 param['star'] = 0 # Galaxy if param['sed_type'] >= 29: param['av'] = 0.6 * param['av'] / 3.0 # for quasar, av=[0, 0.2], 3.0=av.max-av.im param['star'] = 2 # Quasar self.ids += 1 # param['id'] = self.ids param['id'] = gals['galaxyID'][igals] if param['star'] == 0: obj = Galaxy(param, self.rotation, logger=self.logger) self.objs.append(obj) if param['star'] == 2: obj = Quasar(param, logger=self.logger) self.objs.append(obj) def _load_stars(self, stars, pix_id=None): nstars = len(stars['sourceID']) # Apply astrometric modeling ra_arr = stars["RA"][:] dec_arr = stars["Dec"][:] pmra_arr = stars['pmra'][:] pmdec_arr = stars['pmdec'][:] rv_arr = stars['RV'][:] parallax_arr = stars['parallax'][:] if self.config["obs_setting"]["enable_astrometric_model"]: ra_list = ra_arr.tolist() dec_list = dec_arr.tolist() pmra_list = pmra_arr.tolist() pmdec_list = pmdec_arr.tolist() rv_list = rv_arr.tolist() parallax_list = parallax_arr.tolist() dt = datetime.fromtimestamp(self.pointing.timestamp) date_str = dt.date().isoformat() time_str = dt.time().isoformat() ra_arr, dec_arr = on_orbit_obs_position( input_ra_list=ra_list, input_dec_list=dec_list, input_pmra_list=pmra_list, input_pmdec_list=pmdec_list, input_rv_list=rv_list, input_parallax_list=parallax_list, input_nstars=nstars, input_x=self.pointing.sat_x, input_y=self.pointing.sat_y, input_z=self.pointing.sat_z, input_vx=self.pointing.sat_vx, input_vy=self.pointing.sat_vy, input_vz=self.pointing.sat_vz, input_epoch="J2015.5", input_date_str=date_str, input_time_str=time_str ) for istars in range(nstars): param = self.initialize_param() param['ra'] = ra_arr[istars] param['dec'] = dec_arr[istars] param['ra_orig'] = stars["RA"][istars] param['dec_orig'] = stars["Dec"][istars] param['pmra'] = pmra_arr[istars] param['pmdec'] = pmdec_arr[istars] param['rv'] = rv_arr[istars] param['parallax'] = parallax_arr[istars] if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): continue param['mag_use_normal'] = stars['app_sdss_g'][istars] if param['mag_use_normal'] >= 26.5: continue self.ids += 1 # param['id'] = self.ids param['id'] = stars['sourceID'][istars] param['sed_type'] = stars['sourceID'][istars] param['model_tag'] = stars['model_tag'][istars] param['teff'] = stars['teff'][istars] param['logg'] = stars['grav'][istars] param['feh'] = stars['feh'][istars] param['z'] = 0.0 param['star'] = 1 # Star obj = Star(param, logger=self.logger) self.objs.append(obj) def _load(self, **kwargs): self.nav = 15005 self.avGal = extAv(self.nav, seed=self.seed_Av) self.objs = [] self.ids = 0 if "star_cat" in self.config["input_path"] and self.config["input_path"]["star_cat"] and not self.config["run_option"]["galaxy_only"]: star_cat = h5.File(self.star_path, 'r')['catalog'] for pix in self.pix_list: stars = star_cat[str(pix)] self._load_stars(stars, pix_id=pix) del stars if "galaxy_cat" in self.config["input_path"] and self.config["input_path"]["galaxy_cat"] and not self.config["run_option"]["star_only"]: gals_cat = h5.File(self.galaxy_path, 'r')['galaxies'] for pix in self.pix_list: gals = gals_cat[str(pix)] self._load_gals(gals, pix_id=pix) del gals if self.logger is not None: self.logger.info("number of objects in catalog: %d"%(len(self.objs))) else: print("number of objects in catalog: ", len(self.objs)) del self.avGal def load_sed(self, obj, **kwargs): if obj.type == 'star': _, wave, flux = tag_sed( h5file=self.tempSED_star, model_tag=obj.param['model_tag'], teff=obj.param['teff'], logg=obj.param['logg'], feh=obj.param['feh'] ) elif obj.type == 'galaxy' or obj.type == 'quasar': sed_data = getObservedSED( sedCat=self.tempSed_gal[obj.sed_type], redshift=obj.z, av=obj.param["av"], redden=obj.param["redden"] ) wave, flux = sed_data[0], sed_data[1] else: raise ValueError("Object type not known") speci = interpolate.interp1d(wave, flux) # lamb = np.arange(2500, 10001 + 0.5, 0.5) lamb = np.arange(2400, 11001 + 0.5, 0.5) y = speci(lamb) # erg/s/cm2/A --> photo/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')) del wave del flux return sed ObservationSim/Config/ChipOutput.py +17 −3 Original line number Diff line number Diff line import os import logging class ChipOutput(object): def __init__(self, config, focal_plane, chip, filt, imgKey0="", imgKey1="", imgKey2="", exptime=150., mjdTime="", ra_cen=None, dec_cen=None, pointing_type='MS', pointing_ID='0', subdir="./", prefix=""): Loading @@ -20,9 +21,22 @@ class ChipOutput(object): self.chipLabel = focal_plane.getChipLabel(chip.chipID) self.img_name = prefix + exp_name%(self.chipLabel, filt.filter_type) self.cat_name = 'MSC_' + config["obs_setting"]["date_obs"] + config["obs_setting"]["time_obs"] + "_" + str(pointing_ID).rjust(7, '0') + "_" + self.chipLabel.rjust(2,'0') + ".cat" # self.cat_name = 'MSC_' + config["obs_setting"]["date_obs"] + config["obs_setting"]["time_obs"] + "_" + str(pointing_ID).rjust(7, '0') + "_" + self.chipLabel.rjust(2,'0') + ".cat" self.cat_name = "MSC_%s_chip_%s_filt_%s"%(str(pointing_ID).rjust(7, '0'), focal_plane.getChipLabel(chip.chipID), filt.filter_type) + ".cat" self.subdir = subdir # Setup logger for each chip logger_filename = "MSC_%s_chip_%s_filt_%s"%(str(pointing_ID).rjust(7, '0'), focal_plane.getChipLabel(chip.chipID), filt.filter_type) + ".log" self.logger = logging.getLogger() fh = logging.FileHandler(os.path.join(self.subdir, logger_filename), mode='w+', encoding='utf-8') fh.setLevel(logging.DEBUG) self.logger.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setFormatter(formatter) self.logger.addHandler(fh) hdr1 = "obj_ID ID_chip filter xImage yImage ra dec ra_orig dec_orig z mag obj_type " hdr2 = "thetaR bfrac hlr_disk hlr_bulge e1_disk e2_disk e1_bulge e2_bulge g1 g2 " hdr3 = "sed_type av redden " Loading @@ -36,10 +50,10 @@ class ChipOutput(object): self.hdr = hdr1 + hdr2 + hdr3 + hdr4 self.fmt = fmt1 + fmt2 + fmt3 + fmt4 print("pointing_type = %s\n"%(pointing_type)) self.logger.info("pointing_type = %s\n"%(pointing_type)) if pointing_type == 'MS': self.cat = open(os.path.join(self.subdir, self.cat_name), "w") print("Creating catalog file %s ...\n"%(os.path.join(self.subdir, self.cat_name))) self.logger.info("Creating catalog file %s ...\n"%(os.path.join(self.subdir, self.cat_name))) self.cat.write(self.hdr) # def updateHDR(self, hdr): Loading ObservationSim/Instrument/Chip/Chip.py +100 −34 File changed.Preview size limit exceeded, changes collapsed. Show changes ObservationSim/Instrument/Chip/Effects.py +32 −14 Original line number Diff line number Diff line Loading @@ -69,7 +69,7 @@ def DefectivePixels(GSImage, IfHotPix=True, IfDeadPix=True, fraction=1E-4, seed= return GSImage def BadColumns(GSImage, seed=20240309, chipid=1): def BadColumns(GSImage, seed=20240309, chipid=1, logger=None): # Set bad column values ysize,xsize = GSImage.array.shape subarr = GSImage.array[int(ysize*0.1):int(ysize*0.12), int(xsize*0.1):int(xsize*0.12)] Loading @@ -85,6 +85,9 @@ def BadColumns(GSImage, seed=20240309, chipid=1): nbadsecA,nbadsecD = rgn.integers(low=1, high=5, size=2) collen = rgcollen.integers(low=int(ysize*0.1), high=int(ysize*0.7), size=(nbadsecA+nbadsecD)) xposit = rgxpos.integers(low=int(xsize*0.05), high=int(xsize*0.95), size=(nbadsecA+nbadsecD)) if logger is not None: logger.info(xposit+1) else: print(xposit+1) # signs = 2*rgdn.integers(0,2,size=(nbadsecA+nbadsecD))-1 # if meanimg>0: Loading @@ -98,7 +101,7 @@ def BadColumns(GSImage, seed=20240309, chipid=1): return GSImage def AddBiasNonUniform16(GSImage, bias_level = 500, nsecy = 2, nsecx=8, seed=202102): def AddBiasNonUniform16(GSImage, bias_level = 500, nsecy = 2, nsecx=8, seed=202102, logger=None): # Generate Bias and its non-uniformity, and add the 16 bias values to the GS-Image rg = Generator(PCG64(int(seed))) Random16 = (rg.random(nsecy*nsecx)-0.5)*20 Loading @@ -106,6 +109,10 @@ def AddBiasNonUniform16(GSImage, bias_level = 500, nsecy = 2, nsecx=8, seed=2021 BiasLevel = np.zeros((nsecy,nsecx)) elif bias_level>0: BiasLevel = Random16.reshape((nsecy,nsecx)) + bias_level if logger is not None: msg = str(" Biases of 16 channels: " + str(BiasLevel)) logger.info(msg) else: print(" Biases of 16 channels:\n",BiasLevel) arrshape = GSImage.array.shape secsize_x = int(arrshape[1]/nsecx) Loading @@ -116,14 +123,15 @@ def AddBiasNonUniform16(GSImage, bias_level = 500, nsecy = 2, nsecx=8, seed=2021 return GSImage def MakeBiasNcomb(npix_x, npix_y, bias_level=500, ncombine=1, read_noise=5, gain=1, seed=202102): def MakeBiasNcomb(npix_x, npix_y, bias_level=500, ncombine=1, read_noise=5, gain=1, seed=202102, logger=None): # Start with 0 value bias GS-Image ncombine=int(ncombine) BiasSngImg0 = galsim.Image(npix_x, npix_y, init_value=0) BiasSngImg = AddBiasNonUniform16(BiasSngImg0, bias_level=bias_level, nsecy = 2, nsecx=8, seed=int(seed)) seed=int(seed), logger=logger) BiasCombImg = BiasSngImg*ncombine rng = galsim.UniformDeviate() NoiseBias = galsim.GaussianNoise(rng=rng, sigma=read_noise*ncombine**0.5) Loading @@ -139,11 +147,15 @@ def MakeBiasNcomb(npix_x, npix_y, bias_level=500, ncombine=1, read_noise=5, gain return BiasCombImg, BiasTag def ApplyGainNonUniform16(GSImage, gain=1, nsecy = 2, nsecx=8, seed=202102): def ApplyGainNonUniform16(GSImage, gain=1, nsecy = 2, nsecx=8, seed=202102, logger=None): # Generate Gain non-uniformity, and multipy the different factors (mean~1 with sigma~1%) to the GS-Image rg = Generator(PCG64(int(seed))) Random16 = (rg.random(nsecy*nsecx)-0.5)*0.04+1 # sigma~1% Gain16 = Random16.reshape((nsecy,nsecx))/gain if logger is not None: msg = str("Gain of 16 channels: " + str(Gain16)) logger.info(msg) else: print("Gain of 16 channels: ",Gain16) arrshape = GSImage.array.shape secsize_x = int(arrshape[1]/nsecx) Loading @@ -154,11 +166,15 @@ def ApplyGainNonUniform16(GSImage, gain=1, nsecy = 2, nsecx=8, seed=202102): return GSImage def GainsNonUniform16(GSImage, gain=1, nsecy = 2, nsecx=8, seed=202102): def GainsNonUniform16(GSImage, gain=1, nsecy = 2, nsecx=8, seed=202102, logger=None): # Generate Gain non-uniformity, and multipy the different factors (mean~1 with sigma~1%) to the GS-Image rg = Generator(PCG64(int(seed))) Random16 = (rg.random(nsecy*nsecx)-0.5)*0.04+1 # sigma~1% Gain16 = Random16.reshape((nsecy,nsecx))/gain if logger is not None: msg = str(seed-20210202, "Gains of 16 channels: " + str(Gain16)) logger.info(msg) else: print(seed-20210202, "Gains of 16 channels:\n", Gain16) # arrshape = GSImage.array.shape # secsize_x = int(arrshape[1]/nsecx) Loading Loading @@ -186,7 +202,7 @@ def MakeFlatSmooth(GSBounds, seed): return FlatImg def MakeFlatNcomb(flat_single_image, ncombine=1, read_noise=5, gain=1, overscan=500, biaslevel=500, seed_bias=20210311): def MakeFlatNcomb(flat_single_image, ncombine=1, read_noise=5, gain=1, overscan=500, biaslevel=500, seed_bias=20210311, logger=None): ncombine=int(ncombine) FlatCombImg = flat_single_image*ncombine rng = galsim.UniformDeviate() Loading @@ -200,7 +216,8 @@ def MakeFlatNcomb(flat_single_image, ncombine=1, read_noise=5, gain=1, overscan= FlatCombImg, bias_level=biaslevel, nsecy=2, nsecx=8, seed=seed_bias) seed=seed_bias, logger=logger) if ncombine == 1: FlatTag = 'Single' pass Loading @@ -212,7 +229,7 @@ def MakeFlatNcomb(flat_single_image, ncombine=1, read_noise=5, gain=1, overscan= return FlatCombImg, FlatTag def MakeDarkNcomb(npix_x, npix_y, overscan=500, bias_level=500, seed_bias=202102, darkpsec=0.02, exptime=150, ncombine=10, read_noise=5, gain=1): def MakeDarkNcomb(npix_x, npix_y, overscan=500, bias_level=500, seed_bias=202102, darkpsec=0.02, exptime=150, ncombine=10, read_noise=5, gain=1, logger=None): ncombine=int(ncombine) darkpix = darkpsec*exptime DarkSngImg = galsim.Image(npix_x, npix_y, init_value=darkpix) Loading @@ -227,7 +244,8 @@ def MakeDarkNcomb(npix_x, npix_y, overscan=500, bias_level=500, seed_bias=202102 DarkCombImg, bias_level=bias_level, nsecy = 2, nsecx=8, seed=int(seed_bias)) seed=int(seed_bias), logger=logger) if ncombine == 1: DarkTag = 'Single' pass Loading Loading
Catalog/C3Catalog.py +17 −5 Original line number Diff line number Diff line Loading @@ -28,6 +28,11 @@ class C3Catalog(CatalogBase): self.cat_dir = os.path.join(config["data_dir"], config["input_path"]["cat_dir"]) self.seed_Av = config["random_seeds"]["seed_Av"] if "logger" in kwargs: self.logger = kwargs["logger"] else: self.logger = None with pkg_resources.path('Catalog.data', 'SLOAN_SDSS.g.fits') as filter_path: self.normF_star = Table.read(str(filter_path)) with pkg_resources.path('Catalog.data', 'lsst_throuput_g.fits') as filter_path: Loading Loading @@ -63,6 +68,10 @@ class C3Catalog(CatalogBase): dec = np.deg2rad(np.array([dec_max, dec_max, dec_min, dec_min])) vertices = spherical_to_cartesian(1., dec, ra) self.pix_list = hp.query_polygon(NSIDE, np.array(vertices).T, inclusive=True) if self.logger is not None: msg = str(("HEALPix List: ", self.pix_list)) self.logger.info(msg) else: print("HEALPix List: ", self.pix_list) def load_norm_filt(self, obj): Loading Loading @@ -169,10 +178,10 @@ class C3Catalog(CatalogBase): param['id'] = gals['galaxyID'][igals] if param['star'] == 0: obj = Galaxy(param, self.rotation) obj = Galaxy(param, self.rotation, logger=self.logger) self.objs.append(obj) if param['star'] == 2: obj = Quasar(param) obj = Quasar(param, logger=self.logger) self.objs.append(obj) def _load_stars(self, stars, pix_id=None): Loading Loading @@ -230,7 +239,7 @@ class C3Catalog(CatalogBase): param['feh'] = stars['feh'][istars] param['z'] = 0.0 param['star'] = 1 # Star obj = Star(param) obj = Star(param, logger=self.logger) self.objs.append(obj) def _load(self, **kwargs): Loading @@ -250,6 +259,9 @@ class C3Catalog(CatalogBase): gals = gals_cat[str(pix)] self._load_gals(gals, pix_id=pix) del gals if self.logger is not None: self.logger.info("number of objects in catalog: %d"%(len(self.objs))) else: print("number of objects in catalog: ", len(self.objs)) del self.avGal Loading
Catalog/NGPCatalog.py 0 → 100644 +304 −0 Original line number Diff line number Diff line import os import galsim import random import numpy as np import h5py as h5 import healpy as hp import astropy.constants as cons from astropy.coordinates import spherical_to_cartesian from astropy.table import Table from scipy import interpolate from datetime import datetime from ObservationSim.MockObject import CatalogBase, Star, Galaxy, Quasar from ObservationSim.MockObject._util import seds, sed_assign, extAv, tag_sed, getObservedSED from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position try: import importlib.resources as pkg_resources except ImportError: # Try backported to PY<37 'importlib_resources' import importlib_resources as pkg_resources NSIDE = 128 class NGPCatalog(CatalogBase): def __init__(self, config, chip, pointing, **kwargs): super().__init__() self.cat_dir = os.path.join(config["data_dir"], config["input_path"]["cat_dir"]) self.seed_Av = config["random_seeds"]["seed_Av"] if "logger" in kwargs: self.logger = kwargs["logger"] else: self.logger = None with pkg_resources.path('Catalog.data', 'SLOAN_SDSS.g.fits') as filter_path: self.normF_star = Table.read(str(filter_path)) with pkg_resources.path('Catalog.data', 'lsst_throuput_g.fits') as filter_path: self.normF_galaxy = Table.read(str(filter_path)) self.config = config self.chip = chip self.pointing = pointing if "star_cat" in config["input_path"] and config["input_path"]["star_cat"] and not config["run_option"]["galaxy_only"]: star_file = config["input_path"]["star_cat"] star_SED_file = config["SED_templates_path"]["star_SED"] self.star_path = os.path.join(self.cat_dir, star_file) self.star_SED_path = os.path.join(config["data_dir"], star_SED_file) self._load_SED_lib_star() if "galaxy_cat" in config["input_path"] and config["input_path"]["galaxy_cat"] and not config["run_option"]["star_only"]: galaxy_file = config["input_path"]["galaxy_cat"] self.galaxy_path = os.path.join(self.cat_dir, galaxy_file) self.galaxy_SED_path = os.path.join(config["data_dir"], config["SED_templates_path"]["galaxy_SED"]) self._load_SED_lib_gals() if "rotateEll" in config["shear_setting"]: self.rotation = float(int(config["shear_setting"]["rotateEll"]/45.)) else: self.rotation = 0. self._get_healpix_list() self._load() def _get_healpix_list(self): self.sky_coverage = self.chip.getSkyCoverageEnlarged(self.chip.img.wcs, margin=0.2) ra_min, ra_max, dec_min, dec_max = self.sky_coverage.xmin, self.sky_coverage.xmax, self.sky_coverage.ymin, self.sky_coverage.ymax ra = np.deg2rad(np.array([ra_min, ra_max, ra_max, ra_min])) dec = np.deg2rad(np.array([dec_max, dec_max, dec_min, dec_min])) vertices = spherical_to_cartesian(1., dec, ra) self.pix_list = hp.query_polygon(NSIDE, np.array(vertices).T, inclusive=True) if self.logger is not None: msg = str(("HEALPix List: ", self.pix_list)) self.logger.info(msg) else: print("HEALPix List: ", self.pix_list) def load_norm_filt(self, obj): if obj.type == "star": return self.normF_star elif obj.type == "galaxy" or obj.type == "quasar": return self.normF_galaxy else: return None def _load_SED_lib_star(self): self.tempSED_star = h5.File(self.star_SED_path,'r') def _load_SED_lib_gals(self): self.tempSed_gal, self.tempRed_gal = seds("galaxy.list", seddir=self.galaxy_SED_path) def _load_gals(self, gals, pix_id=None): ngals = len(gals['galaxyID']) self.rng_sedGal = random.Random() self.rng_sedGal.seed(pix_id) # Use healpix index as the random seed self.ud = galsim.UniformDeviate(pix_id) # Apply astrometric modeling # in C3 case only aberration ra_arr = gals['ra_true'][:] dec_arr = gals['dec_true'][:] if self.config["obs_setting"]["enable_astrometric_model"]: ra_list = ra_arr.tolist() dec_list = dec_arr.tolist() pmra_list = np.zeros(ngals).tolist() pmdec_list = np.zeros(ngals).tolist() rv_list = np.zeros(ngals).tolist() parallax_list = [1e-9] * ngals dt = datetime.fromtimestamp(self.pointing.timestamp) date_str = dt.date().isoformat() time_str = dt.time().isoformat() ra_arr, dec_arr = on_orbit_obs_position( input_ra_list=ra_list, input_dec_list=dec_list, input_pmra_list=pmra_list, input_pmdec_list=pmdec_list, input_rv_list=rv_list, input_parallax_list=parallax_list, input_nstars=ngals, input_x=self.pointing.sat_x, input_y=self.pointing.sat_y, input_z=self.pointing.sat_z, input_vx=self.pointing.sat_vx, input_vy=self.pointing.sat_vy, input_vz=self.pointing.sat_vz, input_epoch="J2015.5", input_date_str=date_str, input_time_str=time_str ) for igals in range(ngals): param = self.initialize_param() param['ra'] = ra_arr[igals] param['dec'] = dec_arr[igals] param['ra_orig'] = gals['ra_true'][igals] param['dec_orig'] = gals['dec_true'][igals] if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): continue param['mag_use_normal'] = gals['mag_true_g_lsst'][igals] if param['mag_use_normal'] >= 26.5: continue param['z'] = gals['redshift_true'][igals] param['model_tag'] = 'None' param['gamma1'] = 0 param['gamma2'] = 0 param['kappa'] = 0 param['delta_ra'] = 0 param['delta_dec'] = 0 # sersicB = gals['sersic_bulge'][igals] hlrMajB = gals['size_bulge_true'][igals] hlrMinB = gals['size_minor_bulge_true'][igals] # sersicD = gals['sersic_disk'][igals] hlrMajD = gals['size_disk_true'][igals] hlrMinD = gals['size_minor_disk_true'][igals] aGal = gals['size_true'][igals] bGal = gals['size_minor_true'][igals] param['bfrac'] = gals['bulge_to_total_ratio_i'][igals] param['theta'] = gals['position_angle_true'][igals] param['hlr_bulge'] = np.sqrt(hlrMajB * hlrMinB) param['hlr_disk'] = np.sqrt(hlrMajD * hlrMinD) param['ell_bulge'] = (hlrMajB - hlrMinB)/(hlrMajB + hlrMinB) param['ell_disk'] = (hlrMajD - hlrMinD)/(hlrMajD + hlrMinD) param['ell_tot'] = (aGal - bGal) / (aGal + bGal) # Assign each galaxy a template SED param['sed_type'] = sed_assign(phz=param['z'], btt=param['bfrac'], rng=self.rng_sedGal) param['redden'] = self.tempRed_gal[param['sed_type']] param['av'] = self.avGal[int(self.ud()*self.nav)] if param['sed_type'] <= 5: param['av'] = 0.0 param['redden'] = 0 param['star'] = 0 # Galaxy if param['sed_type'] >= 29: param['av'] = 0.6 * param['av'] / 3.0 # for quasar, av=[0, 0.2], 3.0=av.max-av.im param['star'] = 2 # Quasar self.ids += 1 # param['id'] = self.ids param['id'] = gals['galaxyID'][igals] if param['star'] == 0: obj = Galaxy(param, self.rotation, logger=self.logger) self.objs.append(obj) if param['star'] == 2: obj = Quasar(param, logger=self.logger) self.objs.append(obj) def _load_stars(self, stars, pix_id=None): nstars = len(stars['sourceID']) # Apply astrometric modeling ra_arr = stars["RA"][:] dec_arr = stars["Dec"][:] pmra_arr = stars['pmra'][:] pmdec_arr = stars['pmdec'][:] rv_arr = stars['RV'][:] parallax_arr = stars['parallax'][:] if self.config["obs_setting"]["enable_astrometric_model"]: ra_list = ra_arr.tolist() dec_list = dec_arr.tolist() pmra_list = pmra_arr.tolist() pmdec_list = pmdec_arr.tolist() rv_list = rv_arr.tolist() parallax_list = parallax_arr.tolist() dt = datetime.fromtimestamp(self.pointing.timestamp) date_str = dt.date().isoformat() time_str = dt.time().isoformat() ra_arr, dec_arr = on_orbit_obs_position( input_ra_list=ra_list, input_dec_list=dec_list, input_pmra_list=pmra_list, input_pmdec_list=pmdec_list, input_rv_list=rv_list, input_parallax_list=parallax_list, input_nstars=nstars, input_x=self.pointing.sat_x, input_y=self.pointing.sat_y, input_z=self.pointing.sat_z, input_vx=self.pointing.sat_vx, input_vy=self.pointing.sat_vy, input_vz=self.pointing.sat_vz, input_epoch="J2015.5", input_date_str=date_str, input_time_str=time_str ) for istars in range(nstars): param = self.initialize_param() param['ra'] = ra_arr[istars] param['dec'] = dec_arr[istars] param['ra_orig'] = stars["RA"][istars] param['dec_orig'] = stars["Dec"][istars] param['pmra'] = pmra_arr[istars] param['pmdec'] = pmdec_arr[istars] param['rv'] = rv_arr[istars] param['parallax'] = parallax_arr[istars] if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): continue param['mag_use_normal'] = stars['app_sdss_g'][istars] if param['mag_use_normal'] >= 26.5: continue self.ids += 1 # param['id'] = self.ids param['id'] = stars['sourceID'][istars] param['sed_type'] = stars['sourceID'][istars] param['model_tag'] = stars['model_tag'][istars] param['teff'] = stars['teff'][istars] param['logg'] = stars['grav'][istars] param['feh'] = stars['feh'][istars] param['z'] = 0.0 param['star'] = 1 # Star obj = Star(param, logger=self.logger) self.objs.append(obj) def _load(self, **kwargs): self.nav = 15005 self.avGal = extAv(self.nav, seed=self.seed_Av) self.objs = [] self.ids = 0 if "star_cat" in self.config["input_path"] and self.config["input_path"]["star_cat"] and not self.config["run_option"]["galaxy_only"]: star_cat = h5.File(self.star_path, 'r')['catalog'] for pix in self.pix_list: stars = star_cat[str(pix)] self._load_stars(stars, pix_id=pix) del stars if "galaxy_cat" in self.config["input_path"] and self.config["input_path"]["galaxy_cat"] and not self.config["run_option"]["star_only"]: gals_cat = h5.File(self.galaxy_path, 'r')['galaxies'] for pix in self.pix_list: gals = gals_cat[str(pix)] self._load_gals(gals, pix_id=pix) del gals if self.logger is not None: self.logger.info("number of objects in catalog: %d"%(len(self.objs))) else: print("number of objects in catalog: ", len(self.objs)) del self.avGal def load_sed(self, obj, **kwargs): if obj.type == 'star': _, wave, flux = tag_sed( h5file=self.tempSED_star, model_tag=obj.param['model_tag'], teff=obj.param['teff'], logg=obj.param['logg'], feh=obj.param['feh'] ) elif obj.type == 'galaxy' or obj.type == 'quasar': sed_data = getObservedSED( sedCat=self.tempSed_gal[obj.sed_type], redshift=obj.z, av=obj.param["av"], redden=obj.param["redden"] ) wave, flux = sed_data[0], sed_data[1] else: raise ValueError("Object type not known") speci = interpolate.interp1d(wave, flux) # lamb = np.arange(2500, 10001 + 0.5, 0.5) lamb = np.arange(2400, 11001 + 0.5, 0.5) y = speci(lamb) # erg/s/cm2/A --> photo/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')) del wave del flux return sed
ObservationSim/Config/ChipOutput.py +17 −3 Original line number Diff line number Diff line import os import logging class ChipOutput(object): def __init__(self, config, focal_plane, chip, filt, imgKey0="", imgKey1="", imgKey2="", exptime=150., mjdTime="", ra_cen=None, dec_cen=None, pointing_type='MS', pointing_ID='0', subdir="./", prefix=""): Loading @@ -20,9 +21,22 @@ class ChipOutput(object): self.chipLabel = focal_plane.getChipLabel(chip.chipID) self.img_name = prefix + exp_name%(self.chipLabel, filt.filter_type) self.cat_name = 'MSC_' + config["obs_setting"]["date_obs"] + config["obs_setting"]["time_obs"] + "_" + str(pointing_ID).rjust(7, '0') + "_" + self.chipLabel.rjust(2,'0') + ".cat" # self.cat_name = 'MSC_' + config["obs_setting"]["date_obs"] + config["obs_setting"]["time_obs"] + "_" + str(pointing_ID).rjust(7, '0') + "_" + self.chipLabel.rjust(2,'0') + ".cat" self.cat_name = "MSC_%s_chip_%s_filt_%s"%(str(pointing_ID).rjust(7, '0'), focal_plane.getChipLabel(chip.chipID), filt.filter_type) + ".cat" self.subdir = subdir # Setup logger for each chip logger_filename = "MSC_%s_chip_%s_filt_%s"%(str(pointing_ID).rjust(7, '0'), focal_plane.getChipLabel(chip.chipID), filt.filter_type) + ".log" self.logger = logging.getLogger() fh = logging.FileHandler(os.path.join(self.subdir, logger_filename), mode='w+', encoding='utf-8') fh.setLevel(logging.DEBUG) self.logger.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setFormatter(formatter) self.logger.addHandler(fh) hdr1 = "obj_ID ID_chip filter xImage yImage ra dec ra_orig dec_orig z mag obj_type " hdr2 = "thetaR bfrac hlr_disk hlr_bulge e1_disk e2_disk e1_bulge e2_bulge g1 g2 " hdr3 = "sed_type av redden " Loading @@ -36,10 +50,10 @@ class ChipOutput(object): self.hdr = hdr1 + hdr2 + hdr3 + hdr4 self.fmt = fmt1 + fmt2 + fmt3 + fmt4 print("pointing_type = %s\n"%(pointing_type)) self.logger.info("pointing_type = %s\n"%(pointing_type)) if pointing_type == 'MS': self.cat = open(os.path.join(self.subdir, self.cat_name), "w") print("Creating catalog file %s ...\n"%(os.path.join(self.subdir, self.cat_name))) self.logger.info("Creating catalog file %s ...\n"%(os.path.join(self.subdir, self.cat_name))) self.cat.write(self.hdr) # def updateHDR(self, hdr): Loading
ObservationSim/Instrument/Chip/Chip.py +100 −34 File changed.Preview size limit exceeded, changes collapsed. Show changes
ObservationSim/Instrument/Chip/Effects.py +32 −14 Original line number Diff line number Diff line Loading @@ -69,7 +69,7 @@ def DefectivePixels(GSImage, IfHotPix=True, IfDeadPix=True, fraction=1E-4, seed= return GSImage def BadColumns(GSImage, seed=20240309, chipid=1): def BadColumns(GSImage, seed=20240309, chipid=1, logger=None): # Set bad column values ysize,xsize = GSImage.array.shape subarr = GSImage.array[int(ysize*0.1):int(ysize*0.12), int(xsize*0.1):int(xsize*0.12)] Loading @@ -85,6 +85,9 @@ def BadColumns(GSImage, seed=20240309, chipid=1): nbadsecA,nbadsecD = rgn.integers(low=1, high=5, size=2) collen = rgcollen.integers(low=int(ysize*0.1), high=int(ysize*0.7), size=(nbadsecA+nbadsecD)) xposit = rgxpos.integers(low=int(xsize*0.05), high=int(xsize*0.95), size=(nbadsecA+nbadsecD)) if logger is not None: logger.info(xposit+1) else: print(xposit+1) # signs = 2*rgdn.integers(0,2,size=(nbadsecA+nbadsecD))-1 # if meanimg>0: Loading @@ -98,7 +101,7 @@ def BadColumns(GSImage, seed=20240309, chipid=1): return GSImage def AddBiasNonUniform16(GSImage, bias_level = 500, nsecy = 2, nsecx=8, seed=202102): def AddBiasNonUniform16(GSImage, bias_level = 500, nsecy = 2, nsecx=8, seed=202102, logger=None): # Generate Bias and its non-uniformity, and add the 16 bias values to the GS-Image rg = Generator(PCG64(int(seed))) Random16 = (rg.random(nsecy*nsecx)-0.5)*20 Loading @@ -106,6 +109,10 @@ def AddBiasNonUniform16(GSImage, bias_level = 500, nsecy = 2, nsecx=8, seed=2021 BiasLevel = np.zeros((nsecy,nsecx)) elif bias_level>0: BiasLevel = Random16.reshape((nsecy,nsecx)) + bias_level if logger is not None: msg = str(" Biases of 16 channels: " + str(BiasLevel)) logger.info(msg) else: print(" Biases of 16 channels:\n",BiasLevel) arrshape = GSImage.array.shape secsize_x = int(arrshape[1]/nsecx) Loading @@ -116,14 +123,15 @@ def AddBiasNonUniform16(GSImage, bias_level = 500, nsecy = 2, nsecx=8, seed=2021 return GSImage def MakeBiasNcomb(npix_x, npix_y, bias_level=500, ncombine=1, read_noise=5, gain=1, seed=202102): def MakeBiasNcomb(npix_x, npix_y, bias_level=500, ncombine=1, read_noise=5, gain=1, seed=202102, logger=None): # Start with 0 value bias GS-Image ncombine=int(ncombine) BiasSngImg0 = galsim.Image(npix_x, npix_y, init_value=0) BiasSngImg = AddBiasNonUniform16(BiasSngImg0, bias_level=bias_level, nsecy = 2, nsecx=8, seed=int(seed)) seed=int(seed), logger=logger) BiasCombImg = BiasSngImg*ncombine rng = galsim.UniformDeviate() NoiseBias = galsim.GaussianNoise(rng=rng, sigma=read_noise*ncombine**0.5) Loading @@ -139,11 +147,15 @@ def MakeBiasNcomb(npix_x, npix_y, bias_level=500, ncombine=1, read_noise=5, gain return BiasCombImg, BiasTag def ApplyGainNonUniform16(GSImage, gain=1, nsecy = 2, nsecx=8, seed=202102): def ApplyGainNonUniform16(GSImage, gain=1, nsecy = 2, nsecx=8, seed=202102, logger=None): # Generate Gain non-uniformity, and multipy the different factors (mean~1 with sigma~1%) to the GS-Image rg = Generator(PCG64(int(seed))) Random16 = (rg.random(nsecy*nsecx)-0.5)*0.04+1 # sigma~1% Gain16 = Random16.reshape((nsecy,nsecx))/gain if logger is not None: msg = str("Gain of 16 channels: " + str(Gain16)) logger.info(msg) else: print("Gain of 16 channels: ",Gain16) arrshape = GSImage.array.shape secsize_x = int(arrshape[1]/nsecx) Loading @@ -154,11 +166,15 @@ def ApplyGainNonUniform16(GSImage, gain=1, nsecy = 2, nsecx=8, seed=202102): return GSImage def GainsNonUniform16(GSImage, gain=1, nsecy = 2, nsecx=8, seed=202102): def GainsNonUniform16(GSImage, gain=1, nsecy = 2, nsecx=8, seed=202102, logger=None): # Generate Gain non-uniformity, and multipy the different factors (mean~1 with sigma~1%) to the GS-Image rg = Generator(PCG64(int(seed))) Random16 = (rg.random(nsecy*nsecx)-0.5)*0.04+1 # sigma~1% Gain16 = Random16.reshape((nsecy,nsecx))/gain if logger is not None: msg = str(seed-20210202, "Gains of 16 channels: " + str(Gain16)) logger.info(msg) else: print(seed-20210202, "Gains of 16 channels:\n", Gain16) # arrshape = GSImage.array.shape # secsize_x = int(arrshape[1]/nsecx) Loading Loading @@ -186,7 +202,7 @@ def MakeFlatSmooth(GSBounds, seed): return FlatImg def MakeFlatNcomb(flat_single_image, ncombine=1, read_noise=5, gain=1, overscan=500, biaslevel=500, seed_bias=20210311): def MakeFlatNcomb(flat_single_image, ncombine=1, read_noise=5, gain=1, overscan=500, biaslevel=500, seed_bias=20210311, logger=None): ncombine=int(ncombine) FlatCombImg = flat_single_image*ncombine rng = galsim.UniformDeviate() Loading @@ -200,7 +216,8 @@ def MakeFlatNcomb(flat_single_image, ncombine=1, read_noise=5, gain=1, overscan= FlatCombImg, bias_level=biaslevel, nsecy=2, nsecx=8, seed=seed_bias) seed=seed_bias, logger=logger) if ncombine == 1: FlatTag = 'Single' pass Loading @@ -212,7 +229,7 @@ def MakeFlatNcomb(flat_single_image, ncombine=1, read_noise=5, gain=1, overscan= return FlatCombImg, FlatTag def MakeDarkNcomb(npix_x, npix_y, overscan=500, bias_level=500, seed_bias=202102, darkpsec=0.02, exptime=150, ncombine=10, read_noise=5, gain=1): def MakeDarkNcomb(npix_x, npix_y, overscan=500, bias_level=500, seed_bias=202102, darkpsec=0.02, exptime=150, ncombine=10, read_noise=5, gain=1, logger=None): ncombine=int(ncombine) darkpix = darkpsec*exptime DarkSngImg = galsim.Image(npix_x, npix_y, init_value=darkpix) Loading @@ -227,7 +244,8 @@ def MakeDarkNcomb(npix_x, npix_y, overscan=500, bias_level=500, seed_bias=202102 DarkCombImg, bias_level=bias_level, nsecy = 2, nsecx=8, seed=int(seed_bias)) seed=int(seed_bias), logger=logger) if ncombine == 1: DarkTag = 'Single' pass Loading