diff --git a/Catalog/C6_50sqdeg.py b/Catalog/C6_50sqdeg.py deleted file mode 100644 index 4ce9f3ce95089cd7377957d856bcc6efa5fa73c9..0000000000000000000000000000000000000000 --- a/Catalog/C6_50sqdeg.py +++ /dev/null @@ -1,476 +0,0 @@ -import os -import galsim -import random -import copy -import numpy as np -import h5py as h5 -import healpy as hp -import astropy.constants as cons -import traceback -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 tag_sed, getObservedSED, getABMAG, integrate_sed_bandpass, comoving_dist -from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position - -# (TEST) -from astropy.cosmology import FlatLambdaCDM -from astropy import constants -from astropy import units as U -from astropy.coordinates import SkyCoord -from astropy.io import fits - -try: - import importlib.resources as pkg_resources -except ImportError: - # Try backported to PY<37 'importlib_resources' - import importlib_resources as pkg_resources - -NSIDE = 128 - -bundle_file_list = ['galaxies_C6_bundle000199.h5','galaxies_C6_bundle000200.h5','galaxies_C6_bundle000241.h5','galaxies_C6_bundle000242.h5','galaxies_C6_bundle000287.h5','galaxies_C6_bundle000288.h5','galaxies_C6_bundle000714.h5','galaxies_C6_bundle000715.h5','galaxies_C6_bundle000778.h5','galaxies_C6_bundle000779.h5','galaxies_C6_bundle000842.h5','galaxies_C6_bundle000843.h5','galaxies_C6_bundle002046.h5','galaxies_C6_bundle002110.h5','galaxies_C6_bundle002111.h5','galaxies_C6_bundle002173.h5','galaxies_C6_bundle002174.h5','galaxies_C6_bundle002238.h5','galaxies_C6_bundle002596.h5','galaxies_C6_bundle002597.h5','galaxies_C6_bundle002656.h5','galaxies_C6_bundle002657.h5','galaxies_C6_bundle002711.h5','galaxies_C6_bundle002712.h5','galaxies_C6_bundle002844.h5','galaxies_C6_bundle002845.h5','galaxies_C6_bundle002884.h5','galaxies_C6_bundle002885.h5','galaxies_C6_bundle002921.h5','galaxies_C6_bundle002922.h5'] - -qsosed_file_list = ['quickspeclib_interp1d_run1.fits','quickspeclib_interp1d_run2.fits','quickspeclib_interp1d_run3.fits','quickspeclib_interp1d_run4.fits','quickspeclib_interp1d_run5.fits','quickspeclib_interp1d_run6.fits','quickspeclib_interp1d_run7.fits','quickspeclib_interp1d_run8.fits','quickspeclib_interp1d_run9.fits','quickspeclib_interp1d_run10.fits','quickspeclib_interp1d_run11.fits','quickspeclib_interp1d_run12.fits','quickspeclib_interp1d_run13.fits','quickspeclib_interp1d_run14.fits','quickspeclib_interp1d_run15.fits','quickspeclib_interp1d_run16.fits','quickspeclib_interp1d_run17.fits','quickspeclib_interp1d_run18.fits','quickspeclib_interp1d_run19.fits','quickspeclib_interp1d_run20.fits','quickspeclib_interp1d_run21.fits','quickspeclib_interp1d_run22.fits','quickspeclib_interp1d_run23.fits','quickspeclib_interp1d_run24.fits','quickspeclib_interp1d_run25.fits','quickspeclib_interp1d_run26.fits','quickspeclib_interp1d_run27.fits','quickspeclib_interp1d_run28.fits','quickspeclib_interp1d_run29.fits','quickspeclib_interp1d_run30.fits'] - -star_file_list = ['C7_Gaia_Galaxia_RA170DECm23_healpix.hdf5', 'C7_Gaia_Galaxia_RA180DECp60_healpix.hdf5', 'C7_Gaia_Galaxia_RA240DECp30_healpix.hdf5', 'C7_Gaia_Galaxia_RA300DECm60_healpix.hdf5', 'C7_Gaia_Galaxia_RA30DECm48_healpix.hdf5'] -star_center_list = [(170., -23.), (180., 60.), (240., 30.), (300., -60.), (30., -48.)] - -def get_bundleIndex(healpixID_ring, bundleOrder=4, healpixOrder=7): - assert NSIDE == 2**healpixOrder - shift = healpixOrder - bundleOrder - shift = 2*shift - - nside_bundle = 2**bundleOrder - nside_healpix= 2**healpixOrder - - healpixID_nest= hp.ring2nest(nside_healpix, healpixID_ring) - bundleID_nest = (healpixID_nest >> shift) - bundleID_ring = hp.nest2ring(nside_bundle, bundleID_nest) - - return bundleID_ring - -def get_agnsed_file(bundle_file_name): - return qsosed_file_list[bundle_file_list.index(bundle_file_name)] - -def get_star_cat(ra_pointing, dec_pointing): - pointing_c = SkyCoord(ra=ra_pointing*U.deg, dec=dec_pointing*U.deg) - max_dist = 10 - return_star_path = None - for star_file, center in zip(star_file_list, star_center_list): - center_c = SkyCoord(ra=center[0]*U.deg, dec=center[1]*U.deg) - dist = pointing_c.separation(center_c).to(U.deg).value - if dist < max_dist: - return_star_path = star_file - max_dist = dist - return return_star_path - -class Catalog(CatalogBase): - def __init__(self, config, chip, pointing, chip_output, filt, **kwargs): - super().__init__() - self.cat_dir = config["catalog_options"]["input_path"]["cat_dir"] - - self.cosmo = FlatLambdaCDM(H0=67.66, Om0=0.3111) - - self.chip_output = chip_output - self.filt = filt - self.logger = chip_output.logger - - with pkg_resources.path('Catalog.data', 'SLOAN_SDSS.g.fits') as filter_path: - self.normF_star = Table.read(str(filter_path)) - - self.config = config - self.chip = chip - self.pointing = pointing - - self.max_size = 0. - - 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(ra_pointing=self.pointing.ra, dec_pointing=self.pointing.dec) - star_path = os.path.join(config["catalog_options"]["input_path"]["star_cat"], star_file_name) - self.star_path = os.path.join(self.cat_dir, star_path) - self.star_SED_path = config["catalog_options"]["SED_templates_path"]["star_SED"] - self._load_SED_lib_star() - - if "galaxy_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["galaxy_cat"] and not config["catalog_options"]["star_only"]: - galaxy_dir = config["catalog_options"]["input_path"]["galaxy_cat"] - self.galaxy_path = os.path.join(self.cat_dir, galaxy_dir) - self.galaxy_SED_path = config["catalog_options"]["SED_templates_path"]["galaxy_SED"] - self._load_SED_lib_gals() - self.agn_seds = {} - - if "AGN_SED" in config["catalog_options"]["SED_templates_path"] and not config["catalog_options"]["star_only"]: - self.AGN_SED_path = config["catalog_options"]["SED_templates_path"]["AGN_SED"] - - if "rotateEll" in config["catalog_options"]: - self.rotation = np.radians(float(config["catalog_options"]["rotateEll"])) - else: - self.rotation = 0. - - # Update output .cat header with catalog specific output columns - self._add_output_columns_header() - - self._get_healpix_list() - self._load() - - def _add_output_columns_header(self): - self.add_hdr = " model_tag teff logg feh" - self.add_hdr += " bulgemass diskmass detA e1 e2 kappa g1 g2 size galType veldisp " - - self.add_fmt = " %10s %8.4f %8.4f %8.4f" - self.add_fmt += " %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %4d %8.4f " - self.chip_output.update_output_header(additional_column_names=self.add_hdr) - - 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])) - self.pix_list = hp.query_polygon( - NSIDE, - hp.ang2vec(np.radians(90.) - dec, ra), - 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 - return None - 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): - pcs = h5.File(os.path.join(self.galaxy_SED_path, "pcs.h5"), "r") - lamb = h5.File(os.path.join(self.galaxy_SED_path, "lamb.h5"), "r") - self.lamb_gal = lamb['lamb'][()] - self.pcs = pcs['pcs'][()] - - def _load_gals(self, gals, pix_id=None, cat_id=0, agnsed_file=""): - ngals = len(gals['ra']) - - # Apply astrometric modeling - ra_arr = gals['ra'][:] - dec_arr = gals['dec'][:] - 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.utcfromtimestamp(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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - - for igals in range(ngals): - # # (TEST) - # if igals > 100: - # break - - param = self.initialize_param() - param['ra'] = ra_arr[igals] - param['dec'] = dec_arr[igals] - param['ra_orig'] = gals['ra'][igals] - param['dec_orig'] = gals['dec'][igals] - - if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): - continue - - # param['mag_use_normal'] = gals['mag_csst_%s'%(self.filt.filter_type)][igals] - if self.filt.filter_type == 'NUV': - param['mag_use_normal'] = gals['mag_csst_nuv'][igals] - else: - param['mag_use_normal'] = gals['mag_csst_%s'%(self.filt.filter_type)][igals] - if self.filt.is_too_dim(mag=param['mag_use_normal'], margin=self.config["obs_setting"]["mag_lim_margin"]): - continue - - param['z'] = gals['redshift'][igals] - param['model_tag'] = 'None' - param['g1'] = gals['shear'][igals][0] - param['g2'] = gals['shear'][igals][1] - param['kappa'] = gals['kappa'][igals] - param['e1'] = gals['ellipticity_true'][igals][0] - param['e2'] = gals['ellipticity_true'][igals][1] - - # For shape calculation - param['e1'], param['e2'], param['ell_total'] = self.rotate_ellipticity( - e1=gals['ellipticity_true'][igals][0], - e2=gals['ellipticity_true'][igals][1], - rotation=self.rotation, - unit='radians') - # param['ell_total'] = np.sqrt(param['e1']**2 + param['e2']**2) - if param['ell_total'] > 0.9: - continue - # phi_e = cmath.phase(complex(param['e1'], param['e2'])) - # param['e1'] = param['ell_total'] * np.cos(phi_e + 2*self.rotation) - # param['e2'] = param['ell_total'] * np.sin(phi_e + 2*self.rotation) - - param['e1_disk'] = param['e1'] - param['e2_disk'] = param['e2'] - param['e1_bulge'] = param['e1'] - param['e2_bulge'] = param['e2'] - - - param['delta_ra'] = 0 - param['delta_dec'] = 0 - - # Masses - param['bulgemass'] = gals['bulgemass'][igals] - param['diskmass'] = gals['diskmass'][igals] - - param['size'] = gals['size'][igals] - if param['size'] > self.max_size: - self.max_size = param['size'] - - # Sersic index - param['disk_sersic_idx'] = 1. - param['bulge_sersic_idx'] = 4. - - # Sizes - param['bfrac'] = param['bulgemass']/(param['bulgemass'] + param['diskmass']) - if param['bfrac'] >= 0.6: - param['hlr_bulge'] = param['size'] - param['hlr_disk'] = param['size'] * (1. - param['bfrac']) - else: - param['hlr_disk'] = param['size'] - param['hlr_bulge'] = param['size'] * param['bfrac'] - - # SED coefficients - param['coeff'] = gals['coeff'][igals] - param['detA'] = gals['detA'][igals] - - # Others - param['galType'] = gals['type'][igals] - param['veldisp'] = gals['veldisp'][igals] - - # TEST no redening and no extinction - param['av'] = 0.0 - param['redden'] = 0 - - # TEMP - self.ids += 1 - param['id'] = '%06d'%(int(pix_id)) + '%06d'%(cat_id) + '%08d'%(igals) - - # Is this an Quasar? - param['qsoindex'] = gals['qsoindex'][igals] - if param['qsoindex'] == -1: - param['star'] = 0 # Galaxy - param['agnsed_file'] = "" - obj = Galaxy(param, logger=self.logger) - else: - param_qso = copy.deepcopy(param) - param_qso['star'] = 2 # Quasar - param_qso['agnsed_file'] = agnsed_file - # First add QSO model - obj = Quasar(param_qso, logger=self.logger) - # Need to deal with additional output columns - obj.additional_output_str = self.add_fmt%("n", 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., - 0, 0.) - self.objs.append(obj) - # Then add host galaxy model - param['star'] = 0 # Galaxy - param['agnsed_file'] = "" - obj = Galaxy(param, logger=self.logger) - - # Need to deal with additional output columns for (host) galaxy - obj.additional_output_str = self.add_fmt%("n", 0., 0., 0., - param['bulgemass'], param['diskmass'], param['detA'], - param['e1'], param['e2'], param['kappa'], param['g1'], param['g2'], param['size'], - param['galType'], param['veldisp']) - - 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.utcfromtimestamp(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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - for istars in range(nstars): - # (TEST) - # if istars > 100: - # break - - 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] - self.ids += 1 - 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) - - # Append additional output columns to the .cat file - obj.additional_output_str = self.add_fmt%(param["model_tag"], param['teff'], param['logg'], param['feh'], - 0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.) - - self.objs.append(obj) - - def _load(self, **kwargs): - self.objs = [] - self.ids = 0 - - if "star_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["star_cat"] and not self.config["catalog_options"]["galaxy_only"]: - star_cat = h5.File(self.star_path, 'r')['catalog'] - for pix in self.pix_list: - try: - stars = star_cat[str(pix)] - self._load_stars(stars, pix_id=pix) - del stars - except Exception as e: - self.logger.error(str(e)) - print(e) - - if "galaxy_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["galaxy_cat"] and not self.config["catalog_options"]["star_only"]: - for pix in self.pix_list: - try: - bundleID = get_bundleIndex(pix) - bundle_file = "galaxies_C6_bundle{:06}.h5".format(bundleID) - file_path = os.path.join(self.galaxy_path, bundle_file) - gals_cat = h5.File(file_path, 'r')['galaxies'] - gals = gals_cat[str(pix)] - - # Get corresponding AGN SED file - agnsed_file = get_agnsed_file(bundle_file) - agnsed_path = os.path.join(self.AGN_SED_path, agnsed_file) - self.agn_seds[agnsed_file] = fits.open(agnsed_path)[0].data - - self._load_gals(gals, pix_id=pix, cat_id=bundleID, agnsed_file=agnsed_file) - - del gals - except Exception as e: - traceback.print_exc() - self.logger.error(str(e)) - print(e) - - if self.logger is not None: - self.logger.info("maximum galaxy size: %.4f"%(self.max_size)) - self.logger.info("number of objects in catalog: %d"%(len(self.objs))) - else: - print("number of objects in catalog: ", len(self.objs)) - - 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': - factor = 10**(-.4 * self.cosmo.distmod(obj.z).value) - if obj.type == 'galaxy': - flux = np.matmul(self.pcs, obj.coeff) * factor - # if np.any(flux < 0): - # raise ValueError("Glaxy %s: negative SED fluxes"%obj.id) - flux[flux < 0] = 0. - sedcat = np.vstack((self.lamb_gal, flux)).T - sed_data = getObservedSED( - sedCat=sedcat, - redshift=obj.z, - av=obj.param["av"], - redden=obj.param["redden"] - ) - wave, flux = sed_data[0], sed_data[1] - elif obj.type == 'quasar': - flux = self.agn_seds[obj.agnsed_file][int(obj.qsoindex)] * 1e-17 - flux[flux < 0] = 0. - wave = self.lamb_gal * (1.0 + obj.z) - else: - raise ValueError("Object type not known") - speci = interpolate.interp1d(wave, flux) - lamb = np.arange(2000, 11001+0.5, 0.5) - y = speci(lamb) - # 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': - # 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'])) - del wave - del flux - return sed diff --git a/Catalog/C6_Catalog.py b/Catalog/C6_Catalog.py deleted file mode 100644 index 481494504d0964dc106c76960bd4d1deee3e6e6a..0000000000000000000000000000000000000000 --- a/Catalog/C6_Catalog.py +++ /dev/null @@ -1,514 +0,0 @@ -import os -import galsim -import random -import numpy as np -import h5py as h5 -import healpy as hp -import astropy.constants as cons -import traceback -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 tag_sed, getObservedSED, getABMAG, integrate_sed_bandpass, comoving_dist -from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position - -# (TEST) -from astropy.cosmology import FlatLambdaCDM -from astropy import constants -from astropy import units as U - -try: - import importlib.resources as pkg_resources -except ImportError: - # Try backported to PY<37 'importlib_resources' - import importlib_resources as pkg_resources - -NSIDE = 128 - -def get_bundleIndex(healpixID_ring, bundleOrder=4, healpixOrder=7): - assert NSIDE == 2**healpixOrder - shift = healpixOrder - bundleOrder - shift = 2*shift - - nside_bundle = 2**bundleOrder - nside_healpix= 2**healpixOrder - - healpixID_nest= hp.ring2nest(nside_healpix, healpixID_ring) - bundleID_nest = (healpixID_nest >> shift) - bundleID_ring = hp.nest2ring(nside_bundle, bundleID_nest) - - return bundleID_ring - -class Catalog(CatalogBase): - def __init__(self, config, chip, pointing, chip_output, filt, **kwargs): - super().__init__() - self.cat_dir = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["cat_dir"]) - self.seed_Av = config["catalog_options"]["seed_Av"] - - self.cosmo = FlatLambdaCDM(H0=67.66, Om0=0.3111) - - self.chip_output = chip_output - self.filt = filt - self.logger = chip_output.logger - - with pkg_resources.path('Catalog.data', 'SLOAN_SDSS.g.fits') as filter_path: - self.normF_star = Table.read(str(filter_path)) - - self.config = config - self.chip = chip - self.pointing = pointing - - self.max_size = 0. - - if "star_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["star_cat"] and not config["catalog_options"]["galaxy_only"]: - star_file = config["catalog_options"]["input_path"]["star_cat"] - star_SED_file = config["catalog_options"]["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["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["galaxy_cat"] and not config["catalog_options"]["star_only"]: - galaxy_dir = config["catalog_options"]["input_path"]["galaxy_cat"] - self.galaxy_path = os.path.join(self.cat_dir, galaxy_dir) - self.galaxy_SED_path = os.path.join(config["data_dir"], config["catalog_options"]["SED_templates_path"]["galaxy_SED"]) - self._load_SED_lib_gals() - - if "AGN_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["AGN_cat"] and not config["catalog_options"]["star_only"]: - AGN_dir = config["catalog_options"]["input_path"]["AGN_cat"] - self.AGN_path = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["AGN_cat"]) - self.AGN_SED_path = os.path.join(config["data_dir"], config["catalog_options"]["SED_templates_path"]["AGN_SED"]) - self.AGN_SED_wave_path = os.path.join(config['data_dir'], config["catalog_options"]["SED_templates_path"]["AGN_SED_WAVE"]) - self._load_SED_lib_AGN() - - if "rotateEll" in config["catalog_options"]: - self.rotation = np.radians(float(config["catalog_options"]["rotateEll"])) - else: - self.rotation = 0. - - # Update output .cat header with catalog specific output columns - self._add_output_columns_header() - - self._get_healpix_list() - self._load() - - def _add_output_columns_header(self): - self.add_hdr = " model_tag teff logg feh" - self.add_hdr += " bulgemass diskmass detA e1 e2 kappa g1 g2 size galType veldisp " - - self.add_fmt = " %10s %8.4f %8.4f %8.4f" - self.add_fmt += " %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %4d %8.4f " - self.chip_output.update_output_header(additional_column_names=self.add_hdr) - - 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, - hp.ang2vec(np.radians(90.) - dec, ra), - 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 - return None - 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): - pcs = h5.File(os.path.join(self.galaxy_SED_path, "pcs.h5"), "r") - lamb = h5.File(os.path.join(self.galaxy_SED_path, "lamb.h5"), "r") - self.lamb_gal = lamb['lamb'][()] - self.pcs = pcs['pcs'][()] - - def _load_SED_lib_AGN(self): - from astropy.io import fits - self.SED_AGN = fits.open(self.AGN_SED_path)[0].data - self.lamb_AGN = np.load(self.AGN_SED_wave_path) - - - def _load_gals(self, gals, pix_id=None, cat_id=0): - ngals = len(gals['ra']) - - # Apply astrometric modeling - # in C3 case only aberration - ra_arr = gals['ra'][:] - dec_arr = gals['dec'][:] - 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.utcfromtimestamp(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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - - for igals in range(ngals): - # # (TEST) - # if igals > 100: - # break - - param = self.initialize_param() - param['ra'] = ra_arr[igals] - param['dec'] = dec_arr[igals] - param['ra_orig'] = gals['ra'][igals] - param['dec_orig'] = gals['dec'][igals] - param['mag_use_normal'] = gals['mag_csst_%s'%(self.filt.filter_type)][igals] - if self.filt.is_too_dim(mag=param['mag_use_normal'], margin=self.config["obs_setting"]["mag_lim_margin"]): - continue - - param['z'] = gals['redshift'][igals] - param['model_tag'] = 'None' - param['g1'] = gals['shear'][igals][0] - param['g2'] = gals['shear'][igals][1] - param['kappa'] = gals['kappa'][igals] - param['e1'] = gals['ellipticity_true'][igals][0] - param['e2'] = gals['ellipticity_true'][igals][1] - - # For shape calculation - - param['ell_total'] = np.sqrt(param['e1']**2 + param['e2']**2) - if param['ell_total'] > 0.9: - continue - param['e1_disk'] = param['e1'] - param['e2_disk'] = param['e2'] - param['e1_bulge'] = param['e1'] - param['e2_bulge'] = param['e2'] - - - param['delta_ra'] = 0 - param['delta_dec'] = 0 - - # Masses - param['bulgemass'] = gals['bulgemass'][igals] - param['diskmass'] = gals['diskmass'][igals] - - param['size'] = gals['size'][igals] - if param['size'] > self.max_size: - self.max_size = param['size'] - - # Sersic index - param['disk_sersic_idx'] = 1. - param['bulge_sersic_idx'] = 4. - - # Sizes - param['bfrac'] = param['bulgemass']/(param['bulgemass'] + param['diskmass']) - if param['bfrac'] >= 0.6: - param['hlr_bulge'] = param['size'] - param['hlr_disk'] = param['size'] * (1. - param['bfrac']) - else: - param['hlr_disk'] = param['size'] - param['hlr_bulge'] = param['size'] * param['bfrac'] - - # SED coefficients - param['coeff'] = gals['coeff'][igals] - param['detA'] = gals['detA'][igals] - - # Others - param['galType'] = gals['type'][igals] - param['veldisp'] = gals['veldisp'][igals] - - # TEST no redening and no extinction - param['av'] = 0.0 - param['redden'] = 0 - - param['star'] = 0 # Galaxy - - # NOTE: this cut cannot be put before the SED type has been assigned - if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): - continue - - # TEMP - self.ids += 1 - # param['id'] = self.ids - param['id'] = '%06d'%(int(pix_id)) + '%06d'%(cat_id) + '%08d'%(igals) - - if param['star'] == 0: - obj = Galaxy(param, logger=self.logger) - - # Need to deal with additional output columns - obj.additional_output_str = self.add_fmt%("n", 0., 0., 0., - param['bulgemass'], param['diskmass'], param['detA'], - param['e1'], param['e2'], param['kappa'], param['g1'], param['g2'], param['size'], - param['galType'], param['veldisp']) - - 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.utcfromtimestamp(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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - for istars in range(nstars): - # # (TEST) - # if istars > 100: - # break - - 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'] = 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) - - # Append additional output columns to the .cat file - obj.additional_output_str = self.add_fmt%(param["model_tag"], param['teff'], param['logg'], param['feh'], - 0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.) - - self.objs.append(obj) - - def _load_AGNs(self): - data = Table.read(self.AGN_path) - ra_arr = data['ra'] - dec_arr = data['dec'] - nAGNs = len(data) - if self.config["obs_setting"]["enable_astrometric_model"]: - ra_list = ra_arr.tolist() - dec_list = dec_arr.tolist() - pmra_list = np.zeros(nAGNs).tolist() - pmdec_list = np.zeros(nAGNs).tolist() - rv_list = np.zeros(nAGNs).tolist() - parallax_list = [1e-9] * nAGNs - dt = datetime.utcfromtimestamp(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=nAGNs, - 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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - for iAGNs in range(nAGNs): - param = self.initialize_param() - param['ra'] = ra_arr[iAGNs] - param['dec'] = dec_arr[iAGNs] - param['ra_orig'] = data['ra'][iAGNs] - param['dec_orig'] = data['dec'][iAGNs] - param['z'] = data['z'][iAGNs] - param['appMag'] = data['appMag'][iAGNs] - param['absMag'] = data['absMag'][iAGNs] - - # NOTE: this cut cannot be put before the SED type has been assigned - if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): - continue - - # TEST no redening and no extinction - param['av'] = 0.0 - param['redden'] = 0 - - param['star'] = 2 # Quasar - param['id'] = data['igmlos'][iAGNs] - - if param['star'] == 2: - obj = Quasar(param, logger=self.logger) - - # Append additional output columns to the .cat file - obj.additional_output_str = self.add_fmt%("n", 0., 0., 0., - 0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.) - self.objs.append(obj) - - def _load(self, **kwargs): - self.objs = [] - self.ids = 0 - - if "star_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["star_cat"] and not self.config["catalog_options"]["galaxy_only"]: - star_cat = h5.File(self.star_path, 'r')['catalog'] - for pix in self.pix_list: - try: - stars = star_cat[str(pix)] - self._load_stars(stars, pix_id=pix) - del stars - except Exception as e: - self.logger.error(str(e)) - print(e) - - if "galaxy_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["galaxy_cat"] and not self.config["catalog_options"]["star_only"]: - for pix in self.pix_list: - try: - bundleID = get_bundleIndex(pix) - file_path = os.path.join(self.galaxy_path, "galaxies_C6_bundle{:06}.h5".format(bundleID)) - gals_cat = h5.File(file_path, 'r')['galaxies'] - gals = gals_cat[str(pix)] - self._load_gals(gals, pix_id=pix, cat_id=bundleID) - del gals - except Exception as e: - traceback.print_exc() - self.logger.error(str(e)) - print(e) - - if "AGN_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["AGN_cat"] and not self.config["catalog_options"]["star_only"]: - try: - self._load_AGNs() - except Exception as e: - traceback.print_exc() - self.logger.error(str(e)) - print(e) - - if self.logger is not None: - self.logger.info("maximum galaxy size: %.4f"%(self.max_size)) - self.logger.info("number of objects in catalog: %d"%(len(self.objs))) - else: - print("number of objects in catalog: ", len(self.objs)) - - 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': - factor = 10**(-.4 * self.cosmo.distmod(obj.z).value) - if obj.type == 'galaxy': - flux = np.matmul(self.pcs, obj.coeff) * factor - # if np.any(flux < 0): - # raise ValueError("Glaxy %s: negative SED fluxes"%obj.id) - flux[flux < 0] = 0. - sedcat = np.vstack((self.lamb_gal, flux)).T - sed_data = getObservedSED( - sedCat=sedcat, - redshift=obj.z, - av=obj.param["av"], - redden=obj.param["redden"] - ) - wave, flux = sed_data[0], sed_data[1] - elif obj.type == 'quasar': - flux = self.SED_AGN[int(obj.id)] * 1e-17 - # if np.any(flux < 0): - # raise ValueError("Glaxy %s: negative SED fluxes"%obj.id) - flux[flux < 0] = 0. - # sedcat = np.vstack((self.lamb_AGN, flux)).T - wave = self.lamb_AGN - # print("sed (erg/s/cm2/A) = ", sed_data) - # np.savetxt(os.path.join(self.config["work_dir"], "%s_sed.txt"%(obj.id)), sedcat) - else: - raise ValueError("Object type not known") - speci = interpolate.interp1d(wave, flux) - lamb = np.arange(2000, 11001+0.5, 0.5) - y = speci(lamb) - # 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': - # 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) - # if obj.param['mag_use_normal'] >= 30: - # print("obj ID = %d"%obj.id) - # print("mag_use_normal = %.3f"%obj.param['mag_use_normal']) - # print("integrated flux = %.7f"%(interFlux)) - # print("app mag = %.3f"%obj.param['appMag']) - # np.savetxt('./AGN_SED_test/sed_objID_%d.txt'%obj.id, np.transpose([self.lamb_AGN, self.SED_AGN[int(obj.id)]])) - # print("obj ID = %d"%obj.id) - # print("mag_use_normal = %.3f"%obj.param['mag_use_normal']) - # print("integrated flux = %.7f"%(interFlux)) - # print("app mag = %.3f"%obj.param['appMag']) - # print("abs mag = %.3f"%obj.param['absMag']) - # mag = getABMAG(interFlux, self.filt.bandpass_full) - # print("mag diff = %.3f"%(mag - obj.param['mag_use_normal'])) - del wave - del flux - return sed diff --git a/Catalog/C6_fits_Catalog.py b/Catalog/C6_fits_Catalog.py deleted file mode 100644 index d8eea0c6b53a834dddfb3ab226e1718e5940e727..0000000000000000000000000000000000000000 --- a/Catalog/C6_fits_Catalog.py +++ /dev/null @@ -1,636 +0,0 @@ -import os -import galsim -import random -import numpy as np -import h5py as h5 -import healpy as hp -import astropy.constants as cons -import traceback -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, Stamp -from ObservationSim.MockObject._util import tag_sed, getObservedSED, getABMAG, integrate_sed_bandpass, comoving_dist -from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position - -import astropy.io.fits as fitsio -from ObservationSim.MockObject._util import seds, sed_assign, extAv - -# (TEST) -from astropy.cosmology import FlatLambdaCDM -from astropy import constants -from astropy import units as U - -try: - import importlib.resources as pkg_resources -except ImportError: - # Try backported to PY<37 'importlib_resources' - import importlib_resources as pkg_resources - -NSIDE = 128 - -def get_bundleIndex(healpixID_ring, bundleOrder=4, healpixOrder=7): - assert NSIDE == 2**healpixOrder - shift = healpixOrder - bundleOrder - shift = 2*shift - - nside_bundle = 2**bundleOrder - nside_healpix= 2**healpixOrder - - healpixID_nest= hp.ring2nest(nside_healpix, healpixID_ring) - bundleID_nest = (healpixID_nest >> shift) - bundleID_ring = hp.nest2ring(nside_bundle, bundleID_nest) - - return bundleID_ring - -class Catalog(CatalogBase): - def __init__(self, config, chip, pointing, chip_output, filt, **kwargs): - super().__init__() - self.cat_dir = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["cat_dir"]) - self.seed_Av = config["catalog_options"]["seed_Av"] - - # (TEST) - self.cosmo = FlatLambdaCDM(H0=67.66, Om0=0.3111) - - self.chip_output = chip_output - self.filt = filt - self.logger = chip_output.logger - - 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 - - self.max_size = 0. - - if "star_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["star_cat"] and not config["catalog_options"]["galaxy_only"]: - star_file = config["catalog_options"]["input_path"]["star_cat"] - star_SED_file = config["catalog_options"]["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["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["galaxy_cat"] and not config["catalog_options"]["star_only"]: - galaxy_dir = config["catalog_options"]["input_path"]["galaxy_cat"] - self.galaxy_path = os.path.join(self.cat_dir, galaxy_dir) - self.galaxy_SED_path = os.path.join(config["data_dir"], config["catalog_options"]["SED_templates_path"]["galaxy_SED"]) - self._load_SED_lib_gals() - - if "AGN_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["AGN_cat"] and not config["catalog_options"]["star_only"]: - AGN_dir = config["catalog_options"]["input_path"]["AGN_cat"] - self.AGN_path = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["AGN_cat"]) - self.AGN_SED_path = os.path.join(config["data_dir"], config["catalog_options"]["SED_templates_path"]["AGN_SED"]) - self.AGN_SED_wave_path = os.path.join(config['data_dir'], config["catalog_options"]["SED_templates_path"]["AGN_SED_WAVE"]) - self._load_SED_lib_AGN() - - ###mock_stamp_START - if "stamp_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["stamp_cat"] and config["catalog_options"]["stamp_yes"]: - stamp_file = config["catalog_options"]["input_path"]["stamp_cat"] - self.stamp_path = os.path.join(self.cat_dir, stamp_file) - self.tempSed_gal, self.tempRed_gal = seds("galaxy.list", seddir="/share/simudata/CSSOSDataProductsSims/data/Templates/Galaxy/") #only for test - ###mock_stamp_END - - if "rotateEll" in config["catalog_options"]: - self.rotation = np.radians(float(config["catalog_options"]["rotateEll"])) - else: - self.rotation = 0. - - # Update output .cat header with catalog specific output columns - self._add_output_columns_header() - - self._get_healpix_list() - self._load() - - def _add_output_columns_header(self): - self.add_hdr = " model_tag teff logg feh" - self.add_hdr += " bulgemass diskmass detA e1 e2 kappa g1 g2 size galType veldisp " - - self.add_fmt = " %10s %8.4f %8.4f %8.4f" - self.add_fmt += " %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %4d %8.4f " - self.chip_output.update_output_header(additional_column_names=self.add_hdr) - - 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, - hp.ang2vec(np.radians(90.) - dec, ra), - inclusive=True - ) - # 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 - return None - ###mock_stamp_START - elif obj.type == "stamp": - return self.normF_galaxy ###normalize_filter for stamp - #return None - ###mock_stamp_END - 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): - pcs = h5.File(os.path.join(self.galaxy_SED_path, "pcs.h5"), "r") - lamb = h5.File(os.path.join(self.galaxy_SED_path, "lamb.h5"), "r") - self.lamb_gal = lamb['lamb'][()] - self.pcs = pcs['pcs'][()] - - def _load_SED_lib_AGN(self): - from astropy.io import fits - self.SED_AGN = fits.open(self.AGN_SED_path)[0].data - self.lamb_AGN = np.load(self.AGN_SED_wave_path) - - - def _load_gals(self, gals, pix_id=None, cat_id=0): - ngals = len(gals['ra']) - - # Apply astrometric modeling - # in C3 case only aberration - ra_arr = gals['ra'][:] - dec_arr = gals['dec'][:] - 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.utcfromtimestamp(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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - - for igals in range(ngals): - # # (TEST) - if igals > 2000: - break - - param = self.initialize_param() - param['ra'] = ra_arr[igals] - param['dec'] = dec_arr[igals] - param['ra_orig'] = gals['ra'][igals] - param['dec_orig'] = gals['dec'][igals] - param['mag_use_normal'] = gals['mag_csst_%s'%(self.filt.filter_type)][igals] - if self.filt.is_too_dim(mag=param['mag_use_normal'], margin=self.config["obs_setting"]["mag_lim_margin"]): - continue - - param['z'] = gals['redshift'][igals] - param['model_tag'] = 'None' - param['g1'] = gals['shear'][igals][0] - param['g2'] = gals['shear'][igals][1] - param['kappa'] = gals['kappa'][igals] - param['e1'] = gals['ellipticity_true'][igals][0] - param['e2'] = gals['ellipticity_true'][igals][1] - - # For shape calculation - - param['ell_total'] = np.sqrt(param['e1']**2 + param['e2']**2) - if param['ell_total'] > 0.9: - continue - param['e1_disk'] = param['e1'] - param['e2_disk'] = param['e2'] - param['e1_bulge'] = param['e1'] - param['e2_bulge'] = param['e2'] - - - param['delta_ra'] = 0 - param['delta_dec'] = 0 - - # Masses - param['bulgemass'] = gals['bulgemass'][igals] - param['diskmass'] = gals['diskmass'][igals] - - param['size'] = gals['size'][igals] - if param['size'] > self.max_size: - self.max_size = param['size'] - - # Sizes - param['bfrac'] = param['bulgemass']/(param['bulgemass'] + param['diskmass']) - if param['bfrac'] >= 0.6: - param['hlr_bulge'] = param['size'] - param['hlr_disk'] = param['size'] * (1. - param['bfrac']) - else: - param['hlr_disk'] = param['size'] - param['hlr_bulge'] = param['size'] * param['bfrac'] - - # SED coefficients - param['coeff'] = gals['coeff'][igals] - param['detA'] = gals['detA'][igals] - - # Others - param['galType'] = gals['type'][igals] - param['veldisp'] = gals['veldisp'][igals] - - # TEST no redening and no extinction - param['av'] = 0.0 - param['redden'] = 0 - - param['star'] = 0 # Galaxy - - # NOTE: this cut cannot be put before the SED type has been assigned - if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): - continue - - # TEMP - self.ids += 1 - # param['id'] = self.ids - param['id'] = '%06d'%(int(pix_id)) + '%06d'%(cat_id) + '%08d'%(igals) - - if param['star'] == 0: - obj = Galaxy(param, logger=self.logger) - - # Need to deal with additional output columns - obj.additional_output_str = self.add_fmt%("n", 0., 0., 0., - param['bulgemass'], param['diskmass'], param['detA'], - param['e1'], param['e2'], param['kappa'], param['g1'], param['g2'], param['size'], - param['galType'], param['veldisp']) - - 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.utcfromtimestamp(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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - for istars in range(nstars): - # # (TEST) - if istars > 100: - break - - 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'] = 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) - - # Append additional output columns to the .cat file - obj.additional_output_str = self.add_fmt%(param["model_tag"], param['teff'], param['logg'], param['feh'], - 0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.) - - self.objs.append(obj) - - def _load_AGNs(self): - data = Table.read(self.AGN_path) - ra_arr = data['ra'] - dec_arr = data['dec'] - nAGNs = len(data) - if self.config["obs_setting"]["enable_astrometric_model"]: - ra_list = ra_arr.tolist() - dec_list = dec_arr.tolist() - pmra_list = np.zeros(nAGNs).tolist() - pmdec_list = np.zeros(nAGNs).tolist() - rv_list = np.zeros(nAGNs).tolist() - parallax_list = [1e-9] * nAGNs - dt = datetime.utcfromtimestamp(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=nAGNs, - 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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - for iAGNs in range(nAGNs): - if iAGNs > 100: - break - - param = self.initialize_param() - param['ra'] = ra_arr[iAGNs] - param['dec'] = dec_arr[iAGNs] - param['ra_orig'] = data['ra'][iAGNs] - param['dec_orig'] = data['dec'][iAGNs] - param['z'] = data['z'][iAGNs] - param['appMag'] = data['appMag'][iAGNs] - param['absMag'] = data['absMag'][iAGNs] - - # NOTE: this cut cannot be put before the SED type has been assigned - if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): - continue - - # TEST no redening and no extinction - param['av'] = 0.0 - param['redden'] = 0 - - param['star'] = 2 # Quasar - param['id'] = data['igmlos'][iAGNs] - - if param['star'] == 2: - obj = Quasar(param, logger=self.logger) - - # Append additional output columns to the .cat file - obj.additional_output_str = self.add_fmt%("n", 0., 0., 0., - 0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.) - self.objs.append(obj) - - ###mock_stamp_START - def _load_stamps(self, stamps, pix_id=None): - nstamps = len(stamps['filename']) - self.rng_sedGal = random.Random() - self.rng_sedGal.seed(pix_id) # Use healpix index as the random seed - self.ud = galsim.UniformDeviate(pix_id) - - for istamp in range(nstamps): - print('DEBUG:::istamp=', istamp) - - fitsfile = os.path.join(self.cat_dir, "stampCats/"+stamps['filename'][istamp].decode('utf-8')) - hdu=fitsio.open(fitsfile) - - param = self.initialize_param() - param['id'] = hdu[0].header['index'] #istamp - param['star'] = 3 # Stamp type in .cat file - ###param['lensGalaxyID'] = hdu[0].header['lensGID'] - param['ra'] = hdu[0].header['ra'] - param['dec']= hdu[0].header['dec'] - param['pixScale']= hdu[0].header['pixScale'] - #param['srcGalaxyID'] = hdu[0].header['srcGID'] - #param['mu']= hdu[0].header['mu'] - #param['PA']= hdu[0].header['PA'] - #param['bfrac']= hdu[0].header['bfrac'] - #param['z']= hdu[0].header['z'] - param['mag_use_normal'] = 20 #hdu[0].header['m_normal'] #gals['mag_true_g_lsst'] - - ###assert(stamps['lensGID'][istamp] == param['lensGalaxyID']) - - # Apply astrometric modeling - # in C3 case only aberration - param['ra_orig'] = param['ra'] - param['dec_orig']= param['dec'] - if self.config["obs_setting"]["enable_astrometric_model"]: - ra_list = [param['ra']] #ra_arr.tolist() - dec_list= [param['dec']] #dec_arr.tolist() - pmra_list = np.zeros(1).tolist() - pmdec_list = np.zeros(1).tolist() - rv_list = np.zeros(1).tolist() - parallax_list = [1e-9] * 1 - 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=1, - 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 - ) - param['ra'] = ra_arr[0] - param['dec']= dec_arr[0] - - # 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'] = 0.0 - param['redden'] = 0 - - #param["CSSTmag"]= True - #param["mag_r"] = 20. - #param[''] - ###more keywords for stamp### - param['image'] = hdu[0].data - param['image'] = param['image']/(np.sum(param['image'])) - obj = Stamp(param) - self.objs.append(obj) - ###mock_stamp_END - - def _load(self, **kwargs): - self.objs = [] - self.ids = 0 - - if "star_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["star_cat"] and not self.config["catalog_options"]["galaxy_only"]: - star_cat = h5.File(self.star_path, 'r')['catalog'] - for pix in self.pix_list: - try: - stars = star_cat[str(pix)] - self._load_stars(stars, pix_id=pix) - del stars - except Exception as e: - self.logger.error(str(e)) - print(e) - - if "galaxy_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["galaxy_cat"] and not self.config["catalog_options"]["star_only"]: - for pix in self.pix_list: - try: - bundleID = get_bundleIndex(pix) - file_path = os.path.join(self.galaxy_path, "galaxies_C6_bundle{:06}.h5".format(bundleID)) - gals_cat = h5.File(file_path, 'r')['galaxies'] - gals = gals_cat[str(pix)] - self._load_gals(gals, pix_id=pix, cat_id=bundleID) - del gals - except Exception as e: - traceback.print_exc() - self.logger.error(str(e)) - print(e) - - if "AGN_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["AGN_cat"] and not self.config["catalog_options"]["star_only"]: - try: - self._load_AGNs() - except Exception as e: - traceback.print_exc() - self.logger.error(str(e)) - print(e) - - ###mock_stamp_START - if "stamp_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["stamp_cat"] and self.config["catalog_options"]["stamp_yes"]: - stamps_cat = h5.File(self.stamp_path, 'r')['Stamps'] - for pix in self.pix_list: - try: - stamps = stamps_cat[str(pix)] - self._load_stamps(stamps, pix_id=pix) - del stamps - except Exception as e: - self.logger.error(str(e)) - print(e) - ###mock_stamp_END - - if self.logger is not None: - self.logger.info("maximum galaxy size: %.4f"%(self.max_size)) - self.logger.info("number of objects in catalog: %d"%(len(self.objs))) - else: - print("number of objects in catalog: ", len(self.objs)) - - 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': - factor = 10**(-.4 * self.cosmo.distmod(obj.z).value) - if obj.type == 'galaxy': - flux = np.matmul(self.pcs, obj.coeff) * factor - # if np.any(flux < 0): - # raise ValueError("Glaxy %s: negative SED fluxes"%obj.id) - flux[flux < 0] = 0. - sedcat = np.vstack((self.lamb_gal, flux)).T - sed_data = getObservedSED( - sedCat=sedcat, - redshift=obj.z, - av=obj.param["av"], - redden=obj.param["redden"] - ) - wave, flux = sed_data[0], sed_data[1] - elif obj.type == 'quasar': - flux = self.SED_AGN[int(obj.id)] * 1e-17 - # if np.any(flux < 0): - # raise ValueError("Glaxy %s: negative SED fluxes"%obj.id) - flux[flux < 0] = 0. - # sedcat = np.vstack((self.lamb_AGN, flux)).T - wave = self.lamb_AGN - # print("sed (erg/s/cm2/A) = ", sed_data) - # np.savetxt(os.path.join(self.config["work_dir"], "%s_sed.txt"%(obj.id)), sedcat) - ###mock_stamp_START - elif obj.type == 'stamp': - 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] - ###mock_stamp_END - else: - raise ValueError("Object type not known") - speci = interpolate.interp1d(wave, flux) - lamb = np.arange(2000, 11001+0.5, 0.5) - y = speci(lamb) - # 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': - # 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) - # if obj.param['mag_use_normal'] >= 30: - # print("obj ID = %d"%obj.id) - # print("mag_use_normal = %.3f"%obj.param['mag_use_normal']) - # print("integrated flux = %.7f"%(interFlux)) - # print("app mag = %.3f"%obj.param['appMag']) - # np.savetxt('./AGN_SED_test/sed_objID_%d.txt'%obj.id, np.transpose([self.lamb_AGN, self.SED_AGN[int(obj.id)]])) - # print("obj ID = %d"%obj.id) - # print("mag_use_normal = %.3f"%obj.param['mag_use_normal']) - # print("integrated flux = %.7f"%(interFlux)) - # print("app mag = %.3f"%obj.param['appMag']) - # print("abs mag = %.3f"%obj.param['absMag']) - # mag = getABMAG(interFlux, self.filt.bandpass_full) - # print("mag diff = %.3f"%(mag - obj.param['mag_use_normal'])) - del wave - del flux - return sed diff --git a/Catalog/Calib_Catalog.py b/Catalog/Calib_Catalog.py deleted file mode 100644 index 308a9d5fd08146b1e266ba41f692cb760f9395b4..0000000000000000000000000000000000000000 --- a/Catalog/Calib_Catalog.py +++ /dev/null @@ -1,673 +0,0 @@ -import os -import galsim -import random -import numpy as np -import h5py as h5 -import healpy as hp -import astropy.constants as cons -import traceback -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 tag_sed, getObservedSED, getABMAG, integrate_sed_bandpass, comoving_dist -from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position - -# (TEST) -from astropy.cosmology import FlatLambdaCDM -from astropy import constants -from astropy import units as U - -try: - import importlib.resources as pkg_resources -except ImportError: - # Try backported to PY<37 'importlib_resources' - import importlib_resources as pkg_resources - -NSIDE = 128 - -def get_bundleIndex(healpixID_ring, bundleOrder=4, healpixOrder=7): - assert NSIDE == 2**healpixOrder - shift = healpixOrder - bundleOrder - shift = 2*shift - - nside_bundle = 2**bundleOrder - nside_healpix= 2**healpixOrder - - healpixID_nest= hp.ring2nest(nside_healpix, healpixID_ring) - bundleID_nest = (healpixID_nest >> shift) - bundleID_ring = hp.nest2ring(nside_bundle, bundleID_nest) - - return bundleID_ring - -class Catalog(CatalogBase): - def __init__(self, config, chip, pointing, chip_output, filt, **kwargs): - super().__init__() - self.cat_dir = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["cat_dir"]) - self.seed_Av = config["catalog_options"]["seed_Av"] - - self.cosmo = FlatLambdaCDM(H0=67.66, Om0=0.3111) - - self.chip_output = chip_output - self.filt = filt - self.logger = chip_output.logger - - with pkg_resources.path('Catalog.data', 'SLOAN_SDSS.g.fits') as filter_path: - self.normF_star = Table.read(str(filter_path)) - - self.config = config - self.chip = chip - self.pointing = pointing - - self.max_size = 0. - - if "star_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["star_cat"] and not config["catalog_options"]["galaxy_only"]: - star_file = config["catalog_options"]["input_path"]["star_cat"] - star_SED_file = config["catalog_options"]["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["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["galaxy_cat"] and not config["catalog_options"]["star_only"]: - galaxy_dir = config["catalog_options"]["input_path"]["galaxy_cat"] - self.galaxy_path = os.path.join(self.cat_dir, galaxy_dir) - self.galaxy_SED_path = os.path.join(config["data_dir"], config["catalog_options"]["SED_templates_path"]["galaxy_SED"]) - self._load_SED_lib_gals() - - if "AGN_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["AGN_cat"] and not config["catalog_options"]["star_only"]: - AGN_dir = config["catalog_options"]["input_path"]["AGN_cat"] - self.AGN_path = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["AGN_cat"]) - self.AGN_SED_path = os.path.join(config["data_dir"], config["catalog_options"]["SED_templates_path"]["AGN_SED"]) - self.AGN_SED_wave_path = os.path.join(config['data_dir'], config["catalog_options"]["SED_templates_path"]["AGN_SED_WAVE"]) - self._load_SED_lib_AGN() - - if "CALIB_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"][ - "CALIB_cat"] and not config["catalog_options"]["star_only"]: - self.CALIB_cat_path = os.path.join(config["data_dir"], - config["catalog_options"]["input_path"]["CALIB_cat"]) - self.CALIB_SED_path = os.path.join(config["data_dir"], - config["catalog_options"]["SED_templates_path"]["CALIB_SED"]) - - if "rotateEll" in config["catalog_options"]: - self.rotation = np.radians(float(config["catalog_options"]["rotateEll"])) - else: - self.rotation = 0. - - # Update output .cat header with catalog specific output columns - self._add_output_columns_header() - - self._get_healpix_list() - self._load() - - def _add_output_columns_header(self): - self.add_hdr = " model_tag teff logg feh" - self.add_hdr += " bulgemass diskmass detA e1 e2 kappa g1 g2 size galType veldisp " - - self.add_fmt = " %10s %8.4f %8.4f %8.4f" - self.add_fmt += " %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %4d %8.4f " - self.chip_output.update_output_header(additional_column_names=self.add_hdr) - - 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, - hp.ang2vec(np.radians(90.) - dec, ra), - 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 - return None - 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): - pcs = h5.File(os.path.join(self.galaxy_SED_path, "pcs.h5"), "r") - lamb = h5.File(os.path.join(self.galaxy_SED_path, "lamb.h5"), "r") - self.lamb_gal = lamb['lamb'][()] - self.pcs = pcs['pcs'][()] - - def _load_SED_lib_AGN(self): - from astropy.io import fits - self.SED_AGN = fits.open(self.AGN_SED_path)[0].data - self.lamb_AGN = np.load(self.AGN_SED_wave_path) - - - def _load_gals(self, gals, pix_id=None, cat_id=0): - ngals = len(gals['ra']) - - # Apply astrometric modeling - # in C3 case only aberration - ra_arr = gals['ra'][:] - dec_arr = gals['dec'][:] - 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.utcfromtimestamp(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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - - for igals in range(ngals): - # # (TEST) - # if igals > 100: - # break - - param = self.initialize_param() - param['ra'] = ra_arr[igals] - param['dec'] = dec_arr[igals] - param['ra_orig'] = gals['ra'][igals] - param['dec_orig'] = gals['dec'][igals] - param['mag_use_normal'] = gals['mag_csst_%s'%(self.filt.filter_type)][igals] - if self.filt.is_too_dim(mag=param['mag_use_normal'], margin=self.config["obs_setting"]["mag_lim_margin"]): - continue - - param['z'] = gals['redshift'][igals] - param['model_tag'] = 'None' - param['g1'] = gals['shear'][igals][0] - param['g2'] = gals['shear'][igals][1] - param['kappa'] = gals['kappa'][igals] - param['e1'] = gals['ellipticity_true'][igals][0] - param['e2'] = gals['ellipticity_true'][igals][1] - - # For shape calculation - - param['ell_total'] = np.sqrt(param['e1']**2 + param['e2']**2) - if param['ell_total'] > 0.9: - continue - param['e1_disk'] = param['e1'] - param['e2_disk'] = param['e2'] - param['e1_bulge'] = param['e1'] - param['e2_bulge'] = param['e2'] - - - param['delta_ra'] = 0 - param['delta_dec'] = 0 - - # Masses - param['bulgemass'] = gals['bulgemass'][igals] - param['diskmass'] = gals['diskmass'][igals] - - param['size'] = gals['size'][igals] - if param['size'] > self.max_size: - self.max_size = param['size'] - - # Sersic index - param['disk_sersic_idx'] = 1. - param['bulge_sersic_idx'] = 4. - - # Sizes - param['bfrac'] = param['bulgemass']/(param['bulgemass'] + param['diskmass']) - if param['bfrac'] >= 0.6: - param['hlr_bulge'] = param['size'] - param['hlr_disk'] = param['size'] * (1. - param['bfrac']) - else: - param['hlr_disk'] = param['size'] - param['hlr_bulge'] = param['size'] * param['bfrac'] - - # SED coefficients - param['coeff'] = gals['coeff'][igals] - param['detA'] = gals['detA'][igals] - - # Others - param['galType'] = gals['type'][igals] - param['veldisp'] = gals['veldisp'][igals] - - # TEST no redening and no extinction - param['av'] = 0.0 - param['redden'] = 0 - - param['star'] = 0 # Galaxy - - # NOTE: this cut cannot be put before the SED type has been assigned - if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): - continue - - # TEMP - self.ids += 1 - # param['id'] = self.ids - param['id'] = '%06d'%(int(pix_id)) + '%06d'%(cat_id) + '%08d'%(igals) - - if param['star'] == 0: - obj = Galaxy(param, logger=self.logger) - - # Need to deal with additional output columns - obj.additional_output_str = self.add_fmt%("n", 0., 0., 0., - param['bulgemass'], param['diskmass'], param['detA'], - param['e1'], param['e2'], param['kappa'], param['g1'], param['g2'], param['size'], - param['galType'], param['veldisp']) - - 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.utcfromtimestamp(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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - for istars in range(nstars): - # # (TEST) - # if istars > 100: - # break - - 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'] = 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) - - # Append additional output columns to the .cat file - obj.additional_output_str = self.add_fmt%(param["model_tag"], param['teff'], param['logg'], param['feh'], - 0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.) - - self.objs.append(obj) - - def _load_AGNs(self): - data = Table.read(self.AGN_path) - ra_arr = data['ra'] - dec_arr = data['dec'] - nAGNs = len(data) - if self.config["obs_setting"]["enable_astrometric_model"]: - ra_list = ra_arr.tolist() - dec_list = dec_arr.tolist() - pmra_list = np.zeros(nAGNs).tolist() - pmdec_list = np.zeros(nAGNs).tolist() - rv_list = np.zeros(nAGNs).tolist() - parallax_list = [1e-9] * nAGNs - dt = datetime.utcfromtimestamp(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=nAGNs, - 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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - for iAGNs in range(nAGNs): - param = self.initialize_param() - param['ra'] = ra_arr[iAGNs] - param['dec'] = dec_arr[iAGNs] - param['ra_orig'] = data['ra'][iAGNs] - param['dec_orig'] = data['dec'][iAGNs] - param['z'] = data['z'][iAGNs] - param['appMag'] = data['appMag'][iAGNs] - param['absMag'] = data['absMag'][iAGNs] - - # NOTE: this cut cannot be put before the SED type has been assigned - if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): - continue - - # TEST no redening and no extinction - param['av'] = 0.0 - param['redden'] = 0 - - param['star'] = 2 # Quasar - param['id'] = data['igmlos'][iAGNs] - - if param['star'] == 2: - obj = Quasar(param, logger=self.logger) - - # Append additional output columns to the .cat file - obj.additional_output_str = self.add_fmt%("n", 0., 0., 0., - 0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.) - self.objs.append(obj) - - def _load_calibObj(self): - - data = Table.read(self.CALIB_cat_path) - ra_arr = data['RA'] - dec_arr = data['DEC'] - - ngals = len(data) - - # Apply astrometric modeling - # in C3 case only aberration - # ra_arr = gals['ra'][:] - # dec_arr = gals['dec'][:] - 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.utcfromtimestamp(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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - - for igals in range(ngals): - # # (TEST) - # if igals > 100: - # break - - param = self.initialize_param() - param['ra'] = ra_arr[igals] - param['dec'] = dec_arr[igals] - param['ra_orig'] = data['RA'][igals] - param['dec_orig'] = data['DEC'][igals] - param['mag_use_normal'] = data['MAG_g'][igals] - # if self.filt.is_too_dim(mag=param['mag_use_normal'], margin=self.config["obs_setting"]["mag_lim_margin"]): - # continue - - param['z'] = -99 - param['model_tag'] = 'None' - param['g1'] = 0 - param['g2'] = 0 - param['kappa'] = 0 - param['e1'] = 0 - param['e2'] = 0 - - # For shape calculation - - param['ell_total'] = np.sqrt(param['e1'] ** 2 + param['e2'] ** 2) - if param['ell_total'] > 0.9: - continue - param['e1_disk'] = 0 - param['e2_disk'] = 0 - param['e1_bulge'] = 0 - param['e2_bulge'] = 0 - - param['delta_ra'] = 0 - param['delta_dec'] = 0 - - # Masses - # param['bulgemass'] = gals['bulgemass'][igals] - # param['diskmass'] = gals['diskmass'][igals] - - # param['size'] = gals['size'][igals] - # if param['size'] > self.max_size: - # self.max_size = param['size'] - - # Sersic index - param['disk_sersic_idx'] = data['SERSIC_N'][igals] - param['bulge_sersic_idx'] = 1. - param['hlr_bulge'] = data['RE'][igals] - param['hlr_disk'] = data['RE'][igals] - param['bfrac'] = 0 - # TEST no redening and no extinction - param['av'] = 0.0 - param['redden'] = 0 - - param['star'] = 4 - - # NOTE: this cut cannot be put before the SED type has been assigned - if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): - continue - - # TEMP - self.ids += 1 - # param['id'] = self.ids - param['id'] = data['SPEC_FN'][igals][0:-5] - - if param['star'] == 4: - obj = Galaxy(param, logger=self.logger) - - # Need to deal with additional output columns - # obj.additional_output_str = self.add_fmt % ("n", 0., 0., 0., - # param['bulgemass'], param['diskmass'], param['detA'], - # param['e1'], param['e2'], param['kappa'], param['g1'], - # param['g2'], param['size'], - # param['galType'], param['veldisp']) - - self.objs.append(obj) - - - def _load(self, **kwargs): - self.objs = [] - self.ids = 0 - - if "star_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["star_cat"] and not self.config["catalog_options"]["galaxy_only"]: - star_cat = h5.File(self.star_path, 'r')['catalog'] - for pix in self.pix_list: - try: - stars = star_cat[str(pix)] - self._load_stars(stars, pix_id=pix) - del stars - except Exception as e: - self.logger.error(str(e)) - print(e) - - if "galaxy_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["galaxy_cat"] and not self.config["catalog_options"]["star_only"]: - for pix in self.pix_list: - try: - bundleID = get_bundleIndex(pix) - file_path = os.path.join(self.galaxy_path, "galaxies_C6_bundle{:06}.h5".format(bundleID)) - gals_cat = h5.File(file_path, 'r')['galaxies'] - gals = gals_cat[str(pix)] - self._load_gals(gals, pix_id=pix, cat_id=bundleID) - del gals - except Exception as e: - traceback.print_exc() - self.logger.error(str(e)) - print(e) - - if "AGN_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["AGN_cat"] and not self.config["catalog_options"]["star_only"]: - try: - self._load_AGNs() - except Exception as e: - traceback.print_exc() - self.logger.error(str(e)) - print(e) - - if "CALIB_cat" in self.config["catalog_options"]["input_path"] and \ - self.config["catalog_options"]["input_path"][ - "CALIB_cat"] and not self.config["catalog_options"]["star_only"]: - try: - self._load_calibObj() - except Exception as e: - traceback.print_exc() - self.logger.error(str(e)) - print(e) - - if self.logger is not None: - self.logger.info("maximum galaxy size: %.4f"%(self.max_size)) - self.logger.info("number of objects in catalog: %d"%(len(self.objs))) - else: - print("number of objects in catalog: ", len(self.objs)) - - 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': - factor = 10**(-.4 * self.cosmo.distmod(obj.z).value) - if obj.type == 'galaxy': - flux = np.matmul(self.pcs, obj.coeff) * factor - # if np.any(flux < 0): - # raise ValueError("Glaxy %s: negative SED fluxes"%obj.id) - flux[flux < 0] = 0. - sedcat = np.vstack((self.lamb_gal, flux)).T - sed_data = getObservedSED( - sedCat=sedcat, - redshift=obj.z, - av=obj.param["av"], - redden=obj.param["redden"] - ) - wave, flux = sed_data[0], sed_data[1] - elif obj.type == 'quasar': - flux = self.SED_AGN[int(obj.id)] * 1e-17 - # if np.any(flux < 0): - # raise ValueError("Glaxy %s: negative SED fluxes"%obj.id) - flux[flux < 0] = 0. - # sedcat = np.vstack((self.lamb_AGN, flux)).T - wave = self.lamb_AGN - # print("sed (erg/s/cm2/A) = ", sed_data) - # np.savetxt(os.path.join(self.config["work_dir"], "%s_sed.txt"%(obj.id)), sedcat) - elif obj.type == 'calib': - data = Table.read(os.path.join(self.CALIB_SED_path,obj.id+'.fits')) - obj_w = data['WAVELENGTH'] - obj_f = data['FLUX'] - input_delt_w = np.min(obj_w[1:]-obj_w[0:-1]) - if input_delt_w > 0.5: - lamb = np.arange(2000, 11000 + 0.5, 0.5) - speci = interpolate.interp1d(obj_w, obj_f) - y1 = speci(lamb) - else: - lamb = obj_w - y1 = obj_f - # erg/s/cm2/A --> photon/s/m2/A - y1_phot = y1 * lamb / (cons.h.value * cons.c.value) * 1e-13 - sed = Table(np.array([lamb, y1_phot]).T, - names=('WAVELENGTH', 'FLUX')) - - 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) - return sed - else: - raise ValueError("Object type not known") - speci = interpolate.interp1d(wave, flux) - lamb = np.arange(2000, 11001+0.5, 0.5) - y = speci(lamb) - # 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': - # 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) - # if obj.param['mag_use_normal'] >= 30: - # print("obj ID = %d"%obj.id) - # print("mag_use_normal = %.3f"%obj.param['mag_use_normal']) - # print("integrated flux = %.7f"%(interFlux)) - # print("app mag = %.3f"%obj.param['appMag']) - # np.savetxt('./AGN_SED_test/sed_objID_%d.txt'%obj.id, np.transpose([self.lamb_AGN, self.SED_AGN[int(obj.id)]])) - # print("obj ID = %d"%obj.id) - # print("mag_use_normal = %.3f"%obj.param['mag_use_normal']) - # print("integrated flux = %.7f"%(interFlux)) - # print("app mag = %.3f"%obj.param['appMag']) - # print("abs mag = %.3f"%obj.param['absMag']) - # mag = getABMAG(interFlux, self.filt.bandpass_full) - # print("mag diff = %.3f"%(mag - obj.param['mag_use_normal'])) - del wave - del flux - return sed diff --git a/Catalog/FGS_Catalog.py b/Catalog/FGS_Catalog.py deleted file mode 100644 index bdab18cd497a1b5b72a719961c83557cfe2db225..0000000000000000000000000000000000000000 --- a/Catalog/FGS_Catalog.py +++ /dev/null @@ -1,516 +0,0 @@ -import os -import galsim -import random -import numpy as np -import h5py as h5 -import healpy as hp -import astropy.constants as cons -import traceback -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 tag_sed, getObservedSED, getABMAG, integrate_sed_bandpass, comoving_dist -from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position - -# (TEST) -from astropy.cosmology import FlatLambdaCDM -from astropy import constants -from astropy import units as U - -try: - import importlib.resources as pkg_resources -except ImportError: - # Try backported to PY<37 'importlib_resources' - import importlib_resources as pkg_resources - -NSIDE = 128 - -def get_bundleIndex(healpixID_ring, bundleOrder=4, healpixOrder=7): - assert NSIDE == 2**healpixOrder - shift = healpixOrder - bundleOrder - shift = 2*shift - - nside_bundle = 2**bundleOrder - nside_healpix= 2**healpixOrder - - healpixID_nest= hp.ring2nest(nside_healpix, healpixID_ring) - bundleID_nest = (healpixID_nest >> shift) - bundleID_ring = hp.nest2ring(nside_bundle, bundleID_nest) - - return bundleID_ring - -class Catalog(CatalogBase): - def __init__(self, config, chip, pointing, chip_output, filt, **kwargs): - super().__init__() - self.cat_dir = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["cat_dir"]) - self.seed_Av = config["catalog_options"]["seed_Av"] - - # (TEST) - self.cosmo = FlatLambdaCDM(H0=67.66, Om0=0.3111) - - self.chip_output = chip_output - self.filt = filt - self.logger = chip_output.logger - - with pkg_resources.path('Catalog.data', 'SLOAN_SDSS.g.fits') as filter_path: - self.normF_star = Table.read(str(filter_path)) - - self.config = config - self.chip = chip - self.pointing = pointing - - self.max_size = 0. - - if "star_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["star_cat"] and not config["catalog_options"]["galaxy_only"]: - star_file = config["catalog_options"]["input_path"]["star_cat"] - star_SED_file = config["catalog_options"]["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["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["galaxy_cat"] and not config["catalog_options"]["star_only"]: - galaxy_dir = config["catalog_options"]["input_path"]["galaxy_cat"] - self.galaxy_path = os.path.join(self.cat_dir, galaxy_dir) - self.galaxy_SED_path = os.path.join(config["data_dir"], config["catalog_options"]["SED_templates_path"]["galaxy_SED"]) - self._load_SED_lib_gals() - - if "AGN_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["AGN_cat"] and not config["catalog_options"]["star_only"]: - AGN_dir = config["catalog_options"]["input_path"]["AGN_cat"] - self.AGN_path = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["AGN_cat"]) - self.AGN_SED_path = os.path.join(config["data_dir"], config["catalog_options"]["SED_templates_path"]["AGN_SED"]) - self.AGN_SED_wave_path = os.path.join(config['data_dir'], config["catalog_options"]["SED_templates_path"]["AGN_SED_WAVE"]) - self._load_SED_lib_AGN() - - if "rotateEll" in config["catalog_options"]: - self.rotation = np.radians(float(config["catalog_options"]["rotateEll"])) - else: - self.rotation = 0. - - # Update output .cat header with catalog specific output columns - self._add_output_columns_header() - - self._get_healpix_list() - self._load() - - def _add_output_columns_header(self): - self.add_hdr = " model_tag teff logg feh" - self.add_hdr += " bulgemass diskmass detA e1 e2 kappa g1 g2 size galType veldisp " - - self.add_fmt = " %10s %8.4f %8.4f %8.4f" - self.add_fmt += " %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %4d %8.4f " - self.chip_output.update_output_header(additional_column_names=self.add_hdr) - - 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, - hp.ang2vec(np.radians(90.) - dec, ra), - 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 - return None - 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): - pcs = h5.File(os.path.join(self.galaxy_SED_path, "pcs.h5"), "r") - lamb = h5.File(os.path.join(self.galaxy_SED_path, "lamb.h5"), "r") - self.lamb_gal = lamb['lamb'][()] - self.pcs = pcs['pcs'][()] - - def _load_SED_lib_AGN(self): - from astropy.io import fits - self.SED_AGN = fits.open(self.AGN_SED_path)[0].data - self.lamb_AGN = np.load(self.AGN_SED_wave_path) - - - def _load_gals(self, gals, pix_id=None, cat_id=0): - ngals = len(gals['ra']) - - # Apply astrometric modeling - # in C3 case only aberration - ra_arr = gals['ra'][:] - dec_arr = gals['dec'][:] - 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.utcfromtimestamp(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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - - for igals in range(ngals): - # # (TEST) - # if igals > 100: - # break - - param = self.initialize_param() - param['ra'] = ra_arr[igals] - param['dec'] = dec_arr[igals] - param['ra_orig'] = gals['ra'][igals] - param['dec_orig'] = gals['dec'][igals] - # param['mag_use_normal'] = gals['mag_csst_%s'%(self.filt.filter_type)][igals] - # if self.filt.is_too_dim(mag=param['mag_use_normal'], margin=self.config["obs_setting"]["mag_lim_margin"]): - # continue - - param['z'] = gals['redshift'][igals] - param['model_tag'] = 'None' - param['g1'] = gals['shear'][igals][0] - param['g2'] = gals['shear'][igals][1] - param['kappa'] = gals['kappa'][igals] - param['e1'] = gals['ellipticity_true'][igals][0] - param['e2'] = gals['ellipticity_true'][igals][1] - - # For shape calculation - - param['ell_total'] = np.sqrt(param['e1']**2 + param['e2']**2) - if param['ell_total'] > 0.9: - continue - param['e1_disk'] = param['e1'] - param['e2_disk'] = param['e2'] - param['e1_bulge'] = param['e1'] - param['e2_bulge'] = param['e2'] - - - param['delta_ra'] = 0 - param['delta_dec'] = 0 - - # Masses - param['bulgemass'] = gals['bulgemass'][igals] - param['diskmass'] = gals['diskmass'][igals] - - param['size'] = gals['size'][igals] - if param['size'] > self.max_size: - self.max_size = param['size'] - - # Sersic index - param['disk_sersic_idx'] = 1. - param['bulge_sersic_idx'] = 4. - - # Sizes - param['bfrac'] = param['bulgemass']/(param['bulgemass'] + param['diskmass']) - if param['bfrac'] >= 0.6: - param['hlr_bulge'] = param['size'] - param['hlr_disk'] = param['size'] * (1. - param['bfrac']) - else: - param['hlr_disk'] = param['size'] - param['hlr_bulge'] = param['size'] * param['bfrac'] - - # SED coefficients - param['coeff'] = gals['coeff'][igals] - param['detA'] = gals['detA'][igals] - - # Others - param['galType'] = gals['type'][igals] - param['veldisp'] = gals['veldisp'][igals] - - # TEST no redening and no extinction - param['av'] = 0.0 - param['redden'] = 0 - - param['star'] = 0 # Galaxy - - # NOTE: this cut cannot be put before the SED type has been assigned - if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): - continue - - # TEMP - self.ids += 1 - # param['id'] = self.ids - param['id'] = '%06d'%(int(pix_id)) + '%06d'%(cat_id) + '%08d'%(igals) - - if param['star'] == 0: - obj = Galaxy(param, logger=self.logger) - - # Need to deal with additional output columns - obj.additional_output_str = self.add_fmt%("n", 0., 0., 0., - param['bulgemass'], param['diskmass'], param['detA'], - param['e1'], param['e2'], param['kappa'], param['g1'], param['g2'], param['size'], - param['galType'], param['veldisp']) - - 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.utcfromtimestamp(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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - for istars in range(nstars): - # # (TEST) - # if istars > 100: - # break - - 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'] = 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) - - # Append additional output columns to the .cat file - obj.additional_output_str = self.add_fmt%(param["model_tag"], param['teff'], param['logg'], param['feh'], - 0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.) - - self.objs.append(obj) - - def _load_AGNs(self): - data = Table.read(self.AGN_path) - ra_arr = data['ra'] - dec_arr = data['dec'] - nAGNs = len(data) - if self.config["obs_setting"]["enable_astrometric_model"]: - ra_list = ra_arr.tolist() - dec_list = dec_arr.tolist() - pmra_list = np.zeros(nAGNs).tolist() - pmdec_list = np.zeros(nAGNs).tolist() - rv_list = np.zeros(nAGNs).tolist() - parallax_list = [1e-9] * nAGNs - dt = datetime.utcfromtimestamp(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=nAGNs, - 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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - for iAGNs in range(nAGNs): - param = self.initialize_param() - param['ra'] = ra_arr[iAGNs] - param['dec'] = dec_arr[iAGNs] - param['ra_orig'] = data['ra'][iAGNs] - param['dec_orig'] = data['dec'][iAGNs] - param['z'] = data['z'][iAGNs] - param['appMag'] = data['appMag'][iAGNs] - param['absMag'] = data['absMag'][iAGNs] - - # NOTE: this cut cannot be put before the SED type has been assigned - if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): - continue - - # TEST no redening and no extinction - param['av'] = 0.0 - param['redden'] = 0 - - param['star'] = 2 # Quasar - param['id'] = data['igmlos'][iAGNs] - - if param['star'] == 2: - obj = Quasar(param, logger=self.logger) - - # Append additional output columns to the .cat file - obj.additional_output_str = self.add_fmt%("n", 0., 0., 0., - 0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.) - self.objs.append(obj) - - def _load(self, **kwargs): - self.objs = [] - self.ids = 0 - - if "star_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["star_cat"] and not self.config["catalog_options"]["galaxy_only"]: - star_cat = h5.File(self.star_path, 'r')['catalog'] - for pix in self.pix_list: - try: - stars = star_cat[str(pix)] - self._load_stars(stars, pix_id=pix) - del stars - except Exception as e: - self.logger.error(str(e)) - print(e) - - if "galaxy_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["galaxy_cat"] and not self.config["catalog_options"]["star_only"]: - for pix in self.pix_list: - try: - bundleID = get_bundleIndex(pix) - file_path = os.path.join(self.galaxy_path, "galaxies_C6_bundle{:06}.h5".format(bundleID)) - gals_cat = h5.File(file_path, 'r')['galaxies'] - gals = gals_cat[str(pix)] - self._load_gals(gals, pix_id=pix, cat_id=bundleID) - del gals - except Exception as e: - traceback.print_exc() - self.logger.error(str(e)) - print(e) - - if "AGN_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["AGN_cat"] and not self.config["catalog_options"]["star_only"]: - try: - self._load_AGNs() - except Exception as e: - traceback.print_exc() - self.logger.error(str(e)) - print(e) - - if self.logger is not None: - self.logger.info("maximum galaxy size: %.4f"%(self.max_size)) - self.logger.info("number of objects in catalog: %d"%(len(self.objs))) - else: - print("number of objects in catalog: ", len(self.objs)) - - 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': - factor = 10**(-.4 * self.cosmo.distmod(obj.z).value) - if obj.type == 'galaxy': - flux = np.matmul(self.pcs, obj.coeff) * factor - # if np.any(flux < 0): - # raise ValueError("Glaxy %s: negative SED fluxes"%obj.id) - flux[flux < 0] = 0. - sedcat = np.vstack((self.lamb_gal, flux)).T - sed_data = getObservedSED( - sedCat=sedcat, - redshift=obj.z, - av=obj.param["av"], - redden=obj.param["redden"] - ) - wave, flux = sed_data[0], sed_data[1] - elif obj.type == 'quasar': - flux = self.SED_AGN[int(obj.id)] * 1e-17 - # if np.any(flux < 0): - # raise ValueError("Glaxy %s: negative SED fluxes"%obj.id) - flux[flux < 0] = 0. - # sedcat = np.vstack((self.lamb_AGN, flux)).T - wave = self.lamb_AGN - # print("sed (erg/s/cm2/A) = ", sed_data) - # np.savetxt(os.path.join(self.config["work_dir"], "%s_sed.txt"%(obj.id)), sedcat) - else: - raise ValueError("Object type not known") - speci = interpolate.interp1d(wave, flux) - lamb = np.arange(2000, 11001+0.5, 0.5) - y = speci(lamb) - # 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 == 'galaxy' or 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) - # if obj.param['mag_use_normal'] >= 30: - # print("obj ID = %d"%obj.id) - # print("mag_use_normal = %.3f"%obj.param['mag_use_normal']) - # print("integrated flux = %.7f"%(interFlux)) - # print("app mag = %.3f"%obj.param['appMag']) - # np.savetxt('./AGN_SED_test/sed_objID_%d.txt'%obj.id, np.transpose([self.lamb_AGN, self.SED_AGN[int(obj.id)]])) - # print("obj ID = %d"%obj.id) - # print("mag_use_normal = %.3f"%obj.param['mag_use_normal']) - # print("integrated flux = %.7f"%(interFlux)) - # print("app mag = %.3f"%obj.param['appMag']) - # print("abs mag = %.3f"%obj.param['absMag']) - # mag = getABMAG(interFlux, self.filt.bandpass_full) - # print("mag diff = %.3f"%(mag - obj.param['mag_use_normal'])) - del wave - del flux - return sed diff --git a/Catalog/NGPCatalog.py b/Catalog/NGPCatalog.py deleted file mode 100644 index cf6ae97a2758d98ab827f5e94f06222c5a9cdd0b..0000000000000000000000000000000000000000 --- a/Catalog/NGPCatalog.py +++ /dev/null @@ -1,331 +0,0 @@ -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 Catalog(CatalogBase): - def __init__(self, config, chip, pointing, chip_output, **kwargs): - super().__init__() - self.cat_dir = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["cat_dir"]) - self.seed_Av = config["catalog_options"]["seed_Av"] - - self.chip_output = chip_output - self.logger = chip_output.logger - - 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["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["star_cat"] and not config["catalog_options"]["galaxy_only"]: - star_file = config["catalog_options"]["input_path"]["star_cat"] - star_SED_file = config["catalog_options"]["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["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["galaxy_cat"] and not config["catalog_options"]["star_only"]: - galaxy_file = config["catalog_options"]["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["catalog_options"]["SED_templates_path"]["galaxy_SED"]) - self._load_SED_lib_gals() - if "rotateEll" in config["catalog_options"]: - self.rotation = np.radians(float(config["catalog_options"]["rotateEll"])) - else: - self.rotation = 0. - - # Update output .cat header with catalog specific output columns - self._add_output_columns_header() - - self._get_healpix_list() - self._load() - - def _add_output_columns_header(self): - self.add_hdr = " model_tag teff logg feh" - self.add_fmt = " %10s %8.4f %8.4f %8.4f" - self.chip_output.update_output_header(additional_column_names=self.add_hdr) - - 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.utcfromtimestamp(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] - 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['g1'] = 0 - param['g2'] = 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)] - - # TEST no redening and no extinction - param['av'] = 0.0 - param['redden'] = 0 - - 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 - - # NOTE: this cut cannot be put before the SED type has been assigned - if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): - continue - - self.ids += 1 - # param['id'] = self.ids - param['id'] = gals['galaxyID'][igals] - - if param['star'] == 0: - obj = Galaxy(param, logger=self.logger) - if param['star'] == 2: - obj = Quasar(param, logger=self.logger) - - # Need to deal with additional output columns - obj.additional_output_str = self.add_fmt%("n", 0., 0., 0.) - - 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.utcfromtimestamp(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) - - # Append additional output columns to the .cat file - obj.additional_output_str = self.add_fmt%(param["model_tag"], param['teff'], param['logg'], param['feh']) - - 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["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["star_cat"] and not self.config["catalog_options"]["galaxy_only"]: - star_cat = h5.File(self.star_path, 'r')['catalog'] - for pix in self.pix_list: - try: - stars = star_cat[str(pix)] - self._load_stars(stars, pix_id=pix) - del stars - except Exception as e: - self.logger.error(str(e)) - print(e) - if "galaxy_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["galaxy_cat"] and not self.config["catalog_options"]["star_only"]: - gals_cat = h5.File(self.galaxy_path, 'r')['galaxies'] - for pix in self.pix_list: - try: - gals = gals_cat[str(pix)] - self._load_gals(gals, pix_id=pix) - del gals - except Exception as e: - self.logger.error(str(e)) - print(e) - 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(2000, 18001 + 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 diff --git a/Catalog/fd_test_C6.py b/Catalog/fd_test_C6.py deleted file mode 100644 index cbb41e88bcdeed54074a4ef2bca09f053ed1e31c..0000000000000000000000000000000000000000 --- a/Catalog/fd_test_C6.py +++ /dev/null @@ -1,524 +0,0 @@ -import os -import galsim -import random -import numpy as np -import h5py as h5 -import healpy as hp -import astropy.constants as cons -import traceback -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 tag_sed, getObservedSED, getABMAG, integrate_sed_bandpass, comoving_dist -from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position - -# (TEST) -from astropy.cosmology import FlatLambdaCDM -from astropy import constants -from astropy import units as U - -try: - import importlib.resources as pkg_resources -except ImportError: - # Try backported to PY<37 'importlib_resources' - import importlib_resources as pkg_resources - -NSIDE = 128 - -def get_bundleIndex(healpixID_ring, bundleOrder=4, healpixOrder=7): - assert NSIDE == 2**healpixOrder - shift = healpixOrder - bundleOrder - shift = 2*shift - - nside_bundle = 2**bundleOrder - nside_healpix= 2**healpixOrder - - healpixID_nest= hp.ring2nest(nside_healpix, healpixID_ring) - bundleID_nest = (healpixID_nest >> shift) - bundleID_ring = hp.nest2ring(nside_bundle, bundleID_nest) - - return bundleID_ring - -class Catalog(CatalogBase): - def __init__(self, config, chip, pointing, chip_output, filt, **kwargs): - super().__init__() - self.cat_dir = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["cat_dir"]) - self.seed_Av = config["catalog_options"]["seed_Av"] - - self.cosmo = FlatLambdaCDM(H0=67.66, Om0=0.3111) - - self.chip_output = chip_output - self.filt = filt - self.logger = chip_output.logger - - with pkg_resources.path('Catalog.data', 'SLOAN_SDSS.g.fits') as filter_path: - self.normF_star = Table.read(str(filter_path)) - - self.config = config - self.chip = chip - self.pointing = pointing - - self.max_size = 0. - - if "star_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["star_cat"] and not config["catalog_options"]["galaxy_only"]: - star_file = config["catalog_options"]["input_path"]["star_cat"] - star_SED_file = config["catalog_options"]["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["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["galaxy_cat"] and not config["catalog_options"]["star_only"]: - galaxy_dir = config["catalog_options"]["input_path"]["galaxy_cat"] - self.galaxy_path = os.path.join(self.cat_dir, galaxy_dir) - self.galaxy_SED_path = os.path.join(config["data_dir"], config["catalog_options"]["SED_templates_path"]["galaxy_SED"]) - self._load_SED_lib_gals() - - if "AGN_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["AGN_cat"] and not config["catalog_options"]["star_only"]: - AGN_dir = config["catalog_options"]["input_path"]["AGN_cat"] - self.AGN_path = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["AGN_cat"]) - self.AGN_SED_path = os.path.join(config["data_dir"], config["catalog_options"]["SED_templates_path"]["AGN_SED"]) - self.AGN_SED_wave_path = os.path.join(config['data_dir'], config["catalog_options"]["SED_templates_path"]["AGN_SED_WAVE"]) - self._load_SED_lib_AGN() - - if "rotateEll" in config["catalog_options"]: - self.rotation = np.radians(float(config["catalog_options"]["rotateEll"])) - else: - self.rotation = 0. - - # Update output .cat header with catalog specific output columns - self._add_output_columns_header() - - self._get_healpix_list() - self._load() - - def _add_output_columns_header(self): - self.add_hdr = " model_tag teff logg feh" - self.add_hdr += " bulgemass diskmass detA e1 e2 kappa g1 g2 size galType veldisp " - - self.add_fmt = " %10s %8.4f %8.4f %8.4f" - self.add_fmt += " %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %4d %8.4f " - self.chip_output.update_output_header(additional_column_names=self.add_hdr) - - 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, - hp.ang2vec(np.radians(90.) - dec, ra), - 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 - return None - 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): - pcs = h5.File(os.path.join(self.galaxy_SED_path, "pcs.h5"), "r") - lamb = h5.File(os.path.join(self.galaxy_SED_path, "lamb.h5"), "r") - self.lamb_gal = lamb['lamb'][()] - self.pcs = pcs['pcs'][()] - - def _load_SED_lib_AGN(self): - from astropy.io import fits - self.SED_AGN = fits.open(self.AGN_SED_path)[0].data - self.lamb_AGN = np.load(self.AGN_SED_wave_path) - - - def _load_gals(self, gals, pix_id=None, cat_id=0): - ngals = len(gals['ra']) - - # Apply astrometric modeling - # in C3 case only aberration - ra_arr = gals['ra'][:] - dec_arr = gals['dec'][:] - 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.utcfromtimestamp(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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - - # for igals in range(ngals): - for igals in range(0, ngals, 5): - # # (TEST) - # if igals > 1000: - # break - - param = self.initialize_param() - param['ra'] = ra_arr[igals] - param['dec'] = dec_arr[igals] - param['ra_orig'] = gals['ra'][igals] - param['dec_orig'] = gals['dec'][igals] - # param['mag_use_normal'] = gals['mag_csst_%s'%(self.filt.filter_type)][igals] - param['mag_use_normal'] = 20. - if self.filt.is_too_dim(mag=param['mag_use_normal'], margin=self.config["obs_setting"]["mag_lim_margin"]): - continue - - param['z'] = gals['redshift'][igals] - param['model_tag'] = 'None' - # param['g1'] = gals['shear'][igals][0] - # param['g2'] = gals['shear'][igals][1] - param['g1'] = 0. - param['g2'] = 0. - param['kappa'] = gals['kappa'][igals] - param['e1'] = gals['ellipticity_true'][igals][0] - param['e2'] = gals['ellipticity_true'][igals][1] - - # For shape calculation - - param['ell_total'] = np.sqrt(param['e1']**2 + param['e2']**2) - if param['ell_total'] > 0.9: - continue - # param['e1_disk'] = param['e1'] - # param['e2_disk'] = param['e2'] - # param['e1_bulge'] = param['e1'] - # param['e2_bulge'] = param['e2'] - param['e1_disk'] = 0. - param['e2_disk'] = 0. - param['e1_bulge'] = 0. - param['e2_bulge'] = 0. - - - param['delta_ra'] = 0 - param['delta_dec'] = 0 - - # Masses - param['bulgemass'] = gals['bulgemass'][igals] - param['diskmass'] = gals['diskmass'][igals] - - # param['size'] = gals['size'][igals] - param['size'] = 1. - if param['size'] > self.max_size: - self.max_size = param['size'] - - # Sersic index - param['disk_sersic_idx'] = 1. - param['bulge_sersic_idx'] = 4. - - # Sizes - # param['bfrac'] = param['bulgemass']/(param['bulgemass'] + param['diskmass']) - param['bfrac'] = 0. - if param['bfrac'] >= 0.6: - param['hlr_bulge'] = param['size'] - param['hlr_disk'] = param['size'] * (1. - param['bfrac']) - else: - param['hlr_disk'] = param['size'] - param['hlr_bulge'] = param['size'] * param['bfrac'] - - # SED coefficients - param['coeff'] = gals['coeff'][igals] - param['detA'] = gals['detA'][igals] - - # Others - param['galType'] = gals['type'][igals] - param['veldisp'] = gals['veldisp'][igals] - - # TEST no redening and no extinction - param['av'] = 0.0 - param['redden'] = 0 - - param['star'] = 0 # Galaxy - - # NOTE: this cut cannot be put before the SED type has been assigned - if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): - continue - - # TEMP - self.ids += 1 - # param['id'] = self.ids - param['id'] = '%06d'%(int(pix_id)) + '%06d'%(cat_id) + '%08d'%(igals) - - if param['star'] == 0: - obj = Galaxy(param, logger=self.logger) - - # Need to deal with additional output columns - obj.additional_output_str = self.add_fmt%("n", 0., 0., 0., - param['bulgemass'], param['diskmass'], param['detA'], - param['e1'], param['e2'], param['kappa'], param['g1'], param['g2'], param['size'], - param['galType'], param['veldisp']) - - 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.utcfromtimestamp(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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - for istars in range(nstars): - # # (TEST) - # if istars > 100: - # break - - 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'] = 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) - - # Append additional output columns to the .cat file - obj.additional_output_str = self.add_fmt%(param["model_tag"], param['teff'], param['logg'], param['feh'], - 0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.) - - self.objs.append(obj) - - def _load_AGNs(self): - data = Table.read(self.AGN_path) - ra_arr = data['ra'] - dec_arr = data['dec'] - nAGNs = len(data) - if self.config["obs_setting"]["enable_astrometric_model"]: - ra_list = ra_arr.tolist() - dec_list = dec_arr.tolist() - pmra_list = np.zeros(nAGNs).tolist() - pmdec_list = np.zeros(nAGNs).tolist() - rv_list = np.zeros(nAGNs).tolist() - parallax_list = [1e-9] * nAGNs - dt = datetime.utcfromtimestamp(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=nAGNs, - 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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - for iAGNs in range(nAGNs): - param = self.initialize_param() - param['ra'] = ra_arr[iAGNs] - param['dec'] = dec_arr[iAGNs] - param['ra_orig'] = data['ra'][iAGNs] - param['dec_orig'] = data['dec'][iAGNs] - param['z'] = data['z'][iAGNs] - param['appMag'] = data['appMag'][iAGNs] - param['absMag'] = data['absMag'][iAGNs] - - # NOTE: this cut cannot be put before the SED type has been assigned - if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): - continue - - # TEST no redening and no extinction - param['av'] = 0.0 - param['redden'] = 0 - - param['star'] = 2 # Quasar - param['id'] = data['igmlos'][iAGNs] - - if param['star'] == 2: - obj = Quasar(param, logger=self.logger) - - # Append additional output columns to the .cat file - obj.additional_output_str = self.add_fmt%("n", 0., 0., 0., - 0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.) - self.objs.append(obj) - - def _load(self, **kwargs): - self.objs = [] - self.ids = 0 - - # if "star_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["star_cat"] and not self.config["catalog_options"]["galaxy_only"]: - # star_cat = h5.File(self.star_path, 'r')['catalog'] - # for pix in self.pix_list: - # try: - # stars = star_cat[str(pix)] - # self._load_stars(stars, pix_id=pix) - # del stars - # except Exception as e: - # self.logger.error(str(e)) - # print(e) - - if "galaxy_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["galaxy_cat"] and not self.config["catalog_options"]["star_only"]: - for pix in self.pix_list: - try: - bundleID = get_bundleIndex(pix) - file_path = os.path.join(self.galaxy_path, "galaxies_C6_bundle{:06}.h5".format(bundleID)) - gals_cat = h5.File(file_path, 'r')['galaxies'] - gals = gals_cat[str(pix)] - self._load_gals(gals, pix_id=pix, cat_id=bundleID) - del gals - except Exception as e: - traceback.print_exc() - self.logger.error(str(e)) - print(e) - - # if "AGN_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["AGN_cat"] and not self.config["catalog_options"]["star_only"]: - # try: - # self._load_AGNs() - # except Exception as e: - # traceback.print_exc() - # self.logger.error(str(e)) - # print(e) - - if self.logger is not None: - self.logger.info("maximum galaxy size: %.4f"%(self.max_size)) - self.logger.info("number of objects in catalog: %d"%(len(self.objs))) - else: - print("number of objects in catalog: ", len(self.objs)) - - 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': - factor = 10**(-.4 * self.cosmo.distmod(obj.z).value) - if obj.type == 'galaxy': - flux = np.matmul(self.pcs, obj.coeff) * factor - # if np.any(flux < 0): - # raise ValueError("Glaxy %s: negative SED fluxes"%obj.id) - flux[flux < 0] = 0. - sedcat = np.vstack((self.lamb_gal, flux)).T - sed_data = getObservedSED( - sedCat=sedcat, - redshift=obj.z, - av=obj.param["av"], - redden=obj.param["redden"] - ) - wave, flux = sed_data[0], sed_data[1] - elif obj.type == 'quasar': - flux = self.SED_AGN[int(obj.id)] * 1e-17 - # if np.any(flux < 0): - # raise ValueError("Glaxy %s: negative SED fluxes"%obj.id) - flux[flux < 0] = 0. - # sedcat = np.vstack((self.lamb_AGN, flux)).T - wave = self.lamb_AGN - # print("sed (erg/s/cm2/A) = ", sed_data) - # np.savetxt(os.path.join(self.config["work_dir"], "%s_sed.txt"%(obj.id)), sedcat) - else: - raise ValueError("Object type not known") - speci = interpolate.interp1d(wave, flux) - lamb = np.arange(2000, 11001+0.5, 0.5) - y = speci(lamb) - # 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': - # 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) - # if obj.param['mag_use_normal'] >= 30: - # print("obj ID = %d"%obj.id) - # print("mag_use_normal = %.3f"%obj.param['mag_use_normal']) - # print("integrated flux = %.7f"%(interFlux)) - # print("app mag = %.3f"%obj.param['appMag']) - # np.savetxt('./AGN_SED_test/sed_objID_%d.txt'%obj.id, np.transpose([self.lamb_AGN, self.SED_AGN[int(obj.id)]])) - # print("obj ID = %d"%obj.id) - # print("mag_use_normal = %.3f"%obj.param['mag_use_normal']) - # print("integrated flux = %.7f"%(interFlux)) - # print("app mag = %.3f"%obj.param['appMag']) - # print("abs mag = %.3f"%obj.param['absMag']) - # mag = getABMAG(interFlux, self.filt.bandpass_full) - # print("mag diff = %.3f"%(mag - obj.param['mag_use_normal'])) - del wave - del flux - return sed diff --git a/Catalog/testCat_galaxy.py b/Catalog/testCat_galaxy.py deleted file mode 100644 index fd9a5a41c686ebee91ab5633e760dc6902325551..0000000000000000000000000000000000000000 --- a/Catalog/testCat_galaxy.py +++ /dev/null @@ -1,447 +0,0 @@ -import os -import galsim -import random -import numpy as np -import h5py as h5 -import healpy as hp -import astropy.constants as cons -import traceback -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, Stamp -from ObservationSim.MockObject._util import tag_sed, getObservedSED, getABMAG, integrate_sed_bandpass, comoving_dist -from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position - -import astropy.io.fits as fitsio -from ObservationSim.MockObject._util import seds, sed_assign, extAv - -# (TEST) -from astropy.cosmology import FlatLambdaCDM -from astropy import constants -from astropy import units as U - -try: - import importlib.resources as pkg_resources -except ImportError: - # Try backported to PY<37 'importlib_resources' - import importlib_resources as pkg_resources - -NSIDE = 128 - -def get_bundleIndex(healpixID_ring, bundleOrder=4, healpixOrder=7): - assert NSIDE == 2**healpixOrder - shift = healpixOrder - bundleOrder - shift = 2*shift - - nside_bundle = 2**bundleOrder - nside_healpix= 2**healpixOrder - - healpixID_nest= hp.ring2nest(nside_healpix, healpixID_ring) - bundleID_nest = (healpixID_nest >> shift) - bundleID_ring = hp.nest2ring(nside_bundle, bundleID_nest) - - return bundleID_ring - -class Catalog(CatalogBase): - def __init__(self, config, chip, pointing, chip_output, filt, **kwargs): - super().__init__() - self.cat_dir = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["cat_dir"]) - self.seed_Av = config["catalog_options"]["seed_Av"] - - # (TEST) - self.cosmo = FlatLambdaCDM(H0=67.66, Om0=0.3111) - - self.chip_output = chip_output - self.filt = filt - self.logger = chip_output.logger - - with pkg_resources.path('Catalog.data', 'SLOAN_SDSS.g.fits') as filter_path: - self.normF_star = Table.read(str(filter_path)) - - self.config = config - self.chip = chip - self.pointing = pointing - - self.max_size = 0. - - if "galaxy_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["galaxy_cat"] and config["catalog_options"]["galaxy_yes"]: - self.galaxy_path = os.path.join(self.cat_dir, config["catalog_options"]["input_path"]["galaxy_cat"]) - - self.galaxy_SED_path = os.path.join(self.cat_dir, config["catalog_options"]["SED_templates_path"]["galaxy_SED"]) - self._load_SED_lib_gals() - - if "AGN_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["AGN_cat"] and config["catalog_options"]["galaxy_yes"]: - self.AGN_path = os.path.join(self.cat_dir, config["catalog_options"]["input_path"]["AGN_cat"]) - - self.AGN_SED_path = os.path.join(self.cat_dir, config["catalog_options"]["SED_templates_path"]["AGN_SED"]) - self.AGN_SED_wave_path = os.path.join(self.cat_dir, config["catalog_options"]["SED_templates_path"]["AGN_SED_WAVE"]) - self._load_SED_lib_AGN() - - if "rotateEll" in config["catalog_options"]: - self.rotation = np.radians(float(config["catalog_options"]["rotateEll"])) - else: - self.rotation = 0. - - # Update output .cat header with catalog specific output columns - self._add_output_columns_header() - - self._get_healpix_list() - self._load() - - def _add_output_columns_header(self): - self.add_hdr = " model_tag teff logg feh" - self.add_hdr += " bulgemass diskmass detA e1 e2 kappa g1 g2 size galType veldisp " - - self.add_fmt = " %10s %8.4f %8.4f %8.4f" - self.add_fmt += " %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %4d %8.4f " - self.chip_output.update_output_header(additional_column_names=self.add_hdr) - - 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, - hp.ang2vec(np.radians(90.) - dec, ra), - inclusive=True - ) - # 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 == "galaxy" or obj.type == "quasar": - # return self.normF_galaxy - return None - else: - return None - - def _load_SED_lib_gals(self): - pcs = h5.File(os.path.join(self.galaxy_SED_path, "pcs.h5"), "r") - lamb = h5.File(os.path.join(self.galaxy_SED_path, "lamb.h5"), "r") - self.lamb_gal = lamb['lamb'][()] - self.pcs = pcs['pcs'][()] - - def _load_SED_lib_AGN(self): - from astropy.io import fits - self.SED_AGN = fits.open(self.AGN_SED_path)[0].data - self.lamb_AGN = np.load(self.AGN_SED_wave_path) - - - def _load_gals(self, gals, pix_id=None, cat_id=0): - ngals = len(gals['ra']) - - # Apply astrometric modeling - # in C3 case only aberration - ra_arr = gals['ra'][:] - dec_arr = gals['dec'][:] - 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.utcfromtimestamp(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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - - for igals in range(ngals): - # # (TEST) - # if igals > 100: - # break - # if igals < 3447: - # continue - - param = self.initialize_param() - param['ra'] = ra_arr[igals] - param['dec'] = dec_arr[igals] - param['ra_orig'] = gals['ra'][igals] - param['dec_orig'] = gals['dec'][igals] - param['mag_use_normal'] = gals['mag_csst_%s'%(self.filt.filter_type)][igals] - if self.filt.is_too_dim(mag=param['mag_use_normal'], margin=self.config["obs_setting"]["mag_lim_margin"]): - continue - - # if param['mag_use_normal'] >= 26.5: - # continue - param['z'] = gals['redshift'][igals] - param['model_tag'] = 'None' - param['g1'] = gals['shear'][igals][0] - param['g2'] = gals['shear'][igals][1] - param['kappa'] = gals['kappa'][igals] - param['e1'] = gals['ellipticity_true'][igals][0] - param['e2'] = gals['ellipticity_true'][igals][1] - - # For shape calculation - - param['ell_total'] = np.sqrt(param['e1']**2 + param['e2']**2) - if param['ell_total'] > 0.9: - continue - param['e1_disk'] = param['e1'] - param['e2_disk'] = param['e2'] - param['e1_bulge'] = param['e1'] - param['e2_bulge'] = param['e2'] - - - param['delta_ra'] = 0 - param['delta_dec'] = 0 - - # Masses - param['bulgemass'] = gals['bulgemass'][igals] - param['diskmass'] = gals['diskmass'][igals] - - param['size'] = gals['size'][igals] - if param['size'] > self.max_size: - self.max_size = param['size'] - - # Sizes - param['bfrac'] = param['bulgemass']/(param['bulgemass'] + param['diskmass']) - if param['bfrac'] >= 0.6: - param['hlr_bulge'] = param['size'] - param['hlr_disk'] = param['size'] * (1. - param['bfrac']) - else: - param['hlr_disk'] = param['size'] - param['hlr_bulge'] = param['size'] * param['bfrac'] - - # SED coefficients - param['coeff'] = gals['coeff'][igals] - param['detA'] = gals['detA'][igals] - - # Others - param['galType'] = gals['type'][igals] - param['veldisp'] = gals['veldisp'][igals] - - # TEST no redening and no extinction - param['av'] = 0.0 - param['redden'] = 0 - - param['star'] = 0 # Galaxy - - # NOTE: this cut cannot be put before the SED type has been assigned - if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): - continue - - # TEMP - self.ids += 1 - # param['id'] = self.ids - param['id'] = '%06d'%(int(pix_id)) + '%06d'%(cat_id) + '%08d'%(igals) - - if param['star'] == 0: - obj = Galaxy(param, logger=self.logger) - - # Need to deal with additional output columns - obj.additional_output_str = self.add_fmt%("n", 0., 0., 0., - param['bulgemass'], param['diskmass'], param['detA'], - param['e1'], param['e2'], param['kappa'], param['g1'], param['g2'], param['size'], - param['galType'], param['veldisp']) - - self.objs.append(obj) - - def _load_AGNs(self): - data = Table.read(self.AGN_path) - ra_arr = data['ra'] - dec_arr = data['dec'] - nAGNs = len(data) - if self.config["obs_setting"]["enable_astrometric_model"]: - ra_list = ra_arr.tolist() - dec_list = dec_arr.tolist() - pmra_list = np.zeros(nAGNs).tolist() - pmdec_list = np.zeros(nAGNs).tolist() - rv_list = np.zeros(nAGNs).tolist() - parallax_list = [1e-9] * nAGNs - dt = datetime.utcfromtimestamp(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=nAGNs, - 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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - for iAGNs in range(nAGNs): - param = self.initialize_param() - param['ra'] = ra_arr[iAGNs] - param['dec'] = dec_arr[iAGNs] - param['ra_orig'] = data['ra'][iAGNs] - param['dec_orig'] = data['dec'][iAGNs] - param['z'] = data['z'][iAGNs] - param['appMag'] = data['appMag'][iAGNs] - param['absMag'] = data['absMag'][iAGNs] - - # NOTE: this cut cannot be put before the SED type has been assigned - if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): - continue - - # TEST no redening and no extinction - param['av'] = 0.0 - param['redden'] = 0 - - param['star'] = 2 # Quasar - param['id'] = data['igmlos'][iAGNs] - - if param['star'] == 2: - obj = Quasar(param, logger=self.logger) - - # Append additional output columns to the .cat file - obj.additional_output_str = self.add_fmt%("n", 0., 0., 0., - 0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.) - self.objs.append(obj) - - def _load(self, **kwargs): - self.objs = [] - self.ids = 0 - - if "galaxy_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["galaxy_cat"] and self.config["catalog_options"]["galaxy_yes"]: - # for i in range(76): - # file_path = os.path.join(self.galaxy_path, "galaxies%04d_C6.h5"%(i)) - # gals_cat = h5.File(file_path, 'r')['galaxies'] - # for pix in self.pix_list: - # try: - # gals = gals_cat[str(pix)] - # self._load_gals(gals, pix_id=pix, cat_id=i) - # del gals - # except Exception as e: - # traceback.print_exc() - # self.logger.error(str(e)) - # print(e) - for pix in self.pix_list: - try: - bundleID = get_bundleIndex(pix) - # # (TEST C6): - # if pix != 35421 or bundleID != 523: - # continue - gals_cat = h5.File(self.galaxy_path, 'r')['galaxies'] - gals = gals_cat[str(pix)] - self._load_gals(gals, pix_id=pix, cat_id=bundleID) - del gals - except Exception as e: - traceback.print_exc() - self.logger.error(str(e)) - print(e) - #if "AGN_cat" in self.config["input_path"] and self.config["input_path"]["AGN_cat"] and not self.config["run_option"]["star_only"]: - if "AGN_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["AGN_cat"] and self.config["catalog_options"]["galaxy_yes"]: - try: - self._load_AGNs() - except Exception as e: - traceback.print_exc() - self.logger.error(str(e)) - print(e) - - if self.logger is not None: - self.logger.info("maximum galaxy size: %.4f"%(self.max_size)) - self.logger.info("number of objects in catalog: %d"%(len(self.objs))) - else: - print("number of objects in catalog: ", len(self.objs)) - - # (TEST) - # def convert_mags(self, obj): - # spec = np.matmul(obj.coeff, self.pcs.T) - # lamb = self.lamb_gal * U.angstrom - # unit_sed = ((lamb * lamb)/constants.c*U.erg/U.second/U.cm**2/U.angstrom).to(U.jansky) - # unit_sed = unit_sed.value - # lamb = lamb.value - # lamb *= (1 + obj.z) - # spec *= (1 + obj.z) - # mags = -2.5 * np.log10(unit_sed*spec) + 8.9 - # mags += self.cosmo.distmod(obj.z).value - # return lamb, mags - - - def load_sed(self, obj, **kwargs): - if obj.type == 'galaxy' or obj.type == 'quasar': - # dist_L_pc = (1 + obj.z) * comoving_dist(z=obj.z)[0] - # factor = (10 / dist_L_pc)**2 - factor = 10**(-.4 * self.cosmo.distmod(obj.z).value) - if obj.type == 'galaxy': - flux = np.matmul(self.pcs, obj.coeff) * factor - # if np.any(flux < 0): - # raise ValueError("Glaxy %s: negative SED fluxes"%obj.id) - flux[flux < 0] = 0. - sedcat = np.vstack((self.lamb_gal, flux)).T - sed_data = getObservedSED( - sedCat=sedcat, - redshift=obj.z, - av=obj.param["av"], - redden=obj.param["redden"] - ) - wave, flux = sed_data[0], sed_data[1] - elif obj.type == 'quasar': - # flux = self.SED_AGN[int(obj.id)] * factor * 1e-17 - flux = self.SED_AGN[int(obj.id)] * 1e-17 - # if np.any(flux < 0): - # raise ValueError("Glaxy %s: negative SED fluxes"%obj.id) - flux[flux < 0] = 0. - # sedcat = np.vstack((self.lamb_AGN, flux)).T - wave = self.lamb_AGN - # print("sed (erg/s/cm2/A) = ", sed_data) - # np.savetxt(os.path.join(self.config["work_dir"], "%s_sed.txt"%(obj.id)), sedcat) - else: - raise ValueError("Object type not known") - speci = interpolate.interp1d(wave, flux) - lamb = np.arange(2000, 11001+0.5, 0.5) - y = speci(lamb) - # 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': - # 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) - # if obj.param['mag_use_normal'] >= 30: - # print("obj ID = %d"%obj.id) - # print("mag_use_normal = %.3f"%obj.param['mag_use_normal']) - # print("integrated flux = %.7f"%(interFlux)) - # print("app mag = %.3f"%obj.param['appMag']) - # np.savetxt('./AGN_SED_test/sed_objID_%d.txt'%obj.id, np.transpose([self.lamb_AGN, self.SED_AGN[int(obj.id)]])) - # print("obj ID = %d"%obj.id) - # print("mag_use_normal = %.3f"%obj.param['mag_use_normal']) - # print("integrated flux = %.7f"%(interFlux)) - # print("app mag = %.3f"%obj.param['appMag']) - # print("abs mag = %.3f"%obj.param['absMag']) - # mag = getABMAG(interFlux, self.filt.bandpass_full) - # print("mag diff = %.3f"%(mag - obj.param['mag_use_normal'])) - del wave - del flux - return sed diff --git a/Catalog/testCat_star.py b/Catalog/testCat_star.py deleted file mode 100644 index 458e41cd9756c974204633bf4c1ea454726603c5..0000000000000000000000000000000000000000 --- a/Catalog/testCat_star.py +++ /dev/null @@ -1,378 +0,0 @@ -import os -import galsim -import random -import numpy as np -import h5py as h5 -import healpy as hp -import astropy.constants as cons -import traceback -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, Stamp -from ObservationSim.MockObject._util import tag_sed, getObservedSED, getABMAG, integrate_sed_bandpass, comoving_dist -from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position - -import astropy.io.fits as fitsio -from ObservationSim.MockObject._util import seds, sed_assign, extAv - -# (TEST) -from astropy.cosmology import FlatLambdaCDM -from astropy import constants -from astropy import units as U - -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 Catalog(CatalogBase): - """An user customizable class for reading in catalog(s) of objects and SEDs. - - NOTE: must inherit the "CatalogBase" abstract class - - ... - - Attributes - ---------- - cat_dir : str - a directory that contains the catalog file(s) - star_path : str - path to the star catalog file - star_SED_path : str - path to the star SED data - objs : list - a list of ObservationSim.MockObject (Star, Galaxy, or Quasar) - NOTE: must have "obj" list when implement your own Catalog - - Methods - ---------- - load_sed(obj, **kwargs): - load the corresponding SED data for one object - load_norm_filt(obj): - load the filter throughput for the input catalog's photometric system. - """ - def __init__(self, config, chip, pointing, chip_output, filt, **kwargs): - """Constructor method. - - Parameters - ---------- - config : dict - configuration dictionary which is parsed from the input YAML file - chip: ObservationSim.Instrument.Chip - an ObservationSim.Instrument.Chip instance, can be used to identify the band etc. - pointing: ObservationSim.Config.Pointing - an ObservationSim.Config.Pointing instance, can be used to configure the astrometry module - chip_output: ObservationSim.Config.ChipOutput - an ObservationSim.Config.ChipOutput instance, can be used to setup the output format - filt: ObservationSim.Instrument.Filter - an ObservationSim.Instrument.Filter instance, can be used to identify the filter type - **kwargs : dict - other needed input parameters (in key-value pairs), please modify corresponding - initialization call in "ObservationSim.py" as you need. - - Returns - ---------- - None - """ - - super().__init__() - self.cat_dir = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["cat_dir"]) - self.seed_Av = config["catalog_options"]["seed_Av"] - - #self.cosmo = FlatLambdaCDM(H0=67.66, Om0=0.3111) - - self.chip_output = chip_output - self.filt = filt - self.logger = chip_output.logger - - with pkg_resources.path('Catalog.data', 'SLOAN_SDSS.g.fits') as filter_path: - self.normF_star = Table.read(str(filter_path)) - - self.config = config - self.chip = chip - self.pointing = pointing - - self.max_size = 0. - - if "star_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["star_cat"] and config["catalog_options"]["star_yes"]: - self.star_path = os.path.join(self.cat_dir, config["catalog_options"]["input_path"]["star_cat"]) - - self.star_SED_path = os.path.join(self.cat_dir, config["catalog_options"]["SED_templates_path"]["star_SED"]) - self._load_SED_lib_star() - - - if "rotateEll" in config["catalog_options"]: - self.rotation = float(int(config["catalog_options"]["rotateEll"]/45.)) - else: - self.rotation = 0. - - # Update output .cat header with catalog specific output columns - self._add_output_columns_header() - - self._get_healpix_list() - self._load() - - def _add_output_columns_header(self): - self.add_hdr = " model_tag teff logg feh" - self.add_hdr += " bulgemass diskmass detA e1 e2 kappa g1 g2 size galType veldisp " - - self.add_fmt = " %10s %8.4f %8.4f %8.4f" - self.add_fmt += " %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %4d %8.4f " - self.chip_output.update_output_header(additional_column_names=self.add_hdr) - - 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, - hp.ang2vec(np.radians(90.) - dec, ra), - inclusive=True - ) - # 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): - """Load the corresponding thourghput for the input magnitude "param["mag_use_normal"]". - - NOTE: if the input magnitude is already in CSST magnitude, simply return None - - Parameters - ---------- - obj : ObservationSim.MockObject - the object to get thourghput data for - - Returns - ---------- - norm_filt : Astropy.Table - the throughput Table with two columns (namely, "WAVELENGTH", "SENSITIVITY"): - norm_filt["WAVELENGTH"] : wavelengthes in Angstroms - norm_filt["SENSITIVITY"] : efficiencies - """ - if obj.type == "star": - return self.normF_star - else: - return None - - def _load_SED_lib_star(self): - self.tempSED_star = h5.File(self.star_SED_path,'r') - - 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.utcfromtimestamp(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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - for istars in range(nstars): - # # (TEST) - # if istars > 100: - # break - - 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'] = 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) - - # Append additional output columns to the .cat file - obj.additional_output_str = self.add_fmt%(param["model_tag"], param['teff'], param['logg'], param['feh'], - 0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.) - - self.objs.append(obj) - - def _load(self, **kwargs): - """Read in all objects in from the catalog file(s). - - This is a must implemented method which is used to read in all objects, and - then convert them to ObservationSim.MockObject (Star, Galaxy, or Quasar). - - Currently, - the model of ObservationSim.MockObject.Star class requires: - param["star"] : int - specify the object type: 0: galaxy, 1: star, 2: quasar - param["id"] : int - ID number of the object - param["ra"] : float - Right ascension (in degrees) - param["dec"] : float - Declination (in degrees) - param["mag_use_normal"]: float - the absolute magnitude in a particular filter - NOTE: if that filter is not the corresponding CSST filter, the - load_norm_filt(obj) function must be implemented to load the filter - throughput of that particular photometric system - - the model of ObservationSim.MockObject.Galaxy class requires: - param["star"] : int - specify the object type: 0: galaxy, 1: star, 2: quasar - param["id"] : int - ID number of the object - param["ra"] : float - Right ascension (in degrees) - param["dec"] : float - Declination (in degrees) - param["mag_use_normal"]: float - the absolute magnitude in a particular filter - NOTE: if that filter is not the corresponding CSST filter, the - load_norm_filt(obj) function must be implemented to load the filter - throughput of that particular photometric system - param["bfrac"] : float - the bulge fraction - param["hlr_bulge"] : float - the half-light-radius of the bulge - param["hlr_disk"] : float - the half-light-radius of the disk - param["e1_bulge"], param["e2_bulge"] : float - the ellipticity of the bulge components - param["e1_disk"], param["e2_disk"] : float - the ellipticity of the disk components - (Optional parameters): - param['disk_sersic_idx']: float - Sersic index for galaxy disk component - param['bulge_sersic_idx']: float - Sersic index for galaxy bulge component - param['g1'], param['g2']: float - Reduced weak lensing shear components (valid for shear type: catalog) - the model of ObservationSim.MockObject.Galaxy class requires: - Currently a Quasar is modeled as a point source, just like a Star. - - NOTE: To construct an object, according to its type, just call: - Star(param), Galaxy(param), or Quasar(param) - - NOTE: All constructed objects should be appened to "self.objs". - - NOTE: Any other parameters can also be set within "param" dict: - Used to calculate required quantities and/or SEDs etc. - - Parameters - ---------- - **kwargs : dict - other needed input parameters (in key-value pairs), please modify corresponding - initialization call in "ObservationSim.py" as you need. - - Returns - ---------- - None - """ - 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"]: - if "star_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["star_cat"] and self.config["catalog_options"]["star_yes"]: - star_cat = h5.File(self.star_path, 'r')['stars'] - for pix in self.pix_list: - try: - stars = star_cat[str(pix)] - self._load_stars(stars, pix_id=pix) - del stars - except Exception as e: - self.logger.error(str(e)) - print(e) - - 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)) - - def load_sed(self, obj, **kwargs): - """Load the corresponding SED data for a particular obj. - - Parameters - ---------- - obj : ObservationSim.MockObject - the object to get SED data for - **kwargs : dict - other needed input parameters (in key-value pairs), please modify corresponding - initialization call in "ObservationSim.py" as you need. - - Returns - ---------- - sed : Astropy.Table - the SED Table with two columns (namely, "WAVELENGTH", "FLUX"): - sed["WAVELENGTH"] : wavelength in Angstroms - sed["FLUX"] : fluxes in photons/s/m^2/A - NOTE: the range of wavelengthes must at least cover [2450 - 11000] Angstorms - """ - - 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'] - ) - else: - raise ValueError("Object type not known") - speci = interpolate.interp1d(wave, flux) - lamb = np.arange(2000, 11001+0.5, 0.5) - y = speci(lamb) - # 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')) - - del wave - del flux - return sed diff --git a/Catalog/wcs_test_C6.py b/Catalog/wcs_test_C6.py deleted file mode 100644 index 5623ac23e71c4795dea569959058aa9957a2b042..0000000000000000000000000000000000000000 --- a/Catalog/wcs_test_C6.py +++ /dev/null @@ -1,520 +0,0 @@ -import os -import galsim -import random -import numpy as np -import h5py as h5 -import healpy as hp -import astropy.constants as cons -import traceback -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 tag_sed, getObservedSED, getABMAG, integrate_sed_bandpass, comoving_dist -from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position - -# (TEST) -from astropy.cosmology import FlatLambdaCDM -from astropy import constants -from astropy import units as U - -try: - import importlib.resources as pkg_resources -except ImportError: - # Try backported to PY<37 'importlib_resources' - import importlib_resources as pkg_resources - -NSIDE = 128 - -def get_bundleIndex(healpixID_ring, bundleOrder=4, healpixOrder=7): - assert NSIDE == 2**healpixOrder - shift = healpixOrder - bundleOrder - shift = 2*shift - - nside_bundle = 2**bundleOrder - nside_healpix= 2**healpixOrder - - healpixID_nest= hp.ring2nest(nside_healpix, healpixID_ring) - bundleID_nest = (healpixID_nest >> shift) - bundleID_ring = hp.nest2ring(nside_bundle, bundleID_nest) - - return bundleID_ring - -class Catalog(CatalogBase): - def __init__(self, config, chip, pointing, chip_output, filt, **kwargs): - super().__init__() - self.cat_dir = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["cat_dir"]) - self.seed_Av = config["catalog_options"]["seed_Av"] - - self.cosmo = FlatLambdaCDM(H0=67.66, Om0=0.3111) - - self.chip_output = chip_output - self.filt = filt - self.logger = chip_output.logger - - with pkg_resources.path('Catalog.data', 'SLOAN_SDSS.g.fits') as filter_path: - self.normF_star = Table.read(str(filter_path)) - - self.config = config - self.chip = chip - self.pointing = pointing - - self.max_size = 0. - - if "star_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["star_cat"] and not config["catalog_options"]["galaxy_only"]: - star_file = config["catalog_options"]["input_path"]["star_cat"] - star_SED_file = config["catalog_options"]["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["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["galaxy_cat"] and not config["catalog_options"]["star_only"]: - galaxy_dir = config["catalog_options"]["input_path"]["galaxy_cat"] - self.galaxy_path = os.path.join(self.cat_dir, galaxy_dir) - self.galaxy_SED_path = os.path.join(config["data_dir"], config["catalog_options"]["SED_templates_path"]["galaxy_SED"]) - self._load_SED_lib_gals() - - if "AGN_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["AGN_cat"] and not config["catalog_options"]["star_only"]: - AGN_dir = config["catalog_options"]["input_path"]["AGN_cat"] - self.AGN_path = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["AGN_cat"]) - self.AGN_SED_path = os.path.join(config["data_dir"], config["catalog_options"]["SED_templates_path"]["AGN_SED"]) - self.AGN_SED_wave_path = os.path.join(config['data_dir'], config["catalog_options"]["SED_templates_path"]["AGN_SED_WAVE"]) - self._load_SED_lib_AGN() - - if "rotateEll" in config["catalog_options"]: - self.rotation = np.radians(float(config["catalog_options"]["rotateEll"])) - else: - self.rotation = 0. - - # Update output .cat header with catalog specific output columns - self._add_output_columns_header() - - self._get_healpix_list() - self._load() - - def _add_output_columns_header(self): - self.add_hdr = " model_tag teff logg feh" - self.add_hdr += " bulgemass diskmass detA e1 e2 kappa g1 g2 size galType veldisp " - - self.add_fmt = " %10s %8.4f %8.4f %8.4f" - self.add_fmt += " %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %4d %8.4f " - self.chip_output.update_output_header(additional_column_names=self.add_hdr) - - 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, - hp.ang2vec(np.radians(90.) - dec, ra), - 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 - return None - 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): - pcs = h5.File(os.path.join(self.galaxy_SED_path, "pcs.h5"), "r") - lamb = h5.File(os.path.join(self.galaxy_SED_path, "lamb.h5"), "r") - self.lamb_gal = lamb['lamb'][()] - self.pcs = pcs['pcs'][()] - - def _load_SED_lib_AGN(self): - from astropy.io import fits - self.SED_AGN = fits.open(self.AGN_SED_path)[0].data - self.lamb_AGN = np.load(self.AGN_SED_wave_path) - - - def _load_gals(self, gals, pix_id=None, cat_id=0): - ngals = len(gals['ra']) - - # Apply astrometric modeling - # in C3 case only aberration - ra_arr = gals['ra'][:] - dec_arr = gals['dec'][:] - 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.utcfromtimestamp(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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - - for igals in range(ngals): - # # (TEST) - # if igals > 100: - # break - - param = self.initialize_param() - param['ra'] = ra_arr[igals] - param['dec'] = dec_arr[igals] - param['ra_orig'] = gals['ra'][igals] - param['dec_orig'] = gals['dec'][igals] - param['mag_use_normal'] = gals['mag_csst_%s'%(self.filt.filter_type)][igals] - # param['mag_use_normal'] = 20. - if self.filt.is_too_dim(mag=param['mag_use_normal'], margin=self.config["obs_setting"]["mag_lim_margin"]): - continue - - param['z'] = gals['redshift'][igals] - param['model_tag'] = 'None' - # param['g1'] = gals['shear'][igals][0] - # param['g2'] = gals['shear'][igals][1] - param['g1'] = 0. - param['g2'] = 0. - param['kappa'] = gals['kappa'][igals] - # param['e1'] = gals['ellipticity_true'][igals][0] - # param['e2'] = gals['ellipticity_true'][igals][1] - param['e1'] = 0. - param['e2'] = 0. - - # For shape calculation - - param['ell_total'] = np.sqrt(param['e1']**2 + param['e2']**2) - if param['ell_total'] > 0.9: - continue - param['e1_disk'] = param['e1'] - param['e2_disk'] = param['e2'] - param['e1_bulge'] = param['e1'] - param['e2_bulge'] = param['e2'] - - - param['delta_ra'] = 0 - param['delta_dec'] = 0 - - # Masses - param['bulgemass'] = gals['bulgemass'][igals] - param['diskmass'] = gals['diskmass'][igals] - - param['size'] = gals['size'][igals] - if param['size'] > self.max_size: - self.max_size = param['size'] - - # Sersic index - param['disk_sersic_idx'] = 1. - param['bulge_sersic_idx'] = 4. - - # Sizes - param['bfrac'] = param['bulgemass']/(param['bulgemass'] + param['diskmass']) - if param['bfrac'] >= 0.6: - param['hlr_bulge'] = param['size'] - param['hlr_disk'] = param['size'] * (1. - param['bfrac']) - else: - param['hlr_disk'] = param['size'] - param['hlr_bulge'] = param['size'] * param['bfrac'] - - # SED coefficients - param['coeff'] = gals['coeff'][igals] - param['detA'] = gals['detA'][igals] - - # Others - param['galType'] = gals['type'][igals] - param['veldisp'] = gals['veldisp'][igals] - - # TEST no redening and no extinction - param['av'] = 0.0 - param['redden'] = 0 - - param['star'] = 0 # Galaxy - - # NOTE: this cut cannot be put before the SED type has been assigned - if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): - continue - - # TEMP - self.ids += 1 - # param['id'] = self.ids - param['id'] = '%06d'%(int(pix_id)) + '%06d'%(cat_id) + '%08d'%(igals) - - if param['star'] == 0: - obj = Galaxy(param, logger=self.logger) - - # Need to deal with additional output columns - obj.additional_output_str = self.add_fmt%("n", 0., 0., 0., - param['bulgemass'], param['diskmass'], param['detA'], - param['e1'], param['e2'], param['kappa'], param['g1'], param['g2'], param['size'], - param['galType'], param['veldisp']) - - 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.utcfromtimestamp(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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - for istars in range(nstars): - # # (TEST) - # if istars > 100: - # break - - 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] - param['mag_use_normal'] = 20. - # if param['mag_use_normal'] >= 26.5: - # continue - self.ids += 1 - 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) - - # Append additional output columns to the .cat file - obj.additional_output_str = self.add_fmt%(param["model_tag"], param['teff'], param['logg'], param['feh'], - 0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.) - - self.objs.append(obj) - - def _load_AGNs(self): - data = Table.read(self.AGN_path) - ra_arr = data['ra'] - dec_arr = data['dec'] - nAGNs = len(data) - if self.config["obs_setting"]["enable_astrometric_model"]: - ra_list = ra_arr.tolist() - dec_list = dec_arr.tolist() - pmra_list = np.zeros(nAGNs).tolist() - pmdec_list = np.zeros(nAGNs).tolist() - rv_list = np.zeros(nAGNs).tolist() - parallax_list = [1e-9] * nAGNs - dt = datetime.utcfromtimestamp(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=nAGNs, - 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="J2000", - input_date_str=date_str, - input_time_str=time_str - ) - for iAGNs in range(nAGNs): - param = self.initialize_param() - param['ra'] = ra_arr[iAGNs] - param['dec'] = dec_arr[iAGNs] - param['ra_orig'] = data['ra'][iAGNs] - param['dec_orig'] = data['dec'][iAGNs] - param['z'] = data['z'][iAGNs] - param['appMag'] = data['appMag'][iAGNs] - param['absMag'] = data['absMag'][iAGNs] - - # NOTE: this cut cannot be put before the SED type has been assigned - if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): - continue - - # TEST no redening and no extinction - param['av'] = 0.0 - param['redden'] = 0 - - param['star'] = 2 # Quasar - param['id'] = data['igmlos'][iAGNs] - - if param['star'] == 2: - obj = Quasar(param, logger=self.logger) - - # Append additional output columns to the .cat file - obj.additional_output_str = self.add_fmt%("n", 0., 0., 0., - 0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.) - self.objs.append(obj) - - def _load(self, **kwargs): - self.objs = [] - self.ids = 0 - - if "star_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["star_cat"] and not self.config["catalog_options"]["galaxy_only"]: - star_cat = h5.File(self.star_path, 'r')['catalog'] - for pix in self.pix_list: - try: - stars = star_cat[str(pix)] - self._load_stars(stars, pix_id=pix) - del stars - except Exception as e: - self.logger.error(str(e)) - print(e) - - if "galaxy_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["galaxy_cat"] and not self.config["catalog_options"]["star_only"]: - for pix in self.pix_list: - try: - bundleID = get_bundleIndex(pix) - file_path = os.path.join(self.galaxy_path, "galaxies_C6_bundle{:06}.h5".format(bundleID)) - gals_cat = h5.File(file_path, 'r')['galaxies'] - gals = gals_cat[str(pix)] - self._load_gals(gals, pix_id=pix, cat_id=bundleID) - del gals - except Exception as e: - traceback.print_exc() - self.logger.error(str(e)) - print(e) - - if "AGN_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["AGN_cat"] and not self.config["catalog_options"]["star_only"]: - try: - self._load_AGNs() - except Exception as e: - traceback.print_exc() - self.logger.error(str(e)) - print(e) - - if self.logger is not None: - self.logger.info("maximum galaxy size: %.4f"%(self.max_size)) - self.logger.info("number of objects in catalog: %d"%(len(self.objs))) - else: - print("number of objects in catalog: ", len(self.objs)) - - 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': - factor = 10**(-.4 * self.cosmo.distmod(obj.z).value) - if obj.type == 'galaxy': - flux = np.matmul(self.pcs, obj.coeff) * factor - # if np.any(flux < 0): - # raise ValueError("Glaxy %s: negative SED fluxes"%obj.id) - flux[flux < 0] = 0. - sedcat = np.vstack((self.lamb_gal, flux)).T - sed_data = getObservedSED( - sedCat=sedcat, - redshift=obj.z, - av=obj.param["av"], - redden=obj.param["redden"] - ) - wave, flux = sed_data[0], sed_data[1] - elif obj.type == 'quasar': - flux = self.SED_AGN[int(obj.id)] * 1e-17 - # if np.any(flux < 0): - # raise ValueError("Glaxy %s: negative SED fluxes"%obj.id) - flux[flux < 0] = 0. - # sedcat = np.vstack((self.lamb_AGN, flux)).T - wave = self.lamb_AGN - # print("sed (erg/s/cm2/A) = ", sed_data) - # np.savetxt(os.path.join(self.config["work_dir"], "%s_sed.txt"%(obj.id)), sedcat) - else: - raise ValueError("Object type not known") - speci = interpolate.interp1d(wave, flux) - lamb = np.arange(2000, 11001+0.5, 0.5) - y = speci(lamb) - # 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': - # 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) - # if obj.param['mag_use_normal'] >= 30: - # print("obj ID = %d"%obj.id) - # print("mag_use_normal = %.3f"%obj.param['mag_use_normal']) - # print("integrated flux = %.7f"%(interFlux)) - # print("app mag = %.3f"%obj.param['appMag']) - # np.savetxt('./AGN_SED_test/sed_objID_%d.txt'%obj.id, np.transpose([self.lamb_AGN, self.SED_AGN[int(obj.id)]])) - # print("obj ID = %d"%obj.id) - # print("mag_use_normal = %.3f"%obj.param['mag_use_normal']) - # print("integrated flux = %.7f"%(interFlux)) - # print("app mag = %.3f"%obj.param['appMag']) - # print("abs mag = %.3f"%obj.param['absMag']) - # mag = getABMAG(interFlux, self.filt.bandpass_full) - # print("mag diff = %.3f"%(mag - obj.param['mag_use_normal'])) - del wave - del flux - return sed diff --git a/ObservationSim/Config/Header/ImageHeader_1.py b/ObservationSim/Config/Header/ImageHeader_1.py deleted file mode 100644 index a4fc27088c9815699d58670bf5707dfd763f196d..0000000000000000000000000000000000000000 --- a/ObservationSim/Config/Header/ImageHeader_1.py +++ /dev/null @@ -1,434 +0,0 @@ -""" -generate image header -""" -import numpy as np - -from astropy.io import fits -import astropy.wcs as pywcs - -from scipy import math -import random - -import os -import sys - -def chara2digit(char): - """ Function to judge and convert characters to digitals - - Parameters - ---------- - - """ - - try: - float(char) # for int, long and float - except ValueError: - pass - return char - else: - data = float(char) - return data - - -def read_header_parameter(filename='global_header.param'): - """ Function to read the header parameters - - Parameters - ---------- - - """ - - name = [] - value = [] - description = [] - for line in open(filename): - line = line.strip("\n") - arr = line.split('|') -# csvReader = csv.reader(csvDataFile) -# for arr in csvReader: - name.append(arr[0]) - value.append(chara2digit(arr[1])) - description.append(arr[2]) - -# print(value) - return name, value, description - -def rotate_CD_matrix(cd, pa_aper): - """Rotate CD matrix - - Parameters - ---------- - cd: (2,2) array - CD matrix - - pa_aper: float - Position angle, in degrees E from N, of y axis of the detector - - Returns - ------- - cd_rot: (2,2) array - Rotated CD matrix - - Comments - -------- - `astropy.wcs.WCS.rotateCD` doesn't work for non-square pixels in that it - doesn't preserve the pixel scale! The bug seems to come from the fact - that `rotateCD` assumes a transposed version of its own CD matrix. - - """ - rad = np.deg2rad(-pa_aper) - mat = np.zeros((2,2)) - mat[0,:] = np.array([np.cos(rad),-np.sin(rad)]) - mat[1,:] = np.array([np.sin(rad),np.cos(rad)]) - cd_rot = np.dot(mat, cd) - return cd_rot - - -def Header_extention(xlen = 9232, ylen = 9216, gain = 1.0, readout = 5.0, dark = 0.02,saturation=90000, row_num = 1, col_num = 1): - - """ Creat an image frame for CCST with multiple extensions - - Parameters - ---------- - - """ - - flag_ltm_x = [0,1,-1,1,-1] - flag_ltm_y = [0,1,1,-1,-1] - flag_ltv_x = [0,0,1,0,1] - flag_ltv_y = [0,0,0,1,1] - - detector_size_x = int(xlen) - detector_size_y = int(ylen) - - data_x = str(int(detector_size_x)) - data_y = str(int(detector_size_y)) - - data_sec = '[1:'+data_x+',1:'+data_y+']' - - name = [] - value = [] - description = [] - - for k in range(1,2): - # f = open("extension"+str(k)+"_image.param","w") - j = row_num - i = col_num - ccdnum = str((j-1)*5+i) - name = ['EXTNAME', - 'BSCALE', - 'BZERO', - 'OBSID', - 'CCDNAME', - 'AMPNAME', - 'GAIN', - 'RDNOISE', - 'DARK', - 'SATURATE', - 'RSPEED', - 'CHIPTEMP', - 'CCDCHIP', - 'DATASEC', - 'CCDSUM', - 'NSUM', - 'LTM1_1', - 'LTM2_2', - 'LTV1', - 'LTV2', - 'ATM1_1', - 'ATM2_2', - 'ATV1', - 'ATV2', - 'DTV1', - 'DTV2', - 'DTM1_1', - 'DTM2_2'] - - value = ['IM'+str(k), - 1.0, - 0.0, - 'CSST.20200101T000000', - 'ccd' + ccdnum.rjust(2,'0'), - 'ccd' + ccdnum.rjust(2,'0') + ':'+str(k), - gain, - readout, - dark, - saturation, - 10.0, - -100.0, - 'ccd' + ccdnum.rjust(2,'0'), - data_sec, - '1 1', - '1 1', - flag_ltm_x[k], - flag_ltm_y[k], - flag_ltv_x[k]*(detector_size_x-20*2+1), - flag_ltv_y[k]*(detector_size_y+1), - flag_ltm_x[k], - flag_ltm_y[k], - flag_ltv_x[k]*(detector_size_x-20*2+1), - flag_ltv_y[k]*(detector_size_y+1), - 0, - 0, - 1, - 1] - - description = ['Extension name', - ' ', - ' ', - 'Observation ID', - 'CCD name', - 'Amplifier name', - 'Gain (e-/ADU)', - 'Readout noise (e-/pixel)', - 'Dark noise (e-/pixel/s)', - 'Saturation (e-)', - 'Read speed', - 'Chip temperature', - 'CCD chip ID', - 'Data section', - 'CCD pixel summing', - 'CCD pixel summing', - 'CCD to image transformation', - 'CCD to image transformation', - 'CCD to image transformation', - 'CCD to image transformation', - 'CCD to amplifier transformation', - 'CCD to amplifier transformation', - 'CCD to amplifier transformation', - 'CCD to amplifier transformation', - 'CCD to detector transformatio', - 'CCD to detector transformatio', - 'CCD to detector transformatio', - 'CCD to detector transformatio'] - return name, value, description - - -##9232 9216 898 534 1309 60 -40 -23.4333 -def WCS_def(xlen = 9232, ylen = 9216, gapx = 898.0, gapy1 = 534, gapy2 = 1309, ra = 60, dec = -40, pa = -23.433,psize = 0.074, row_num = 1, col_num = 1): - - """ Creat a wcs frame for CCST with multiple extensions - - Parameters - ---------- - - """ - - flag_x = [0, 1, -1, 1, -1] - flag_y = [0, 1, 1, -1, -1] - flag_ext_x = [0,-1,1,-1,1] - flag_ext_y = [0,-1,-1,1,1] - x_num = 5 - y_num = 6 - detector_num = x_num*y_num - - - detector_size_x = xlen - detector_size_y = ylen - gap_x = gapx - gap_y = [gapy1,gapy2] - ra_ref = ra - dec_ref = dec - - pa_aper = pa - - pixel_size = psize - - gap_y1_num = 3 - gap_y2_num = 2 - - x_center = (detector_size_x*x_num+gap_x*(x_num-1))/2 - y_center = (detector_size_y*y_num+gap_y[0]*gap_y1_num+gap_y[1]*gap_y2_num)/2 - - gap_y_map = np.array([[0,0,0,0,0],[gap_y[0],gap_y[1],gap_y[1],gap_y[1],gap_y[1]],[gap_y[1],gap_y[0],gap_y[0],gap_y[0],gap_y[0]],[gap_y[0],gap_y[0],gap_y[0],gap_y[0],gap_y[0]],[gap_y[0],gap_y[0],gap_y[0],gap_y[0],gap_y[1]],[gap_y[1],gap_y[1],gap_y[1],gap_y[1],gap_y[0]]]) - - - frame_array = np.empty((5,6),dtype=np.float64) - # print(x_center,y_center) - - j = row_num - i = col_num - ccdnum = str((j-1)*5+i) - - x_ref, y_ref = (detector_size_x+gap_x)*i-gap_x-detector_size_x/2, detector_size_y*j + sum(gap_y_map[0:j,i-1]) - detector_size_y/2 - - # print(i,j,x_ref,y_ref,ra_ref,dec_ref) - - name = [] - value = [] - description = [] - - for k in range(1,2): - - cd = np.array([[ pixel_size, 0], [0, pixel_size]])/3600.*flag_x[k] - cd_rot = rotate_CD_matrix(cd, pa_aper) - - # f = open("CCD"+ccdnum.rjust(2,'0')+"_extension"+str(k)+"_wcs.param","w") - - name = ['EQUINOX', - 'WCSDIM', - 'CTYPE1', - 'CTYPE2', - 'CRVAL1', - 'CRVAL2', - 'CRPIX1', - 'CRPIX2', - 'CD1_1', - 'CD1_2', - 'CD2_1', - 'CD2_2'] - value = [2000.0, - 2.0, - 'RA---TAN', - 'DEC--TAN', - ra_ref, - dec_ref, - flag_ext_x[k]*((x_ref+flag_ext_x[k]*detector_size_x/2)-x_center), - flag_ext_y[k]*((y_ref+flag_ext_y[k]*detector_size_y/2)-y_center), - cd_rot[0,0], - cd_rot[0,1], - cd_rot[1,0], - cd_rot[1,1]] - description = ['Equinox of WCS', - 'WCS Dimensionality', - 'Coordinate type', - 'Coordinate typ', - 'Coordinate reference value', - 'Coordinate reference value', - 'Coordinate reference pixel', - 'Coordinate reference pixel', - 'Coordinate matrix', - 'Coordinate matrix', - 'Coordinate matrix', - 'Coordinate matrix'] - - return name, value, description - - - -def generatePrimaryHeader(xlen = 9232, ylen = 9216,pointNum = '1', ra = 60, dec = -40, psize = 0.074, row_num = 1, col_num = 1): - - # array_size1, array_size2, flux, sigma = int(argv[1]), int(argv[2]), 1000.0, 5.0 - filerParm_fn = os.path.split(os.path.realpath(__file__))[0] + '/filter.lst' - f = open(filerParm_fn) - s = f.readline() - s = s.strip("\n") - filter = s.split(' ') - - k = (row_num-1)*5+col_num - ccdnum = str(k) - - g_header_fn = os.path.split(os.path.realpath(__file__))[0] + '/global_header.param' - name, value, description = read_header_parameter(g_header_fn) - - h_prim = fits.Header() - - date = '200930' - time_obs = '120000' - - for i in range(len(name)): - if(name[i]=='FILTER'): - value[i] = filter[k-1] - - if(name[i]=='FILENAME'): - value[i] = 'CSST_' + date + '_' +time_obs + '_' + pointNum.rjust(6,'0') + '_' +ccdnum.rjust(2,'0')+'_raw' - - if(name[i]=='DETSIZE'): - value[i] = '[1:' + str(int(xlen)) + ',1:'+ str(int(ylen)) + ']' - - if(name[i]=='PIXSCAL1'): - value[i] = str(psize) - - if(name[i]=='PIXSCAL2'): - value[i] = str(psize) - - - h_prim[name[i]] = (value[i],description[i]) - - h_prim.add_comment('==================================================================',after='FILETYPE') - h_prim.add_comment('Target information') - h_prim.add_comment('==================================================================') - - h_prim.add_comment('==================================================================',after='EQUINOX') - h_prim.add_comment('Exposure information') - h_prim.add_comment('==================================================================') - - h_prim.add_comment('==================================================================',after='MJDEND') - h_prim.add_comment('Telescope information') - h_prim.add_comment('==================================================================') - - h_prim.add_comment('==================================================================',after='REFFRAME') - h_prim.add_comment('Detector information') - h_prim.add_comment('==================================================================') - - h_prim.add_comment('==================================================================',after='FILTER') - h_prim.add_comment('Other information') - h_prim.add_comment('==================================================================') - - return h_prim - -def generateExtensionHeader(xlen = 9232, ylen = 9216,ra = 60, dec = -40, pa = -23.433, gain = 1.0, readout = 5.0, dark = 0.02, saturation=90000, psize = 0.074, row_num = 1, col_num = 1): - - h_ext = fits.Header() - - for i in range(1,2): - - # NAXIS1:Number of pixels per row; NAXIS2:Number of rows - h_ext['NAXIS1'] = xlen - h_ext['NAXIS2'] = ylen - name, value, description = Header_extention(xlen = xlen, ylen = ylen, gain = gain, readout = readout, dark = dark, saturation=saturation, row_num = row_num, col_num = col_num) - - for j in range(len(name)): - h_ext[name[j]] = (value[j],description[j]) - - name, value, description = WCS_def(xlen = xlen, ylen = ylen, gapx = 898.0, gapy1 = 534, gapy2 = 1309, ra = ra, dec = dec, pa = pa ,psize = psize, row_num = row_num, col_num = col_num) - - for j in range(len(name)): - h_ext[name[j]] = (value[j],description[j]) - - h_ext.add_comment('==================================================================',after='OBSID') - h_ext.add_comment('Readout information') - h_ext.add_comment('==================================================================') - - h_ext.add_comment('==================================================================',after='CHIPTEMP') - h_ext.add_comment('Chip information') - h_ext.add_comment('==================================================================') - - h_ext.add_comment('==================================================================',after='DTM2_2') - h_ext.add_comment('WCS information') - h_ext.add_comment('==================================================================') - - return h_ext - - - -def main(argv): - - xlen = int(argv[1]) - ylen = int(argv[2]) - pointingNum = argv[3] - ra = float(argv[4]) - dec = float(argv[5]) - pSize = float(argv[6]) - ccd_row_num = int(argv[7]) - ccd_col_num = int(argv[8]) - pa_aper = float(argv[9]) - gain = float(argv[10]) - readout = float(argv[11]) - dark = float(argv[12]) - fw = float(argv[13]) - - - - h_prim = generatePrimaryHeader(xlen = xlen, ylen = ylen,ra = ra, dec = dec, psize = pSize, row_num = ccd_row_num, col_num = ccd_col_num, pointNum = pointingNum) - - h_ext = generateExtensionHeader(xlen = xlen, ylen = ylen,ra = ra, dec = dec, pa = pa_aper, gain = gain, readout = readout, dark = dark, saturation=fw, psize = pSize, row_num = ccd_row_num, col_num = ccd_col_num) - hdu1 = fits.PrimaryHDU(header=h_prim) - hdu2 = fits.ImageHDU(np.zeros([ylen,xlen]),header = h_ext) - - hdul = fits.HDUList([hdu1,hdu2]) - - hdul.writeto(h_prim['FILENAME']+'.fits',output_verify='ignore') - -# if __name__ == "__main__": -# main(sys.argv) diff --git a/ObservationSim/Config/_util.py b/ObservationSim/Config/_util.py deleted file mode 100644 index 7e49dee6110de0c4683f772d4ca0226cf6200dd8..0000000000000000000000000000000000000000 --- a/ObservationSim/Config/_util.py +++ /dev/null @@ -1,16 +0,0 @@ - -def get_obs_id(img_type='SCI', project_cycle=6, run_counter=0, pointing_id='00000001',pointing_type_code='101'): - # obs_type = {'SCI': '01', 'BIAS': '03', 'DARK': '07', 'FLAT': '11', 'CRS': '98', 'CRD': '99'} - # obs_type = {'SCIE': '01', 'BIAS': '03', 'DARK': '07', 'FLAT': '11', 'CRS': '98', 'CRD': '99', 'CAL': '01'} - obs_id = pointing_type_code + str(int(project_cycle)).rjust(2, '0') + str(int(run_counter)) + pointing_id - return obs_id - -# def get_obs_id(img_type='SCI', project_cycle=6, run_counter=0, pointing_num=0): -# # obs_type = {'SCI': '01', 'BIAS': '03', 'DARK': '07', 'FLAT': '11', 'CRS': '98', 'CRD': '99'} -# obs_type = {'SCIE': '01', 'BIAS': '03', 'DARK': '07', 'FLAT': '11', 'CRS': '98', 'CRD': '99', 'CAL': '01'} -# obs_id = '1'+ obs_type[img_type] + str(int(project_cycle)).rjust(2, '0') + str(int(run_counter)) + str(pointing_num).rjust(8,'0') -# return obs_id - -def get_file_type(img_type='SCI'): - file_type = {'SCI':'SCI', 'BIAS':'BIAS', 'DARK':'DARK', 'FLAT':'FLAT', 'CRS':'CRS', 'CRD':'CRD','CALS':'CALS','CALF':'CALF'} - return file_type[img_type] \ No newline at end of file diff --git a/ObservationSim/Instrument/Chip/Chip.py b/ObservationSim/Instrument/Chip/Chip.py deleted file mode 100755 index 03532ee6b7e022b00023f589de31459bbf66cd6d..0000000000000000000000000000000000000000 --- a/ObservationSim/Instrument/Chip/Chip.py +++ /dev/null @@ -1,1053 +0,0 @@ -import galsim -import os -import numpy as np -import pickle -import json -import ObservationSim.Instrument._util as _util -from astropy.table import Table -from numpy.random import Generator, PCG64 -from astropy.io import fits -from datetime import datetime - -from ObservationSim.Instrument.Chip import Effects as effects -from ObservationSim.Instrument.FocalPlane import FocalPlane -from ObservationSim.Config.Header import generatePrimaryHeader, generateExtensionHeader -from ObservationSim.Instrument._util import rotate_conterclockwise -from ObservationSim.Instrument.Chip import ChipUtils as chip_utils - -from ObservationSim.Instrument.Chip.libCTI.CTI_modeling import CTI_sim - -try: - import importlib.resources as pkg_resources -except ImportError: - # Try backported to PY<37 'importlib_resources' - import importlib_resources as pkg_resources - - -class Chip(FocalPlane): - def __init__(self, chipID, ccdEffCurve_dir=None, CRdata_dir=None, sls_dir=None, config=None, treering_func=None, logger=None): - # Get focal plane (instance of paraent class) info - super().__init__() - self.nsecy = 2 - self.nsecx = 8 - self.gain_channel = np.ones(self.nsecy * self.nsecx) - self._set_attributes_from_config(config) - - self.logger = logger - - # A chip ID must be assigned - self.chipID = int(chipID) - self.chip_name = str(chipID).rjust(2, '0') - - # Get corresponding filter info - self.filter_id, self.filter_type = self.getChipFilter() - self.survey_type = self._getSurveyType() - - if self.filter_type != "FGS": - self._getChipRowCol() - - # Set the relavent specs for detectors - try: - with pkg_resources.files('ObservationSim.Instrument.data.ccd').joinpath("chip_definition.json") as chip_definition: - with open(chip_definition, "r") as f: - chip_dict = json.load(f)[str(self.chipID)] - except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data.ccd', "chip_definition.json") as chip_definition: - with open(chip_definition, "r") as f: - chip_dict = json.load(f)[str(self.chipID)] - for key in chip_dict: - setattr(self, key, chip_dict[key]) - - self.fdModel = None - if self.filter_type == "FGS": - fgs_name = self.chip_name[0:4] - try: - with pkg_resources.files('ObservationSim.Instrument.data.field_distortion').joinpath("FieldDistModelGlobal_pr4_%s.pickle" % (fgs_name.lower())) as field_distortion: - with open(field_distortion, "rb") as f: - self.fdModel = pickle.load(f) - except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data.field_distortion', "FieldDistModelGlobal_pr4_%s.pickle" % (fgs_name.lower())) as field_distortion: - with open(field_distortion, "rb") as f: - self.fdModel = pickle.load(f) - else: - # Get the corresponding field distortion model - try: - with pkg_resources.files('ObservationSim.Instrument.data.field_distortion').joinpath("FieldDistModel_v2.0.pickle") as field_distortion: - with open(field_distortion, "rb") as f: - self.fdModel = pickle.load(f) - except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data.field_distortion', "FieldDistModelGlobal_mainFP_v1.0.pickle") as field_distortion: - with open(field_distortion, "rb") as f: - self.fdModel = pickle.load(f) - - # Get boundary (in pix) - self.bound = self.getChipLim() - - self.ccdEffCurve_dir = ccdEffCurve_dir - self.CRdata_dir = CRdata_dir - - slsconfs = chip_utils.getChipSLSConf(chipID=self.chipID) - if np.size(slsconfs) == 1: - try: - with pkg_resources.files('ObservationSim.Instrument.data.sls_conf').joinpath(slsconfs) as conf_path: - self.sls_conf = str(conf_path) - except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data.sls_conf', slsconfs) as conf_path: - self.sls_conf = str(conf_path) - else: - # self.sls_conf = [os.path.join(self.sls_dir, slsconfs[0]), os.path.join(self.sls_dir, slsconfs[1])] - self.sls_conf = [] - try: - with pkg_resources.files('ObservationSim.Instrument.data.sls_conf').joinpath(slsconfs[0]) as conf_path: - self.sls_conf.append(str(conf_path)) - except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data.sls_conf', slsconfs[0]) as conf_path: - self.sls_conf.append(str(conf_path)) - try: - with pkg_resources.files('ObservationSim.Instrument.data.sls_conf').joinpath(slsconfs[1]) as conf_path: - self.sls_conf.append(str(conf_path)) - except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data.sls_conf', slsconfs[1]) as conf_path: - self.sls_conf.append(str(conf_path)) - - self.effCurve = self._getChipEffCurve(self.filter_type) - self._getCRdata() - - # # Define the sensor model - self.sensor = galsim.Sensor() - - self.flat_cube = None # for spectroscopic flat field cube simulation - - def _set_attributes_from_config(self, config): - # Default setting - self.read_noise = 5.0 # e/pix - self.dark_noise = 0.02 # e/pix/s - self.rotate_angle = 0. - self.overscan = 1000 - # Override default values - # for key in ["gain", "bias_level, dark_exptime", "flat_exptime", "readout_time", "full_well", "read_noise", "dark_noise", "overscan"]: - # if key in config["ins_effects"]: - # setattr(self, key, config["ins_effects"][key]) - - def _getChipRowCol(self): - self.rowID, self.colID = self.getChipRowCol(self.chipID) - - def getChipRowCol(self, chipID): - rowID = ((chipID - 1) % 5) + 1 - colID = 6 - ((chipID - 1) // 5) - return rowID, colID - - def _getSurveyType(self): - if self.filter_type in _util.SPEC_FILTERS: - return "spectroscopic" - elif self.filter_type in _util.PHOT_FILTERS: - return "photometric" - # elif self.filter_type in ["FGS"]: - # return "FGS" - - def _getChipEffCurve(self, filter_type): - # CCD efficiency curves - if filter_type in ['NUV', 'u', 'GU']: - filename = 'UV0.txt' - if filter_type in ['g', 'r', 'GV', 'FGS']: - # TODO, need to switch to the right efficiency curvey for FGS CMOS - filename = 'Astro_MB.txt' - if filter_type in ['i', 'z', 'y', 'GI']: - filename = 'Basic_NIR.txt' - try: - with pkg_resources.files('ObservationSim.Instrument.data.ccd').joinpath(filename) as ccd_path: - table = Table.read(ccd_path, format='ascii') - except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data.ccd', filename) as ccd_path: - table = Table.read(ccd_path, format='ascii') - throughput = galsim.LookupTable( - x=table['col1'], f=table['col2'], interpolant='linear') - bandpass = galsim.Bandpass(throughput, wave_type='nm') - return bandpass - - def _getCRdata(self): - try: - with pkg_resources.files('ObservationSim.Instrument.data').joinpath("wfc-cr-attachpixel.dat") as cr_path: - self.attachedSizes = np.loadtxt(cr_path) - except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data', "wfc-cr-attachpixel.dat") as cr_path: - self.attachedSizes = np.loadtxt(cr_path) - - # def loadSLSFLATCUBE(self, flat_fn='flat_cube.fits'): - # try: - # with pkg_resources.files('ObservationSim.Instrument.data').joinpath(flat_fn) as data_path: - # flat_fits = fits.open(data_path, ignore_missing_simple=True) - # except AttributeError: - # with pkg_resources.path('ObservationSim.Instrument.data', flat_fn) as data_path: - # flat_fits = fits.open(data_path, ignore_missing_simple=True) - - # fl = len(flat_fits) - # fl_sh = flat_fits[0].data.shape - # assert fl == 4, 'FLAT Field Cube is Not 4 layess!!!!!!!' - # self.flat_cube = np.zeros([fl, fl_sh[0], fl_sh[1]]) - # for i in np.arange(0, fl, 1): - # self.flat_cube[i] = flat_fits[i].data - - def getChipFilter(self, chipID=None): - """Return the filter index and type for a given chip #(chipID) - """ - filter_type_list = _util.ALL_FILTERS - if chipID == None: - chipID = self.chipID - - # updated configurations - if chipID > 42 or chipID < 1: - raise ValueError("!!! Chip ID: [1,42]") - if chipID in [6, 15, 16, 25]: - filter_type = "y" - if chipID in [11, 20]: - filter_type = "z" - if chipID in [7, 24]: - filter_type = "i" - if chipID in [14, 17]: - filter_type = "u" - if chipID in [9, 22]: - filter_type = "r" - if chipID in [12, 13, 18, 19]: - filter_type = "NUV" - if chipID in [8, 23]: - filter_type = "g" - if chipID in [1, 10, 21, 30]: - filter_type = "GI" - if chipID in [2, 5, 26, 29]: - filter_type = "GV" - if chipID in [3, 4, 27, 28]: - filter_type = "GU" - if chipID in range(31, 43): - filter_type = 'FGS' - filter_id = filter_type_list.index(filter_type) - - return filter_id, filter_type - - def getChipLim(self, chipID=None): - """Calculate the edges in pixel for a given CCD chip on the focal plane - NOTE: There are 5*4 CCD chips in the focus plane for photometric / spectroscopic observation. - Parameters: - chipID: int - the index of the chip - Returns: - A galsim BoundsD object - """ - xmin, xmax, ymin, ymax = 1e10, -1e10, 1e10, -1e10 - xcen = self.x_cen / self.pix_size - ycen = self.y_cen / self.pix_size - sign_x = [-1., 1., -1., 1.] - sign_y = [-1., -1., 1., 1.] - for i in range(4): - x = xcen + sign_x[i] * self.npix_x / 2. - y = ycen + sign_y[i] * self.npix_y / 2. - x, y = _util.rotate_conterclockwise( - x0=xcen, y0=ycen, x=x, y=y, angle=self.rotate_angle) - xmin, xmax = min(xmin, x), max(xmax, x) - ymin, ymax = min(ymin, y), max(ymax, y) - return galsim.BoundsD(xmin, xmax, ymin, ymax) - - def getSkyCoverage(self, wcs): - # print("In getSkyCoverage: xmin = %.3f, xmax = %.3f, ymin = %.3f, ymax = %.3f"%(self.bound.xmin, self.bound.xmax, self.bound.ymin, self.bound.ymax)) - return super().getSkyCoverage(wcs, self.bound.xmin, self.bound.xmax, self.bound.ymin, self.bound.ymax) - - def getSkyCoverageEnlarged(self, wcs, margin=0.5): - """The enlarged sky coverage of the chip - """ - margin /= 60.0 - bound = self.getSkyCoverage(wcs) - return galsim.BoundsD(bound.xmin - margin, bound.xmax + margin, bound.ymin - margin, bound.ymax + margin) - - def isContainObj(self, ra_obj=None, dec_obj=None, x_image=None, y_image=None, wcs=None, margin=1): - # magin in number of pix - if (ra_obj is not None) and (dec_obj is not None): - if wcs is None: - wcs = self.img.wcs - pos_obj = wcs.toImage(galsim.CelestialCoord( - ra=ra_obj*galsim.degrees, dec=dec_obj*galsim.degrees)) - x_image, y_image = pos_obj.x, pos_obj.y - elif (x_image is None) or (y_image is None): - raise ValueError( - "Either (ra_obj, dec_obj) or (x_image, y_image) should be given") - - xmin, xmax = self.bound.xmin - margin, self.bound.xmax + margin - ymin, ymax = self.bound.ymin - margin, self.bound.ymax + margin - if (x_image - xmin) * (x_image - xmax) > 0.0 or (y_image - ymin) * (y_image - ymax) > 0.0: - return False - return True - - def getChipNoise(self, exptime=150.0): - noise = self.dark_noise * exptime + self.read_noise**2 - return noise - - # def addEffects(self, config, img, chip_output, filt, ra_cen, dec_cen, img_rot, exptime=150., pointing_ID=0, timestamp_obs=1621915200, pointing_type='SCI', sky_map=None, post_flash_map=None, tel=None, logger=None): - # # Set random seeds - # SeedGainNonuni = int(config["random_seeds"]["seed_gainNonUniform"]) - # SeedBiasNonuni = int(config["random_seeds"]["seed_biasNonUniform"]) - # SeedRnNonuni = int(config["random_seeds"]["seed_rnNonUniform"]) - # SeedBadColumns = int(config["random_seeds"]["seed_badcolumns"]) - # SeedDefective = int(config["random_seeds"]["seed_defective"]) - # SeedCosmicRay = int(config["random_seeds"]["seed_CR"]) - # fullwell = int(self.full_well) - # if config["ins_effects"]["add_hotpixels"] == True: - # BoolHotPix = True - # else: - # BoolHotPix = False - # if config["ins_effects"]["add_deadpixels"] == True: - # BoolDeadPix = True - # else: - # BoolDeadPix = False - # self.logger = logger - - # # Get Poisson noise generator - # rng_poisson, poisson_noise = chip_utils.get_poisson( - # seed=int(config["random_seeds"]["seed_poisson"]) + pointing_ID*30 + self.chipID, sky_level=0.) - - # # Add sky background - # if config["ins_effects"]["add_back"] == True: - # img, sky_map = chip_utils.add_sky_background( - # img=img, filt=filt, exptime=exptime, sky_map=sky_map, tel=tel) - # del sky_map - - # # Apply flat-field large scale structure for one chip - # if config["ins_effects"]["flat_fielding"] == True: - # chip_utils.log_info( - # msg=" Creating and applying Flat-Fielding", logger=self.logger) - # chip_utils.log_info(msg=str(img.bounds), logger=self.logger) - # flat_img, flat_normal = chip_utils.get_flat( - # img=img, seed=int(config["random_seeds"]["seed_flat"])) - # if self.survey_type == "photometric": - # img *= flat_normal - # del flat_normal - # if config["output_setting"]["flat_output"] == False: - # del flat_img - - # if post_flash_map is not None: - # img = img + post_flash_map - - # # Apply Shutter-effect for one chip - # if config["ins_effects"]["shutter_effect"] == True: - # chip_utils.log_info( - # msg=" Apply shutter effect", logger=self.logger) - # # shutter effect normalized image for this chip - # shuttimg = effects.ShutterEffectArr( - # img, t_shutter=1.3, dist_bearing=735, dt=1E-3) - # if self.survey_type == "photometric": - # img *= shuttimg - # # output 16-bit shutter effect image with pixel value <=65535 - # if config["output_setting"]["shutter_output"] == True: - # shutt_gsimg = galsim.ImageUS(shuttimg*6E4) - # shutt_gsimg.write("%s/ShutterEffect_%s_1.fits" % - # (chip_output.subdir, self.chipID)) - # del shutt_gsimg - # del shuttimg - # # # Add Poisson noise to the resulting images - # # # (NOTE): this can only applied to the slitless image - # # # since it dose not use photon shooting to draw stamps - # # if self.survey_type == "spectroscopic": - # # img.addNoise(poisson_noise) - - # # Add cosmic-rays - # if config["ins_effects"]["cosmic_ray"] == True and pointing_type == 'SCI': - # chip_utils.log_info(msg=" Adding Cosmic-Ray", logger=self.logger) - # img, crmap_gsimg, cr_event_num = chip_utils.add_cosmic_rays(img=img, chip=self, exptime=exptime, - # seed=SeedCosmicRay+pointing_ID*30+self.chipID) - # chip_utils.outputCal( - # chip=self, - # img=crmap_gsimg, - # ra_cen=ra_cen, - # dec_cen=dec_cen, - # img_rot=img_rot, - # im_type='CRS', - # pointing_ID=pointing_ID, - # output_dir=chip_output.subdir, - # exptime=exptime, - # project_cycle=config["project_cycle"], - # run_counter=config["run_counter"], - # timestamp=timestamp_obs) - # del crmap_gsimg - - # # Apply PRNU effect and output PRNU flat file: - # if config["ins_effects"]["prnu_effect"] == True: - # chip_utils.log_info( - # msg=" Applying PRNU effect", logger=self.logger) - # img, prnu_img = chip_utils.add_PRNU(img=img, chip=self, - # seed=int(config["random_seeds"]["seed_prnu"]+self.chipID)) - # if config["output_setting"]["prnu_output"] == True: - # prnu_img.write("%s/FlatImg_PRNU_%s.fits" % - # (chip_output.subdir, self.chipID)) - # if config["output_setting"]["flat_output"] == False: - # del prnu_img - - # # # Add dark current - # # if config["ins_effects"]["add_dark"] == True: - # # dark_noise = galsim.DeviateNoise(galsim.PoissonDeviate(rng_poisson, self.dark_noise*(exptime+0.5*self.readout_time))) - # # img.addNoise(dark_noise) - - # # Add dark current & Poisson noise - # InputDark = False - # if config["ins_effects"]["add_dark"] == True: - # if InputDark: - # img = chip_utils.add_inputdark( - # img=img, chip=self, exptime=exptime) - # else: - # img, _ = chip_utils.add_poisson( - # img=img, chip=self, exptime=exptime, poisson_noise=poisson_noise) - # else: - # img, _ = chip_utils.add_poisson( - # img=img, chip=self, exptime=exptime, poisson_noise=poisson_noise, dark_noise=0.) - - # # Add diffusion & brighter-fatter effects - # if config["ins_effects"]["bright_fatter"] == True: - # img = chip_utils.add_brighter_fatter(img=img) - - # # Add Hot Pixels or/and Dead Pixels - # rgbadpix = Generator(PCG64(int(SeedDefective+self.chipID))) - # badfraction = 5E-5*(rgbadpix.random()*0.5+0.7) - # img = effects.DefectivePixels(img, IfHotPix=BoolHotPix, IfDeadPix=BoolDeadPix, - # fraction=badfraction, seed=SeedDefective+self.chipID, biaslevel=0) - - # # Apply Bad lines - # if config["ins_effects"]["add_badcolumns"] == True: - # img = effects.BadColumns( - # img, seed=SeedBadColumns, chipid=self.chipID, logger=self.logger) - - # # Apply Nonlinearity on the chip image - # if config["ins_effects"]["non_linear"] == True: - # chip_utils.log_info( - # msg=" Applying Non-Linearity on the chip image", logger=self.logger) - # img = effects.NonLinearity(GSImage=img, beta1=5.e-7, beta2=0) - - # # Apply CCD Saturation & Blooming - # if config["ins_effects"]["saturbloom"] == True: - # chip_utils.log_info( - # msg=" Applying CCD Saturation & Blooming", logger=self.logger) - # img = effects.SaturBloom( - # GSImage=img, nsect_x=1, nsect_y=1, fullwell=fullwell) - - # # Apply CTE Effect - # # if config["ins_effects"]["cte_trail"] == True: - # # chip_utils.log_info(msg=" Apply CTE Effect", logger=self.logger) - # # img = effects.CTE_Effect(GSImage=img, threshold=27) - - # pre1 = self.prescan_x # 27 - # over1 = self.overscan_x # 71 - # pre2 = self.prescan_y # 0 #4 - # over2 = self.overscan_y # 84 #80 - - # if config["ins_effects"]["cte_trail"] == True: - # chip_utils.log_info(msg=" Apply CTE Effect", logger=self.logger) - # # img = effects.CTE_Effect(GSImage=img, threshold=27) - # # CTI_modeling - # # 2*8 -> 1*16 img-layout - # img = chip_utils.formatOutput(GSImage=img) - # self.nsecy = 1 - # self.nsecx = 16 - - # img_arr = img.array - # ny, nx = img_arr.shape - # dx = int(nx/self.nsecx) - # dy = int(ny/self.nsecy) - # newimg = galsim.Image(nx, int(ny+over2), init_value=0) - # for ichannel in range(16): - # print('\n***add CTI effects: pointing-{:} chip-{:} channel-{:}***'.format( - # pointing_ID, self.chipID, ichannel+1)) - # # nx,ny,noverscan,nsp,nmax = 4608,4616,84,3,10 - # noverscan, nsp, nmax = over2, 3, 10 - # beta, w, c = 0.478, 84700, 0 - # t = np.array([0.74, 7.7, 37], dtype=np.float32) - # rho_trap = np.array([0.6, 1.6, 1.4], dtype=np.float32) - # trap_seeds = np.array( - # [0, 1000, 10000], dtype=np.int32) + ichannel + self.chipID*16 - # release_seed = 50 + ichannel + pointing_ID*30 + self.chipID*16 - # newimg.array[:, 0+ichannel*dx:dx+ichannel*dx] = CTI_sim( - # img_arr[:, 0+ichannel*dx:dx+ichannel*dx], dx, dy, noverscan, nsp, nmax, beta, w, c, t, rho_trap, trap_seeds, release_seed) - # newimg.wcs = img.wcs - # del img - # img = newimg - - # # 1*16 -> 2*8 img-layout - # img = chip_utils.formatRevert(GSImage=img) - # self.nsecy = 2 - # self.nsecx = 8 - - # # prescan & overscan - # if config["ins_effects"]["add_prescan"] == True: - # chip_utils.log_info( - # msg=" Apply pre/over-scan", logger=self.logger) - # if config["ins_effects"]["cte_trail"] == False: - # img = chip_utils.AddPreScan( - # GSImage=img, pre1=pre1, pre2=pre2, over1=over1, over2=over2) - # if config["ins_effects"]["cte_trail"] == True: - # img = chip_utils.AddPreScan( - # GSImage=img, pre1=pre1, pre2=pre2, over1=over1, over2=0) - - # # 1*16 output - # if config["ins_effects"]["format_output"] == True: - # chip_utils.log_info(msg=" Apply 1*16 format", logger=self.logger) - # img = chip_utils.formatOutput(GSImage=img) - # self.nsecy = 1 - # self.nsecx = 16 - - # # Add Bias level - # if config["ins_effects"]["add_bias"] == True: - # chip_utils.log_info( - # msg=" Adding Bias level and 16-channel non-uniformity", logger=self.logger) - # if config["ins_effects"]["bias_16channel"] == True: - # img = effects.AddBiasNonUniform16(img, - # bias_level=float( - # self.bias_level), - # nsecy=self.nsecy, nsecx=self.nsecx, - # seed=SeedBiasNonuni+self.chipID, - # logger=self.logger) - # elif config["ins_effects"]["bias_16channel"] == False: - # img += self.bias_level - - # # Add Read-out Noise - # if config["ins_effects"]["add_readout"] == True: - # seed = int(config["random_seeds"]["seed_readout"] - # ) + pointing_ID*30 + self.chipID - # rng_readout = galsim.BaseDeviate(seed) - # readout_noise = galsim.GaussianNoise( - # rng=rng_readout, sigma=self.read_noise) - # img.addNoise(readout_noise) - - # # Apply Gain & Quantization - # chip_utils.log_info( - # msg=" Applying Gain (and 16 channel non-uniformity) & Quantization", logger=self.logger) - # if config["ins_effects"]["gain_16channel"] == True: - # img, self.gain_channel = effects.ApplyGainNonUniform16( - # img, gain=self.gain, - # nsecy=self.nsecy, nsecx=self.nsecx, - # seed=SeedGainNonuni+self.chipID, - # logger=self.logger) - # elif config["ins_effects"]["gain_16channel"] == False: - # img /= self.gain - - # img.array[img.array > 65535] = 65535 - # img.replaceNegative(replace_value=0) - # img.quantize() - - # ###################################################################################### - # # Output images for calibration pointing - # ###################################################################################### - # # Bias output - # if config["ins_effects"]["add_bias"] == True and config["output_setting"]["bias_output"] == True and pointing_type == 'CAL': - # if self.logger is not None: - # self.logger.info(" Output N frame Bias files") - # else: - # print(" Output N frame Bias files", flush=True) - # NBias = int(config["output_setting"]["NBias"]) - # for i in range(NBias): - # # BiasCombImg, BiasTag = effects.MakeBiasNcomb( - # # self.npix_x, self.npix_y, - # # bias_level=float(self.bias_level), - # # ncombine=1, read_noise=self.read_noise, gain=1, - # # seed=SeedBiasNonuni+self.chipID, - # # logger=self.logger) - # BiasCombImg = galsim.Image( - # self.npix_x, self.npix_y, init_value=0) - # if config["ins_effects"]["add_bias"] == True: - # biaslevel = self.bias_level - # overscan = biaslevel-2 - # elif config["ins_effects"]["add_bias"] == False: - # biaslevel = 0 - # overscan = 0 - - # # Readout noise for Biases is not generated with random seeds. So readout noise for bias images can't be reproduced. - # if config["ins_effects"]["cosmic_ray"] == True: - # if config["ins_effects"]["cray_differ"] == True: - # cr_map, cr_event_num = effects.produceCR_Map( - # xLen=self.npix_x, yLen=self.npix_y, - # exTime=0.01, - # cr_pixelRatio=0.003 * - # (0.01+0.5*self.readout_time)/150., - # gain=self.gain, - # attachedSizes=self.attachedSizes, - # seed=SeedCosmicRay+pointing_ID*30+self.chipID+1) - # # seed: obj-imaging:+0; bias:+1; dark:+2; flat:+3; - # BiasCombImg += cr_map - # del cr_map - - # # Apply Bad lines - # if config["ins_effects"]["add_badcolumns"] == True: - # BiasCombImg = effects.BadColumns( - # BiasCombImg-float(self.bias_level)+5, seed=SeedBadColumns, chipid=self.chipID, logger=self.logger) + float(self.bias_level)-5 - - # # Non-Linearity for Bias - # if config["ins_effects"]["non_linear"] == True: - # if self.logger is not None: - # self.logger.info( - # " Applying Non-Linearity on the Bias image") - # else: - # print( - # " Applying Non-Linearity on the Bias image", flush=True) - # BiasCombImg = effects.NonLinearity( - # GSImage=BiasCombImg, beta1=5.e-7, beta2=0) - - # # START - # pre1 = self.prescan_x # 27 - # over1 = self.overscan_x # 71 - # pre2 = self.prescan_y # 0 #4 - # over2 = self.overscan_y # 84 #80 - - # # prescan & overscan - # if config["ins_effects"]["add_prescan"] == True: - # chip_utils.log_info( - # msg=" Apply pre/over-scan", logger=self.logger) - # BiasCombImg = chip_utils.AddPreScan( - # GSImage=BiasCombImg, pre1=pre1, pre2=pre2, over1=over1, over2=over2) - - # # 1*16 output - # if config["ins_effects"]["format_output"] == True: - # chip_utils.log_info( - # msg=" Apply 1*16 format", logger=self.logger) - # BiasCombImg = chip_utils.formatOutput(GSImage=BiasCombImg) - # self.nsecy = 1 - # self.nsecx = 16 - # # END - - # # Add Bias level - # if config["ins_effects"]["add_bias"] == True: - # if self.logger is not None: - # self.logger.info( - # " Adding Bias level and 16-channel non-uniformity") - # else: - # print(" Adding Bias level and 16-channel non-uniformity") - # BiasCombImg = effects.AddBiasNonUniform16(BiasCombImg, - # bias_level=biaslevel, - # nsecy=self.nsecy, nsecx=self.nsecx, - # seed=SeedBiasNonuni+self.chipID, - # logger=self.logger) - # rng = galsim.UniformDeviate() - # ncombine = 1 - # NoiseBias = galsim.GaussianNoise( - # rng=rng, sigma=self.read_noise*ncombine**0.5) - # BiasCombImg.addNoise(NoiseBias) - - # BiasCombImg, self.gain_channel = effects.ApplyGainNonUniform16(BiasCombImg, gain=self.gain, - # nsecy=self.nsecy, nsecx=self.nsecx, - # seed=SeedGainNonuni+self.chipID, - # logger=self.logger) - # # BiasCombImg = effects.AddOverscan( - # # BiasCombImg, - # # overscan=float(config["ins_effects"]["bias_level"])-2, gain=self.gain, - # # widthl=27, widthr=27, widtht=8, widthb=8) - # BiasCombImg.replaceNegative(replace_value=0) - # BiasCombImg.quantize() - # BiasCombImg = galsim.ImageUS(BiasCombImg) - # timestamp_obs += 10 * 60 - # chip_utils.outputCal( - # chip=self, - # img=BiasCombImg, - # ra_cen=ra_cen, - # dec_cen=dec_cen, - # img_rot=img_rot, - # im_type='BIAS', - # pointing_ID=pointing_ID, - # output_dir=chip_output.subdir, - # exptime=0.0, - # project_cycle=config["project_cycle"], - # run_counter=config["run_counter"], - # timestamp=timestamp_obs) - # del BiasCombImg - - # # Export combined (ncombine, Vignetting + PRNU) & single vignetting flat-field file - # if config["ins_effects"]["flat_fielding"] == True and config["output_setting"]["flat_output"] == True and pointing_type == 'CAL': - # if self.logger is not None: - # self.logger.info(" Output N frame Flat-Field files") - # else: - # print(" Output N frame Flat-Field files", flush=True) - # NFlat = int(config["output_setting"]["NFlat"]) - # if config["ins_effects"]["add_bias"] == True: - # biaslevel = self.bias_level - # overscan = biaslevel-2 - # elif config["ins_effects"]["add_bias"] == False: - # biaslevel = 0 - # overscan = 0 - # darklevel = self.dark_noise * \ - # (self.flat_exptime+0.5*self.readout_time) - # for i in range(NFlat): - # FlatSingle = flat_img * prnu_img + darklevel - # FlatCombImg, FlatTag = effects.MakeFlatNcomb( - # flat_single_image=FlatSingle, - # ncombine=1, - # read_noise=self.read_noise, - # gain=1, - # overscan=overscan, - # biaslevel=0, - # seed_bias=SeedDefective+self.chipID, - # logger=self.logger - # ) - # if config["ins_effects"]["cosmic_ray"] == True: - # if config["ins_effects"]["cray_differ"] == True: - # cr_map, cr_event_num = effects.produceCR_Map( - # xLen=self.npix_x, yLen=self.npix_y, - # exTime=self.flat_exptime+0.5*self.readout_time, - # cr_pixelRatio=0.003 * - # (self.flat_exptime+0.5*self.readout_time)/150., - # gain=self.gain, - # attachedSizes=self.attachedSizes, - # seed=SeedCosmicRay+pointing_ID*30+self.chipID+3) - # # seed: obj-imaging:+0; bias:+1; dark:+2; flat:+3; - # FlatCombImg += cr_map - # del cr_map - - # # Add Hot Pixels or/and Dead Pixels - # rgbadpix = Generator(PCG64(int(SeedDefective+self.chipID))) - # badfraction = 5E-5*(rgbadpix.random()*0.5+0.7) - # FlatCombImg = effects.DefectivePixels( - # FlatCombImg, IfHotPix=BoolHotPix, IfDeadPix=BoolDeadPix, fraction=badfraction, seed=SeedDefective+self.chipID, biaslevel=0) - - # # Apply Bad lines - # if config["ins_effects"]["add_badcolumns"] == True: - # FlatCombImg = effects.BadColumns( - # FlatCombImg, seed=SeedBadColumns, chipid=self.chipID, logger=self.logger) - - # if config["ins_effects"]["non_linear"] == True: - # if self.logger is not None: - # self.logger.info( - # " Applying Non-Linearity on the Flat image") - # else: - # print( - # " Applying Non-Linearity on the Flat image", flush=True) - # FlatCombImg = effects.NonLinearity( - # GSImage=FlatCombImg, beta1=5.e-7, beta2=0) - - # # if config["ins_effects"]["cte_trail"] == True: - # # FlatCombImg = effects.CTE_Effect(GSImage=FlatCombImg, threshold=3) - # # START - # pre1 = self.prescan_x # 27 - # over1 = self.overscan_x # 71 - # pre2 = self.prescan_y # 0 #4 - # over2 = self.overscan_y # 84 #80 - # if config["ins_effects"]["cte_trail"] == True: - # chip_utils.log_info( - # msg=" Apply CTE Effect", logger=self.logger) - # # img = effects.CTE_Effect(GSImage=img, threshold=27) - # # CTI_modeling - # # 2*8 -> 1*16 img-layout - # FlatCombImg = chip_utils.formatOutput(GSImage=FlatCombImg) - # self.nsecy = 1 - # self.nsecx = 16 - - # img_arr = FlatCombImg.array - # ny, nx = img_arr.shape - # dx = int(nx/self.nsecx) - # dy = int(ny/self.nsecy) - # newimg = galsim.Image(nx, int(ny+over2), init_value=0) - # for ichannel in range(16): - # print('\n***add CTI effects: pointing-{:} chip-{:} channel-{:}***'.format( - # pointing_ID, self.chipID, ichannel+1)) - # # nx,ny,noverscan,nsp,nmax = 4608,4616,84,3,10 - # noverscan, nsp, nmax = over2, 3, 10 - # beta, w, c = 0.478, 84700, 0 - # t = np.array([0.74, 7.7, 37], dtype=np.float32) - # rho_trap = np.array([0.6, 1.6, 1.4], dtype=np.float32) - # trap_seeds = np.array( - # [0, 1000, 10000], dtype=np.int32) + ichannel + self.chipID*16 - # release_seed = 50 + ichannel + pointing_ID*30 + self.chipID*16 - # newimg.array[:, 0+ichannel*dx:dx+ichannel*dx] = CTI_sim( - # img_arr[:, 0+ichannel*dx:dx+ichannel*dx], dx, dy, noverscan, nsp, nmax, beta, w, c, t, rho_trap, trap_seeds, release_seed) - # newimg.wcs = FlatCombImg.wcs - # del FlatCombImg - # FlatCombImg = newimg - - # # 1*16 -> 2*8 img-layout - # FlatCombImg = chip_utils.formatRevert(GSImage=FlatCombImg) - # self.nsecy = 2 - # self.nsecx = 8 - - # # prescan & overscan - # if config["ins_effects"]["add_prescan"] == True: - # chip_utils.log_info( - # msg=" Apply pre/over-scan", logger=self.logger) - # if config["ins_effects"]["cte_trail"] == False: - # FlatCombImg = chip_utils.AddPreScan( - # GSImage=FlatCombImg, pre1=pre1, pre2=pre2, over1=over1, over2=over2) - # if config["ins_effects"]["cte_trail"] == True: - # FlatCombImg = chip_utils.AddPreScan( - # GSImage=FlatCombImg, pre1=pre1, pre2=pre2, over1=over1, over2=0) - - # # 1*16 output - # if config["ins_effects"]["format_output"] == True: - # chip_utils.log_info( - # msg=" Apply 1*16 format", logger=self.logger) - # FlatCombImg = chip_utils.formatOutput(GSImage=FlatCombImg) - # self.nsecy = 1 - # self.nsecx = 16 - # # END - - # # Add Bias level - # if config["ins_effects"]["add_bias"] == True: - # if self.logger is not None: - # self.logger.info( - # " Adding Bias level and 16-channel non-uniformity") - # else: - # print(" Adding Bias level and 16-channel non-uniformity") - # # img += float(config["ins_effects"]["bias_level"]) - # FlatCombImg = effects.AddBiasNonUniform16(FlatCombImg, - # bias_level=biaslevel, - # nsecy=self.nsecy, nsecx=self.nsecx, - # seed=SeedBiasNonuni+self.chipID, - # logger=self.logger) - - # # Add Read-out Noise - # if config["ins_effects"]["add_readout"] == True: - # seed = int(config["random_seeds"]["seed_readout"] - # ) + pointing_ID*30 + self.chipID + 3 - # rng_readout = galsim.BaseDeviate(seed) - # readout_noise = galsim.GaussianNoise( - # rng=rng_readout, sigma=self.read_noise) - # FlatCombImg.addNoise(readout_noise) - - # FlatCombImg, self.gain_channel = effects.ApplyGainNonUniform16(FlatCombImg, gain=self.gain, - # nsecy=self.nsecy, nsecx=self.nsecx, - # seed=SeedGainNonuni+self.chipID, - # logger=self.logger) - # # FlatCombImg = effects.AddOverscan(FlatCombImg, overscan=overscan, gain=self.gain, widthl=27, widthr=27, widtht=8, widthb=8) - # FlatCombImg.replaceNegative(replace_value=0) - # FlatCombImg.quantize() - # FlatCombImg = galsim.ImageUS(FlatCombImg) - # timestamp_obs += 10 * 60 - # chip_utils.outputCal( - # chip=self, - # img=FlatCombImg, - # ra_cen=ra_cen, - # dec_cen=dec_cen, - # img_rot=img_rot, - # im_type='FLAT', - # pointing_ID=pointing_ID, - # output_dir=chip_output.subdir, - # exptime=self.flat_exptime, - # project_cycle=config["project_cycle"], - # run_counter=config["run_counter"], - # timestamp=timestamp_obs) - - # del FlatCombImg, FlatSingle, prnu_img - # # flat_img.replaceNegative(replace_value=0) - # # flat_img.quantize() - # # galsim.ImageUS(flat_img).write("%s/FlatImg_Vignette_%s.fits" % (chip_output.subdir, self.chipID)) - # del flat_img - - # # Export Dark current images - # if config["ins_effects"]["add_dark"] == True and config["output_setting"]["dark_output"] == True and pointing_type == 'CAL': - # if self.logger is not None: - # self.logger.info(" Output N frame Dark Current files") - # else: - # print(" Output N frame Dark Current files", flush=True) - # NDark = int(config["output_setting"]["NDark"]) - # if config["ins_effects"]["add_bias"] == True: - # biaslevel = self.bias_level - # overscan = biaslevel-2 - # elif config["ins_effects"]["add_bias"] == False: - # biaslevel = 0 - # overscan = 0 - # for i in range(NDark): - # DarkCombImg, DarkTag = effects.MakeDarkNcomb( - # self.npix_x, self.npix_y, - # overscan=overscan, bias_level=0, darkpsec=0.02, exptime=self.dark_exptime+0.5*self.readout_time, - # ncombine=1, read_noise=self.read_noise, - # gain=1, seed_bias=SeedBiasNonuni+self.chipID, - # logger=self.logger) - # if config["ins_effects"]["cosmic_ray"] == True: - # if config["ins_effects"]["cray_differ"] == True: - # cr_map, cr_event_num = effects.produceCR_Map( - # xLen=self.npix_x, yLen=self.npix_y, - # exTime=self.dark_exptime+0.5*self.readout_time, - # cr_pixelRatio=0.003 * - # (self.dark_exptime+0.5*self.readout_time)/150., - # gain=self.gain, - # attachedSizes=self.attachedSizes, - # seed=SeedCosmicRay+pointing_ID*30+self.chipID+2) - # # seed: obj-imaging:+0; bias:+1; dark:+2; flat:+3; - # DarkCombImg += cr_map - # cr_map[cr_map > 65535] = 65535 - # cr_map[cr_map < 0] = 0 - # crmap_gsimg = galsim.Image(cr_map, dtype=np.uint16) - # del cr_map - # # START - # # prescan & overscan - # if config["ins_effects"]["add_prescan"] == True: - # chip_utils.log_info( - # msg=" Apply pre/over-scan", logger=self.logger) - # crmap_gsimg = chip_utils.AddPreScan( - # GSImage=crmap_gsimg, pre1=pre1, pre2=pre2, over1=over1, over2=over2) - - # # 1*16 output - # if config["ins_effects"]["format_output"] == True: - # chip_utils.log_info( - # msg=" Apply 1*16 format", logger=self.logger) - # crmap_gsimg = chip_utils.formatOutput( - # GSImage=crmap_gsimg) - # self.nsecy = 1 - # self.nsecx = 16 - # # END - # chip_utils.outputCal( - # chip=self, - # img=crmap_gsimg, - # ra_cen=ra_cen, - # dec_cen=dec_cen, - # img_rot=img_rot, - # im_type='CRD', - # pointing_ID=pointing_ID, - # output_dir=chip_output.subdir, - # exptime=self.dark_exptime, - # project_cycle=config["project_cycle"], - # run_counter=config["run_counter"], - # timestamp=timestamp_obs) - # del crmap_gsimg - - # # Add Hot Pixels or/and Dead Pixels - # rgbadpix = Generator(PCG64(int(SeedDefective+self.chipID))) - # badfraction = 5E-5*(rgbadpix.random()*0.5+0.7) - # DarkCombImg = effects.DefectivePixels( - # DarkCombImg, IfHotPix=BoolHotPix, IfDeadPix=BoolDeadPix, fraction=badfraction, seed=SeedDefective+self.chipID, biaslevel=0) - - # # Apply Bad lines - # if config["ins_effects"]["add_badcolumns"] == True: - # DarkCombImg = effects.BadColumns( - # DarkCombImg, seed=SeedBadColumns, chipid=self.chipID, logger=self.logger) - - # # Non-Linearity for Dark - # if config["ins_effects"]["non_linear"] == True: - # if self.logger is not None: - # self.logger.info( - # " Applying Non-Linearity on the Dark image") - # else: - # print( - # " Applying Non-Linearity on the Dark image", flush=True) - # DarkCombImg = effects.NonLinearity( - # GSImage=DarkCombImg, beta1=5.e-7, beta2=0) - - # # if config["ins_effects"]["cte_trail"] == True: - # # DarkCombImg = effects.CTE_Effect(GSImage=DarkCombImg, threshold=3) - # # START - # pre1 = self.prescan_x # 27 - # over1 = self.overscan_x # 71 - # pre2 = self.prescan_y # 0 #4 - # over2 = self.overscan_y # 84 #80 - # if config["ins_effects"]["cte_trail"] == True: - # chip_utils.log_info( - # msg=" Apply CTE Effect", logger=self.logger) - # # img = effects.CTE_Effect(GSImage=img, threshold=27) - # # CTI_modeling - # # 2*8 -> 1*16 img-layout - # DarkCombImg = chip_utils.formatOutput(GSImage=DarkCombImg) - # self.nsecy = 1 - # self.nsecx = 16 - - # img_arr = DarkCombImg.array - # ny, nx = img_arr.shape - # dx = int(nx/self.nsecx) - # dy = int(ny/self.nsecy) - # newimg = galsim.Image(nx, int(ny+over2), init_value=0) - # for ichannel in range(16): - # print('\n***add CTI effects: pointing-{:} chip-{:} channel-{:}***'.format( - # pointing_ID, self.chipID, ichannel+1)) - # # nx,ny,noverscan,nsp,nmax = 4608,4616,84,3,10 - # noverscan, nsp, nmax = over2, 3, 10 - # beta, w, c = 0.478, 84700, 0 - # t = np.array([0.74, 7.7, 37], dtype=np.float32) - # rho_trap = np.array([0.6, 1.6, 1.4], dtype=np.float32) - # trap_seeds = np.array( - # [0, 1000, 10000], dtype=np.int32) + ichannel + self.chipID*16 - # release_seed = 50 + ichannel + pointing_ID*30 + self.chipID*16 - # newimg.array[:, 0+ichannel*dx:dx+ichannel*dx] = CTI_sim( - # img_arr[:, 0+ichannel*dx:dx+ichannel*dx], dx, dy, noverscan, nsp, nmax, beta, w, c, t, rho_trap, trap_seeds, release_seed) - # newimg.wcs = DarkCombImg.wcs - # del DarkCombImg - # DarkCombImg = newimg - - # # 1*16 -> 2*8 img-layout - # DarkCombImg = chip_utils.formatRevert(GSImage=DarkCombImg) - # self.nsecy = 2 - # self.nsecx = 8 - - # # prescan & overscan - # if config["ins_effects"]["add_prescan"] == True: - # chip_utils.log_info( - # msg=" Apply pre/over-scan", logger=self.logger) - # if config["ins_effects"]["cte_trail"] == False: - # DarkCombImg = chip_utils.AddPreScan( - # GSImage=DarkCombImg, pre1=pre1, pre2=pre2, over1=over1, over2=over2) - # if config["ins_effects"]["cte_trail"] == True: - # DarkCombImg = chip_utils.AddPreScan( - # GSImage=DarkCombImg, pre1=pre1, pre2=pre2, over1=over1, over2=0) - - # # 1*16 output - # if config["ins_effects"]["format_output"] == True: - # chip_utils.log_info( - # msg=" Apply 1*16 format", logger=self.logger) - # DarkCombImg = chip_utils.formatOutput(GSImage=DarkCombImg) - # self.nsecy = 1 - # self.nsecx = 16 - # # END - - # # Add Bias level - # if config["ins_effects"]["add_bias"] == True: - # if self.logger is not None: - # self.logger.info( - # " Adding Bias level and 16-channel non-uniformity") - # else: - # print(" Adding Bias level and 16-channel non-uniformity") - # # img += float(config["ins_effects"]["bias_level"]) - # DarkCombImg = effects.AddBiasNonUniform16(DarkCombImg, - # bias_level=biaslevel, - # nsecy=self.nsecy, nsecx=self.nsecx, - # seed=SeedBiasNonuni+self.chipID, - # logger=self.logger) - - # # Add Read-out Noise - # if config["ins_effects"]["add_readout"] == True: - # seed = int(config["random_seeds"]["seed_readout"] - # ) + pointing_ID*30 + self.chipID + 2 - # rng_readout = galsim.BaseDeviate(seed) - # readout_noise = galsim.GaussianNoise( - # rng=rng_readout, sigma=self.read_noise) - # DarkCombImg.addNoise(readout_noise) - - # DarkCombImg, self.gain_channel = effects.ApplyGainNonUniform16( - # DarkCombImg, gain=self.gain, - # nsecy=self.nsecy, nsecx=self.nsecx, - # seed=SeedGainNonuni+self.chipID, - # logger=self.logger) - # # DarkCombImg = effects.AddOverscan( - # # DarkCombImg, - # # overscan=overscan, gain=self.gain, - # # widthl=27, widthr=27, widtht=8, widthb=8) - # DarkCombImg.replaceNegative(replace_value=0) - # DarkCombImg.quantize() - # DarkCombImg = galsim.ImageUS(DarkCombImg) - # timestamp_obs += 10 * 60 - # chip_utils.outputCal( - # chip=self, - # img=DarkCombImg, - # ra_cen=ra_cen, - # dec_cen=dec_cen, - # img_rot=img_rot, - # im_type='DARK', - # pointing_ID=pointing_ID, - # output_dir=chip_output.subdir, - # exptime=self.dark_exptime, - # project_cycle=config["project_cycle"], - # run_counter=config["run_counter"], - # timestamp=timestamp_obs) - # del DarkCombImg - # # img = galsim.ImageUS(img) - - # # # 16 output channel, with each a single image file - # # if config["ins_effects"]["readout16"] == True: - # # print(" 16 Output Channel simulation") - # # for coli in [0, 1]: - # # for rowi in range(8): - # # sub_img = effects.readout16( - # # GSImage=img, - # # rowi=rowi, - # # coli=coli, - # # overscan_value=self.overscan) - # # rowcoltag = str(rowi) + str(coli) - # # img_name_root = chip_output.img_name.split(".")[0] - # # sub_img.write("%s/%s_%s.fits" % (chip_output.subdir, img_name_root, rowcoltag)) - # # del sub_img - # return img diff --git a/ObservationSim/Instrument/Telescope.py b/ObservationSim/Instrument/Telescope.py deleted file mode 100755 index 719a422dd748fa2c96fc2ef51782e24e698d713f..0000000000000000000000000000000000000000 --- a/ObservationSim/Instrument/Telescope.py +++ /dev/null @@ -1,44 +0,0 @@ -import numpy as np - -try: - import importlib.resources as pkg_resources -except ImportError: - # Try backported to PY<37 'importlib_resources' - import importlib_resources as pkg_resources - -class Telescope(object): - def __init__(self, param=None, optEffCurve_path=None): - self.diameter = 2.0 # in unit of meter - if param is not None: - self.diameter = param["diameter"] - self.pupil_area = np.pi * (0.5 * self.diameter)**2 - if optEffCurve_path is not None: - self.efficiency = self._get_efficiency(optEffCurve_path) - else: - try: - with pkg_resources.files('ObservationSim.Instrument.data').joinpath('mirror_ccdnote.txt') as optEffCurve_path: - self.efficiency = self._get_efficiency(optEffCurve_path) - except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data', 'mirror_ccdnote.txt') as optEffCurve_path: - self.efficiency = self._get_efficiency(optEffCurve_path) - - def _get_efficiency(self, effCurve_path): - """ Read in the efficiency of optics - for each band - Parameters: - effCurve_path: the path for efficiency file - Returns: - opticsEff: a dictionary of efficiency (a scalar) for each band - """ - f = open(effCurve_path, 'r') - for _ in range(2): - header = f.readline() - - iline = 0 - opticsEff = {} - for line in f: - line = line.strip() - columns = line.split() - opticsEff[str(columns[0])] = float(columns[2]) - f.close() - return opticsEff \ No newline at end of file diff --git a/ObservationSim/Instrument/_util.py b/ObservationSim/Instrument/_util.py deleted file mode 100755 index 58d153ccaa04160f776fb0a1752a0a3db9329d17..0000000000000000000000000000000000000000 --- a/ObservationSim/Instrument/_util.py +++ /dev/null @@ -1,130 +0,0 @@ -import numpy as np -import os -import math -from pylab import * -from scipy import interpolate - -try: - import importlib.resources as pkg_resources -except ImportError: - # Try backported to PY<37 'importlib_resources' - import importlib_resources as pkg_resources - -VC_A = 2.99792458e+18 # speed of light: A/s -VC_M = 2.99792458e+8 # speed of light: m/s -H_PLANK = 6.626196e-27 # Plank constant: erg s - -ALL_FILTERS = ["NUV","u", "g", "r", "i","z","y","GU", "GV", "GI", "FGS"] -PHOT_FILTERS = ["NUV", "u", "g", 'r', 'i', 'z', 'y', 'FGS'] -SPEC_FILTERS = ["GI", "GV", "GU"] - -def rotate_conterclockwise(x0, y0, x, y, angle): - """ - Rotate a point counterclockwise by a given angle around a given origin. - - The angle should be given in radians. - """ - angle = np.deg2rad(angle) - qx = x0 + np.cos(angle)*(x - x0) - np.sin(angle) * (y - y0) - qy = y0 + np.sin(angle)*(x - x0) + np.cos(angle) * (y - y0) - return qx, qy - -def photonEnergy(lambd): - """ The energy of photon at a given wavelength - - Parameter: - lambd: the wavelength in unit of Angstrom - Return: - eph: energy of photon in unit of erg - """ - nu = VC_A / lambd - eph = H_PLANK * nu - return eph - -def calculateLimitMag(aperture = 2.0, psf_fwhm = 0.1969,pixelSize = 0.074, pmRation = 0.8, throughputFn = 'i_throughput.txt', readout = 5.0, skyFn= 'sky_emiss_hubble_50_50_A.dat', darknoise = 0.02,exTime = 150, exNum = 1, fw = 90000): - ''' - description: - param {*} aperture: unit m, default 2 m - param {*} psf_fwhm: psf fwhm, default 0.1969" - param {*} pixelSize: pixel size, default 0.074" - param {*} pmRation: the ratio of souce flux in the limit mag calculation - param {*} throughputFn: throuput file name - param {*} readout: unit, e-/pixel - param {*} skyFn: sky sed file name, average of hst, 'sky_emiss_hubble_50_50_A.dat' - param {*} darknoise: unit, e-/pixel/s - param {*} exTime: exposure time one time, default 150s - param {*} exNum: exposure number, defautl 1 - param {*} fw, full well value( or saturation value),default 90000e-/pixel - return {*} limit mag and saturation mag - ''' - try: - with pkg_resources.files('ObservationSim.Instrument.data.throughputs').joinpath(throughputFn) as data_file: - throughput_f = np.loadtxt(data_file) - except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data.throughputs', throughputFn) as data_file: - throughput_f = np.loadtxt(data_file) - thr_i = interpolate.interp1d(throughput_f[:,0]/10, throughput_f[:,1]); # wavelength in anstrom - f_s = 200 - f_e = 1100 - delt_f = 0.5 - - data_num = int((f_e-f_s)/delt_f+1) - - eff = np.zeros([data_num,2]) - eff[:,0] = np.arange(f_s,f_e+delt_f,delt_f) - eff[:,1] = thr_i(eff[:,0]) - - wave = np.arange(f_s,f_e+delt_f,delt_f) - wavey = np.ones(wave.shape[0]) - - try: - with pkg_resources.files('ObservationSim.Instrument.data.throughputs').joinpath(skyFn) as data_file: - skydata = np.loadtxt(data_file) - except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data.throughputs', skyFn) as data_file: - skydata = np.loadtxt(data_file) - skydatai = interpolate.interp1d(skydata[:,0]/10, skydata[:,1]*10) - - sky_data = np.zeros([data_num,2]) - sky_data[:,0] = np.arange(f_s,f_e+delt_f,delt_f) - sky_data[:,1] = skydatai(sky_data[:,0]) - - flux_sky = trapz((sky_data[:,1])*eff[:,1],sky_data[:,0]) - skyPix = flux_sky*pixelSize*pixelSize*pi*(aperture*aperture/4) - - - ###limit mag - - r_pix = psf_fwhm*0.7618080243778568/pixelSize # radius RE80, pixel - cnum = math.pi * r_pix * r_pix - sn = 5 - - d = skyPix*exTime*exNum*cnum + darknoise*exTime*exNum*cnum+readout*readout*cnum*exNum - a=1 - b=-sn*sn - c=-sn*sn*d - - flux = (-b+sqrt(b*b-4*a*c))/(2*a)/pmRation - limitMag = -2.5*log10(flux/(54799275581.04437 * trapz(wavey*eff[:,1]/wave,wave, 0.1)*exTime*exNum*pi*(aperture/2)*(aperture/2))) - - - ### saturation mag - - from astropy.modeling.models import Gaussian2D - m_size = int(20 * psf_fwhm/pixelSize) - if m_size%2 == 0: - m_size + 1 - m_cen = m_size//2 - psf_sigma = psf_fwhm/2.355/pixelSize - - gaussShape = Gaussian2D(1, m_cen, m_cen, psf_sigma, psf_sigma) - yp, xp = np.mgrid[0:m_size, 0:m_size] - psfMap = gaussShape(xp, yp) - maxRatio = np.amax(psfMap)/np.sum(psfMap) - # print(maxRatio) - - flux_sat = fw/maxRatio*exNum - satMag = -2.5*log10(flux_sat/(54799275581.04437 * trapz(wavey*eff[:,1]/wave,wave, 0.1)*exTime*exNum*pi*(aperture/2)*(aperture/2))); - - - return limitMag , satMag \ No newline at end of file diff --git a/ObservationSim/MockObject/CosmicRay.py b/ObservationSim/MockObject/CosmicRay.py deleted file mode 100755 index bdfb9ab3ae1fe2705b42b347592bde7c11649a6c..0000000000000000000000000000000000000000 --- a/ObservationSim/MockObject/CosmicRay.py +++ /dev/null @@ -1,4 +0,0 @@ -from ObservationSim.MockObject.MockObject import MockObject - -class CosmicRay(MockObject): - pass \ No newline at end of file diff --git a/ObservationSim/PSF/PSFGauss.py b/ObservationSim/PSF/PSFGauss.py deleted file mode 100644 index 234d5d08f8c7e0f2ac7026115cfb185b923ce0d1..0000000000000000000000000000000000000000 --- a/ObservationSim/PSF/PSFGauss.py +++ /dev/null @@ -1,118 +0,0 @@ -import galsim -import sep -import numpy as np -from scipy.interpolate import interp1d - -from ObservationSim.PSF.PSFModel import PSFModel - -class PSFGauss(PSFModel): - def __init__(self, chip, fwhm=0.187, sigSpin=0., psfRa=None): - self.pix_size = chip.pix_scale - self.chip = chip - if psfRa is None: - self.fwhm = fwhm - self.sigGauss = 0.15 - else: - self.fwhm = self.fwhmGauss(r=psfRa) - self.sigGauss = psfRa # 80% light radius - self.sigSpin = sigSpin - self.psf = galsim.Gaussian(flux=1.0,fwhm=fwhm) - - def perfGauss(self, r, sig): - """ - pseudo-error function, i.e. Cumulative distribution function of Gaussian distribution - - Parameter: - r: radius - sig: sigma of the Gaussian distribution - - Return: - the value of the pseudo CDF - """ - gaussFun = lambda sigma, r: 1.0/(np.sqrt(2.0*np.pi)*sigma) * np.exp(-r**2/(2.0*sigma**2)) - nxx = 1000 - rArr = np.linspace(0.0,r,nxx) - gauss = gaussFun(sig,rArr) - erf = 2.0*np.trapz(gauss,rArr) - return erf - - def fracGauss(self, sig, r=0.15, pscale=None): - """ - For a given Gaussian PSF with sigma=sig, - derive the flux ratio ar the given radius r - - Parameters: - sig: sigma of the Gauss PSF Function in arcsec - r: radius in arcsec - pscale: pixel scale - - Return: the flux ratio - """ - if pscale == None: - pscale = self.pix_size - gaussx = galsim.Gaussian(flux=1.0,sigma=sig) - gaussImg = gaussx.drawImage(scale=pscale, method='no_pixel') - gaussImg = gaussImg.array - size = np.size(gaussImg,axis=0) - cxy = 0.5*(size-1) - flux, ferr, flag = sep.sum_circle(gaussImg,[cxy],[cxy],[r/pscale],subpix=0) - return flux - - def fwhmGauss(self, r=0.15,fr=0.8,pscale=None): - """ - Given a total flux ratio 'fr' within a fixed radius 'r', - estimate the fwhm of the Gaussian function - - return the fwhm in arcsec - """ - if pscale == None: - pscale = self.pix_size - err = 1.0e-3 - nxx = 100 - sig = np.linspace(0.5*pscale,1.0,nxx) - frA = np.zeros(nxx) - for i in range(nxx): frA[i] = self.fracGauss(sig[i],r=r,pscale=pscale) - index = [i for i in range(nxx-1) if (fr-frA[i])*(fr-frA[i+1])<=0.0][0] - - while abs(frA[index]-fr)>1.0e-3: - sig = np.linspace(sig[index],sig[index+1],nxx) - for i in range(nxx): frA[i] = self.fracGauss(sig[i],r=r,pscale=pscale) - index = [i for i in range(nxx-1) if (fr-frA[i])*(fr-frA[i+1])<=0.0][0] - - fwhm = 2.35482*sig[index] - return fwhm - - def get_PSF(self, pos_img, chip=None, bandpass=None, folding_threshold=5.e-3): - dx = pos_img.x - self.chip.cen_pix_x - dy = pos_img.y - self.chip.cen_pix_y - return self.PSFspin(dx, dy) - - def PSFspin(self, x, y): - """ - The PSF profile at a given image position relative to the axis center - - Parameters: - theta : spin angles in a given exposure in unit of [arcsecond] - dx, dy: relative position to the axis center in unit of [pixels] - - Return: - Spinned PSF: g1, g2 and axis ratio 'a/b' - """ - a2Rad = np.pi/(60.0*60.0*180.0) - - ff = self.sigGauss * 0.107 * (1000.0/10.0) # in unit of [pixels] - rc = np.sqrt(x*x + y*y) - cpix = rc*(self.sigSpin*a2Rad) - - beta = (np.arctan2(y,x) + np.pi/2) - ell = cpix**2/(2.0*ff**2+cpix**2) - #ell *= 10.0 - qr = np.sqrt((1.0+ell)/(1.0-ell)) - - #psfShape = galsim.Shear(e=ell, beta=beta) - #g1, g2 = psfShape.g1, psfShape.g2 - #qr = np.sqrt((1.0+ell)/(1.0-ell)) - - #return ell, beta, qr - PSFshear = galsim.Shear(e=ell, beta=beta*galsim.radians) - return self.psf.shear(PSFshear), PSFshear \ No newline at end of file diff --git a/ObservationSim/PSF/PSFModel.py b/ObservationSim/PSF/PSFModel.py deleted file mode 100755 index 0f37d31b444dcc7354297475e71a3860d4e29243..0000000000000000000000000000000000000000 --- a/ObservationSim/PSF/PSFModel.py +++ /dev/null @@ -1,41 +0,0 @@ -import galsim -import sep -import numpy as np -from scipy.interpolate import interp1d -import pylab as pl -import os, sys - -class PSFModel(object): - def __init__(self, sigSpin=0., psfRa=0.15): - # TODO: what are the nesseary fields in PSFModel class? - pass - - def PSFspin(self, psf, sigSpin, sigGauss, dx, dy): - """ - The PSF profile at a given image position relative to the axis center - - Parameters: - theta : spin angles in a given exposure in unit of [arcsecond] - dx, dy: relative position to the axis center in unit of [pixels] - - Return: - Spinned PSF: g1, g2 and axis ratio 'a/b' - """ - a2Rad = np.pi/(60.0*60.0*180.0) - - ff = sigGauss * 0.107 * (1000.0/10.0) # in unit of [pixels] - rc = np.sqrt(dx*dx + dy*dy) - cpix = rc*(sigSpin*a2Rad) - - beta = (np.arctan2(dy,dx) + np.pi/2) - ell = cpix**2/(2.0*ff**2+cpix**2) - #ell *= 10.0 - qr = np.sqrt((1.0+ell)/(1.0-ell)) - - #psfShape = galsim.Shear(e=ell, beta=beta) - #g1, g2 = psfShape.g1, psfShape.g2 - #qr = np.sqrt((1.0+ell)/(1.0-ell)) - - #return ell, beta, qr - PSFshear = galsim.Shear(e=ell, beta=beta*galsim.radians) - return psf.shear(PSFshear), PSFshear \ No newline at end of file diff --git a/ObservationSim/sim_steps/add_LED_flat.py b/ObservationSim/sim_steps/add_LED_flat.py deleted file mode 100644 index befd04d9e1a4e3272c80264cef40f803533cdcdc..0000000000000000000000000000000000000000 --- a/ObservationSim/sim_steps/add_LED_flat.py +++ /dev/null @@ -1,51 +0,0 @@ -import numpy as np -from ObservationSim.MockObject import FlatLED -import galsim - -from astropy.time import Time -from datetime import datetime, timezone - -import gc - -def add_LED_Flat(self, chip, filt, tel, pointing, catalog, obs_param): - - if not hasattr(self, 'h_ext'): - _, _ = self.prepare_headers(chip=chip, pointing=pointing) - chip_wcs = galsim.FitsWCS(header = self.h_ext) - pf_map = np.zeros_like(chip.img.array) - if obs_param["LED_TYPE"] is not None: - if len(obs_param["LED_TYPE"]) != 0: - print("LED OPEN--------") - - led_obj = FlatLED(chip, filt) - led_flat, ledstat, letts = led_obj.drawObj_LEDFlat(led_type_list=obs_param["LED_TYPE"], exp_t_list=obs_param["LED_TIME"]) - pf_map = led_flat - self.updateHeaderInfo(header_flag='ext', keys = ['LEDSTAT'], values = [ledstat]) - self.updateHeaderInfo(header_flag='ext', keys = ['LEDT01','LEDT02','LEDT03','LEDT04','LEDT05','LEDT06','LEDT07','LEDT08','LEDT09','LEDT10','LEDT11','LEDT12','LEDT13','LEDT14'], values = letts) - - - if obs_param["shutter_effect"] == True: - pf_map = pf_map * chip.shutter_img - pf_map = np.array(pf_map, dtype='float32') - self.updateHeaderInfo(header_flag='ext', keys = ['SHTSTAT'], values = [True]) - else: - self.updateHeaderInfo(header_flag='ext', keys = ['SHTSTAT','SHTOPEN1','SHTCLOS0'], values = [True,self.h_ext['SHTCLOS1'],self.h_ext['SHTOPEN0']]) - - chip.img = chip.img + pf_map - - # renew header info - datetime_obs = datetime.utcfromtimestamp(pointing.timestamp) - datetime_obs = datetime_obs.replace(tzinfo=timezone.utc) - t_obs = Time(datetime_obs) - - ##ccd刷新2s,等待0.5s,开灯后等待0.5s,开始曝光 - t_obs_renew = Time(t_obs.mjd - (2.) / 86400., format="mjd") - - t_obs_utc = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(t_obs_renew.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) - self.updateHeaderInfo(header_flag='prim', keys = ['DATE-OBS'], values = [t_obs_utc.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]]) - - #dark time : - self.updateHeaderInfo(header_flag='ext', keys = ['DARKTIME'], values = [pointing.exp_time]) - - gc.collect() - return chip, filt, tel, pointing \ No newline at end of file diff --git a/ObservationSim/sim_steps/add_pattern_noise.py b/ObservationSim/sim_steps/add_pattern_noise.py deleted file mode 100644 index 4fb2598ae15062d766d34207924497416abbd767..0000000000000000000000000000000000000000 --- a/ObservationSim/sim_steps/add_pattern_noise.py +++ /dev/null @@ -1,75 +0,0 @@ -from numpy.random import Generator, PCG64 -from ObservationSim.Instrument.Chip import ChipUtils as chip_utils -from ObservationSim.Instrument.Chip import Effects - -def apply_PRNU(self, chip, filt, tel, pointing, catalog, obs_param): - chip.img *= chip.prnu_img - if self.overall_config["output_setting"]["prnu_output"] == True: - chip.prnu_img.write("%s/FlatImg_PRNU_%s.fits" % (self.chip_output.subdir, str(chip.chipID).rjust(2, '0'))) - return chip, filt, tel, pointing - -def add_poisson_and_dark(self, chip, filt, tel, pointing, catalog, obs_param): - # Add dark current & Poisson noise - # Get exposure time - if (obs_param) and ("exptime" in obs_param) and (obs_param["exptime"] is not None): - exptime = obs_param["exptime"] - else: - exptime = pointing.exp_time - - if obs_param["add_dark"] == True: - chip.img, _ = chip_utils.add_poisson(img=chip.img, - chip=chip, - exptime=pointing.exp_time, - poisson_noise=chip.poisson_noise, - InputDark=None) - else: - chip.img, _ = chip_utils.add_poisson(img=chip.img, - chip=self, - exptime=exptime, - poisson_noise=chip.poisson_noise, - dark_noise=0.) - return chip, filt, tel, pointing - -def add_detector_defects(self, chip, filt, tel, pointing, catalog, obs_param): - # Add Hot Pixels or/and Dead Pixels - rgbadpix = Generator(PCG64(int(self.overall_config["random_seeds"]["seed_defective"]+chip.chipID))) - badfraction = 5E-5*(rgbadpix.random()*0.5+0.7) - chip.img = Effects.DefectivePixels( - chip.img, - IfHotPix=obs_param["hot_pixels"], - IfDeadPix=obs_param["dead_pixels"], - fraction=badfraction, - seed=self.overall_config["random_seeds"]["seed_defective"]+chip.chipID, biaslevel=0) - # Apply Bad columns - if obs_param["bad_columns"] == True: - chip.img = Effects.BadColumns(chip.img, - seed=self.overall_config["random_seeds"]["seed_badcolumns"], - chipid=chip.chipID) - return chip, filt, tel, pointing - -def add_nonlinearity(self, chip, filt, tel, pointing, catalog, obs_param): - self.chip_output.Log_info(" Applying Non-Linearity on the chip image") - chip.img = Effects.NonLinearity(GSImage=chip.img, - beta1=5.e-7, - beta2=0) - return chip, filt, tel, pointing - -def add_blooming(self, chip, filt, tel, pointing, catalog, obs_param): - self.chip_output.Log_info(" Applying CCD Saturation & Blooming") - chip.img = Effects.SaturBloom(GSImage=chip.img, - nsect_x=1, - nsect_y=1, - fullwell=int(chip.full_well)) - return chip, filt, tel, pointing - -def add_bias(self, chip, filt, tel, pointing, catalog, obs_param): - self.chip_output.Log_info(" Adding Bias level and 16-channel non-uniformity") - if obs_param["bias_16channel"] == True: - chip.img = Effects.AddBiasNonUniform16(chip.img, - bias_level=float(chip.bias_level), - nsecy = chip.nsecy, - nsecx=chip.nsecx, - seed=self.overall_config["random_seeds"]["seed_biasNonUniform"]+chip.chipID) - elif obs_param["bias_16channel"] == False: - chip.img += self.bias_level - return chip, filt, tel, pointing diff --git a/ObservationSim/sim_steps/prepare_headers.py b/ObservationSim/sim_steps/prepare_headers.py deleted file mode 100644 index bfd88e904612939a1adde6d56a6be08d1bacaa82..0000000000000000000000000000000000000000 --- a/ObservationSim/sim_steps/prepare_headers.py +++ /dev/null @@ -1,50 +0,0 @@ -from ObservationSim.Config.Header import generatePrimaryHeader, generateExtensionHeader - -def prepare_headers(self, chip, pointing): - self.h_prim = generatePrimaryHeader( - xlen=chip.npix_x, - ylen=chip.npix_y, - pointing_id = pointing.obs_id, - pointing_type_code = pointing.pointing_type_code, - ra=pointing.ra, - dec=pointing.dec, - pixel_scale=chip.pix_scale, - time_pt = pointing.timestamp, - exptime=pointing.exp_time, - im_type=pointing.pointing_type, - sat_pos=[pointing.sat_x, pointing.sat_y, pointing.sat_z], - sat_vel=[pointing.sat_vx, pointing.sat_vy, pointing.sat_vz], - project_cycle=self.overall_config["project_cycle"], - run_counter=self.overall_config["run_counter"], - chip_name=str(chip.chipID).rjust(2, '0')) - self.h_ext = generateExtensionHeader( - chip=chip, - xlen=chip.npix_x, - ylen=chip.npix_y, - ra=pointing.ra, - dec=pointing.dec, - pa=pointing.img_pa.deg, - gain=chip.gain, - readout=chip.read_noise, - dark=chip.dark_noise, - saturation=90000, - pixel_scale=chip.pix_scale, - pixel_size=chip.pix_size, - xcen=chip.x_cen, - ycen=chip.y_cen, - extName=pointing.pointing_type, - timestamp = pointing.timestamp, - exptime = pointing.exp_time, - readoutTime = chip.readout_time, - t_shutter_open = pointing.t_shutter_open, - t_shutter_close = pointing.t_shutter_close) - - return self.h_prim, self.h_ext - -def updateHeaderInfo(self,header_flag='prim', keys = ['key'], values = [0]): - if header_flag == 'prim': - for key,value in zip(keys, values): - self.h_prim[key] = value - if header_flag == 'ext': - for key,value in zip(keys, values): - self.h_ext[key] = value diff --git a/Catalog/C6_50sqdeg_ns.py b/catalog/C9_Catalog.py similarity index 73% rename from Catalog/C6_50sqdeg_ns.py rename to catalog/C9_Catalog.py index 23fea6583f7e25a527497b59a35700b17e6af469..948fc96648faf2d5b38231def2d7d04d1642ffc6 100644 --- a/Catalog/C6_50sqdeg_ns.py +++ b/catalog/C9_Catalog.py @@ -12,9 +12,9 @@ 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 tag_sed, getObservedSED, getABMAG, integrate_sed_bandpass, comoving_dist -from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position +from observation_sim.mock_objects import CatalogBase, Star, Galaxy, Quasar +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 # (TEST) from astropy.cosmology import FlatLambdaCDM @@ -34,23 +34,29 @@ except ImportError: NSIDE = 128 -bundle_file_list = ['galaxies_C6_bundle000199.h5','galaxies_C6_bundle000200.h5','galaxies_C6_bundle000241.h5','galaxies_C6_bundle000242.h5','galaxies_C6_bundle000287.h5','galaxies_C6_bundle000288.h5','galaxies_C6_bundle000714.h5','galaxies_C6_bundle000715.h5','galaxies_C6_bundle000778.h5','galaxies_C6_bundle000779.h5','galaxies_C6_bundle000842.h5','galaxies_C6_bundle000843.h5','galaxies_C6_bundle002046.h5','galaxies_C6_bundle002110.h5','galaxies_C6_bundle002111.h5','galaxies_C6_bundle002173.h5','galaxies_C6_bundle002174.h5','galaxies_C6_bundle002238.h5','galaxies_C6_bundle002596.h5','galaxies_C6_bundle002597.h5','galaxies_C6_bundle002656.h5','galaxies_C6_bundle002657.h5','galaxies_C6_bundle002711.h5','galaxies_C6_bundle002712.h5','galaxies_C6_bundle002844.h5','galaxies_C6_bundle002845.h5','galaxies_C6_bundle002884.h5','galaxies_C6_bundle002885.h5','galaxies_C6_bundle002921.h5','galaxies_C6_bundle002922.h5'] +bundle_file_list = ['galaxies_C6_bundle000199.h5', 'galaxies_C6_bundle000200.h5', 'galaxies_C6_bundle000241.h5', 'galaxies_C6_bundle000242.h5', 'galaxies_C6_bundle000287.h5', 'galaxies_C6_bundle000288.h5', 'galaxies_C6_bundle000714.h5', 'galaxies_C6_bundle000715.h5', 'galaxies_C6_bundle000778.h5', 'galaxies_C6_bundle000779.h5', 'galaxies_C6_bundle000842.h5', 'galaxies_C6_bundle000843.h5', 'galaxies_C6_bundle002046.h5', 'galaxies_C6_bundle002110.h5', 'galaxies_C6_bundle002111.h5', + 'galaxies_C6_bundle002173.h5', 'galaxies_C6_bundle002174.h5', 'galaxies_C6_bundle002238.h5', 'galaxies_C6_bundle002596.h5', 'galaxies_C6_bundle002597.h5', 'galaxies_C6_bundle002656.h5', 'galaxies_C6_bundle002657.h5', 'galaxies_C6_bundle002711.h5', 'galaxies_C6_bundle002712.h5', 'galaxies_C6_bundle002844.h5', 'galaxies_C6_bundle002845.h5', 'galaxies_C6_bundle002884.h5', 'galaxies_C6_bundle002885.h5', 'galaxies_C6_bundle002921.h5', 'galaxies_C6_bundle002922.h5'] -qsosed_file_list = ['quickspeclib_interp1d_run1.fits','quickspeclib_interp1d_run2.fits','quickspeclib_interp1d_run3.fits','quickspeclib_interp1d_run4.fits','quickspeclib_interp1d_run5.fits','quickspeclib_interp1d_run6.fits','quickspeclib_interp1d_run7.fits','quickspeclib_interp1d_run8.fits','quickspeclib_interp1d_run9.fits','quickspeclib_interp1d_run10.fits','quickspeclib_interp1d_run11.fits','quickspeclib_interp1d_run12.fits','quickspeclib_interp1d_run13.fits','quickspeclib_interp1d_run14.fits','quickspeclib_interp1d_run15.fits','quickspeclib_interp1d_run16.fits','quickspeclib_interp1d_run17.fits','quickspeclib_interp1d_run18.fits','quickspeclib_interp1d_run19.fits','quickspeclib_interp1d_run20.fits','quickspeclib_interp1d_run21.fits','quickspeclib_interp1d_run22.fits','quickspeclib_interp1d_run23.fits','quickspeclib_interp1d_run24.fits','quickspeclib_interp1d_run25.fits','quickspeclib_interp1d_run26.fits','quickspeclib_interp1d_run27.fits','quickspeclib_interp1d_run28.fits','quickspeclib_interp1d_run29.fits','quickspeclib_interp1d_run30.fits'] +qsosed_file_list = ['quickspeclib_interp1d_run1.fits', 'quickspeclib_interp1d_run2.fits', 'quickspeclib_interp1d_run3.fits', 'quickspeclib_interp1d_run4.fits', 'quickspeclib_interp1d_run5.fits', 'quickspeclib_interp1d_run6.fits', 'quickspeclib_interp1d_run7.fits', 'quickspeclib_interp1d_run8.fits', 'quickspeclib_interp1d_run9.fits', 'quickspeclib_interp1d_run10.fits', 'quickspeclib_interp1d_run11.fits', 'quickspeclib_interp1d_run12.fits', 'quickspeclib_interp1d_run13.fits', 'quickspeclib_interp1d_run14.fits', 'quickspeclib_interp1d_run15.fits', + 'quickspeclib_interp1d_run16.fits', 'quickspeclib_interp1d_run17.fits', 'quickspeclib_interp1d_run18.fits', 'quickspeclib_interp1d_run19.fits', 'quickspeclib_interp1d_run20.fits', 'quickspeclib_interp1d_run21.fits', 'quickspeclib_interp1d_run22.fits', 'quickspeclib_interp1d_run23.fits', 'quickspeclib_interp1d_run24.fits', 'quickspeclib_interp1d_run25.fits', 'quickspeclib_interp1d_run26.fits', 'quickspeclib_interp1d_run27.fits', 'quickspeclib_interp1d_run28.fits', 'quickspeclib_interp1d_run29.fits', 'quickspeclib_interp1d_run30.fits'] # star_file_list = ['C7_Gaia_Galaxia_RA170DECm23_healpix.hdf5', 'C7_Gaia_Galaxia_RA180DECp60_healpix.hdf5', 'C7_Gaia_Galaxia_RA240DECp30_healpix.hdf5', 'C7_Gaia_Galaxia_RA300DECm60_healpix.hdf5', 'C7_Gaia_Galaxia_RA30DECm48_healpix.hdf5'] -star_center_list = [(170., -23.), (180., 60.), (240., 30.), (300., -60.), (30., -48.),[246.5, 40]] +star_center_list = [(170., -23.), (180., 60.), (240., 30.), + (300., -60.), (30., -48.), [246.5, 40]] + +star_file_list = ['C9_RA170_DECm23_calmag_Nside_128_healpix.hdf5', 'C9_RA180_DECp60_calmag_Nside_128_healpix.hdf5', 'C9_RA240_DECp30_calmag_Nside_128_healpix.hdf5', + 'C9_RA300_DECm60_calmag_Nside_128_healpix.hdf5', 'C9_RA30_DECm48_calmag_Nside_128_healpix.hdf5', 'trilegal_calMag_mpi_Nside_128_healpix.hdf5'] -star_file_list = ['C9_RA170_DECm23_calmag_Nside_128_healpix.hdf5', 'C9_RA180_DECp60_calmag_Nside_128_healpix.hdf5', 'C9_RA240_DECp30_calmag_Nside_128_healpix.hdf5', 'C9_RA300_DECm60_calmag_Nside_128_healpix.hdf5', 'C9_RA30_DECm48_calmag_Nside_128_healpix.hdf5','trilegal_calMag_mpi_Nside_128_healpix.hdf5'] class StarParm(ctypes.Structure): _fields_ = [ - ('logte',ctypes.c_float), - ('logg',ctypes.c_float), - ('Mass',ctypes.c_float), - ('Av', ctypes.c_float), - ('mu0', ctypes.c_float), - ('Z', ctypes.c_float)] + ('logte', ctypes.c_float), + ('logg', ctypes.c_float), + ('Mass', ctypes.c_float), + ('Av', ctypes.c_float), + ('mu0', ctypes.c_float), + ('Z', ctypes.c_float)] + def get_bundleIndex(healpixID_ring, bundleOrder=4, healpixOrder=7): assert NSIDE == 2**healpixOrder @@ -58,17 +64,19 @@ def get_bundleIndex(healpixID_ring, bundleOrder=4, healpixOrder=7): shift = 2*shift nside_bundle = 2**bundleOrder - nside_healpix= 2**healpixOrder + nside_healpix = 2**healpixOrder - healpixID_nest= hp.ring2nest(nside_healpix, healpixID_ring) + healpixID_nest = hp.ring2nest(nside_healpix, healpixID_ring) bundleID_nest = (healpixID_nest >> shift) bundleID_ring = hp.nest2ring(nside_bundle, bundleID_nest) return bundleID_ring + def get_agnsed_file(bundle_file_name): return qsosed_file_list[bundle_file_list.index(bundle_file_name)] + def get_star_cat(ra_pointing, dec_pointing): pointing_c = SkyCoord(ra=ra_pointing*U.deg, dec=dec_pointing*U.deg) max_dist = 10 @@ -81,6 +89,7 @@ def get_star_cat(ra_pointing, dec_pointing): max_dist = dist return return_star_path + class Catalog(CatalogBase): def __init__(self, config, chip, pointing, chip_output, filt, **kwargs): super().__init__() @@ -92,9 +101,9 @@ class Catalog(CatalogBase): self.filt = filt self.logger = chip_output.logger - with pkg_resources.path('Catalog.data', 'SLOAN_SDSS.g.fits') as filter_path: + with pkg_resources.path('catalog.data', 'SLOAN_SDSS.g.fits') as filter_path: self.normF_star = Table.read(str(filter_path)) - + self.config = config self.chip = chip self.pointing = pointing @@ -103,12 +112,14 @@ class Catalog(CatalogBase): 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(ra_pointing=self.pointing.ra, dec_pointing=self.pointing.dec) - star_path = os.path.join(config["catalog_options"]["input_path"]["star_cat"], star_file_name) + star_file_name = get_star_cat( + ra_pointing=self.pointing.ra, dec_pointing=self.pointing.dec) + star_path = os.path.join( + config["catalog_options"]["input_path"]["star_cat"], star_file_name) self.star_path = os.path.join(self.cat_dir, star_path) self.star_SED_path = config["catalog_options"]["SED_templates_path"]["star_SED"] self._load_SED_lib_star() - + if "galaxy_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["galaxy_cat"] and not config["catalog_options"]["star_only"]: galaxy_dir = config["catalog_options"]["input_path"]["galaxy_cat"] self.galaxy_path = os.path.join(self.cat_dir, galaxy_dir) @@ -120,7 +131,8 @@ class Catalog(CatalogBase): self.AGN_SED_path = config["catalog_options"]["SED_templates_path"]["AGN_SED"] if "rotateEll" in config["catalog_options"]: - self.rotation = np.radians(float(config["catalog_options"]["rotateEll"])) + self.rotation = np.radians( + float(config["catalog_options"]["rotateEll"])) else: self.rotation = 0. @@ -129,17 +141,19 @@ class Catalog(CatalogBase): self._get_healpix_list() self._load() - + def _add_output_columns_header(self): self.add_hdr = " av stellarmass dm teff logg feh" self.add_hdr += " bulgemass diskmass detA e1 e2 kappa g1 g2 size galType veldisp " self.add_fmt = "%8.4f %8.4f %8.4f %8.4f %8.4f %8.4f" self.add_fmt += " %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %4d %8.4f " - self.chip_output.update_output_header(additional_column_names=self.add_hdr) + self.chip_output.update_output_header( + additional_column_names=self.add_hdr) def _get_healpix_list(self): - self.sky_coverage = self.chip.getSkyCoverageEnlarged(self.chip.img.wcs, margin=0.2) + 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])) @@ -167,27 +181,31 @@ class Catalog(CatalogBase): # self.tempSED_star = h5.File(self.star_SED_path,'r') def _load_SED_lib_star(self): # self.tempSED_star = h5.File(self.star_SED_path,'r') - with pkg_resources.path('Catalog.data', 'starSpecInterp.so') as ddl_path: + with pkg_resources.path('catalog.data', 'starSpecInterp.so') as ddl_path: self.starDDL = ctypes.CDLL(str(ddl_path)) - self.starDDL.loadSpecLibs.argtypes=[ctypes.c_char_p, ctypes.c_char_p] - self.starDDL.loadExts.argtypes=[ctypes.c_char_p] - nwv = self.starDDL.loadSpecLibs(str.encode(os.path.join(self.star_SED_path,'file_BT-Settl_CSST_wl1000-24000_R1000.par')),str.encode(self.star_SED_path)) - self.starDDL.loadExts(str.encode(os.path.join(self.star_SED_path,"Ext_odonnell94_R3.1_CSST_wl1000-24000_R1000.fits"))) + self.starDDL.loadSpecLibs.argtypes = [ctypes.c_char_p, ctypes.c_char_p] + self.starDDL.loadExts.argtypes = [ctypes.c_char_p] + nwv = self.starDDL.loadSpecLibs(str.encode(os.path.join( + self.star_SED_path, 'file_BT-Settl_CSST_wl1000-24000_R1000.par')), str.encode(self.star_SED_path)) + self.starDDL.loadExts(str.encode(os.path.join( + self.star_SED_path, "Ext_odonnell94_R3.1_CSST_wl1000-24000_R1000.fits"))) self.star_spec_len = nwv def _interp_star_sed(self, obj): spec = (ctypes.c_float*self.star_spec_len)() wave = (ctypes.c_float*self.star_spec_len)() - self.starDDL.interpSingleStar.argtypes=[ctypes.Structure, ctypes.POINTER(ctypes.c_float)] + self.starDDL.interpSingleStar.argtypes = [ + ctypes.Structure, ctypes.POINTER(ctypes.c_float)] # s=Star(obj.param['teff'], obj.param['grav''], obj.paramstar['mwmsc_mass'], obj.param['AV'], obj.param['DM'], obj.param['z_met']) - s=StarParm(obj.param['teff'], obj.param['logg'], obj.param['stellarMass'], obj.param['av'], obj.param['DM'], obj.param['feh']) + s = StarParm(obj.param['teff'], obj.param['logg'], obj.param['stellarMass'], + obj.param['av'], obj.param['DM'], obj.param['feh']) self.starDDL.interpSingleStar(s, spec, wave) rv_c = obj.param['rv']/(atcons.c.value/1000.) Doppler_factor = np.sqrt((1+rv_c)/(1-rv_c)) wave_RV = wave*Doppler_factor - return wave_RV, np.power(10,spec[:]) + return wave_RV, np.power(10, spec[:]) def _load_SED_lib_gals(self): pcs = h5.File(os.path.join(self.galaxy_SED_path, "pcs.h5"), "r") @@ -234,7 +252,7 @@ class Catalog(CatalogBase): # # (TEST) # if igals > 100: # break - + param = self.initialize_param() param['ra'] = ra_arr[igals] param['dec'] = dec_arr[igals] @@ -243,12 +261,13 @@ class Catalog(CatalogBase): if not self.chip.isContainObj(ra_obj=param['ra'], dec_obj=param['dec'], margin=200): continue - + # param['mag_use_normal'] = gals['mag_csst_%s'%(self.filt.filter_type)][igals] if self.filt.filter_type == 'NUV': param['mag_use_normal'] = gals['mag_csst_nuv'][igals] else: - param['mag_use_normal'] = gals['mag_csst_%s'%(self.filt.filter_type)][igals] + param['mag_use_normal'] = gals['mag_csst_%s' % + (self.filt.filter_type)][igals] if self.filt.is_too_dim(mag=param['mag_use_normal'], margin=self.config["obs_setting"]["mag_lim_margin"]): continue @@ -259,26 +278,25 @@ class Catalog(CatalogBase): param['kappa'] = gals['kappa'][igals] param['e1'] = gals['ellipticity_true'][igals][0] param['e2'] = gals['ellipticity_true'][igals][1] - + # For shape calculation param['e1'], param['e2'], param['ell_total'] = self.rotate_ellipticity( - e1=gals['ellipticity_true'][igals][0], - e2=gals['ellipticity_true'][igals][1], - rotation=self.rotation, - unit='radians') + e1=gals['ellipticity_true'][igals][0], + e2=gals['ellipticity_true'][igals][1], + rotation=self.rotation, + unit='radians') # param['ell_total'] = np.sqrt(param['e1']**2 + param['e2']**2) if param['ell_total'] > 0.9: continue # phi_e = cmath.phase(complex(param['e1'], param['e2'])) # param['e1'] = param['ell_total'] * np.cos(phi_e + 2*self.rotation) # param['e2'] = param['ell_total'] * np.sin(phi_e + 2*self.rotation) - + param['e1_disk'] = param['e1'] param['e2_disk'] = param['e2'] param['e1_bulge'] = param['e1'] param['e2_bulge'] = param['e2'] - param['delta_ra'] = 0 param['delta_dec'] = 0 @@ -295,7 +313,8 @@ class Catalog(CatalogBase): param['bulge_sersic_idx'] = 4. # Sizes - param['bfrac'] = param['bulgemass']/(param['bulgemass'] + param['diskmass']) + param['bfrac'] = param['bulgemass'] / \ + (param['bulgemass'] + param['diskmass']) if param['bfrac'] >= 0.6: param['hlr_bulge'] = param['size'] param['hlr_disk'] = param['size'] * (1. - param['bfrac']) @@ -310,14 +329,15 @@ class Catalog(CatalogBase): # Others param['galType'] = gals['type'][igals] param['veldisp'] = gals['veldisp'][igals] - + # TEST no redening and no extinction param['av'] = 0.0 param['redden'] = 0 # TEMP self.ids += 1 - param['id'] = '%06d'%(int(pix_id)) + '%06d'%(cat_id) + '%08d'%(igals) + param['id'] = '%06d' % (int(pix_id)) + \ + '%06d' % (cat_id) + '%08d' % (igals) # Is this an Quasar? param['qsoindex'] = gals['qsoindex'][igals] @@ -332,20 +352,20 @@ class Catalog(CatalogBase): # First add QSO model obj = Quasar(param_qso, logger=self.logger) # Need to deal with additional output columns - obj.additional_output_str = self.add_fmt%(0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., - 0, 0.) + obj.additional_output_str = self.add_fmt % (0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., + 0, 0.) self.objs.append(obj) # Then add host galaxy model param['star'] = 0 # Galaxy param['agnsed_file'] = "" obj = Galaxy(param, logger=self.logger) - + # Need to deal with additional output columns for (host) galaxy - obj.additional_output_str = self.add_fmt%(0., 0., 0., 0., 0., 0., - param['bulgemass'], param['diskmass'], param['detA'], - param['e1'], param['e2'], param['kappa'], param['g1'], param['g2'], param['size'], - param['galType'], param['veldisp']) - + obj.additional_output_str = self.add_fmt % (0., 0., 0., 0., 0., 0., + param['bulgemass'], param['diskmass'], param['detA'], + param['e1'], param['e2'], param['kappa'], param['g1'], param['g2'], param['size'], + param['galType'], param['veldisp']) + self.objs.append(obj) def _load_stars(self, stars, pix_id=None): @@ -386,7 +406,7 @@ class Catalog(CatalogBase): input_time_str=time_str ) for istars in range(nstars): - # (TEST) + # # (TEST) # if istars > 100: # break @@ -404,7 +424,7 @@ class Catalog(CatalogBase): param['mag_use_normal'] = stars['app_sdss_g'][istars] self.ids += 1 - param['id'] = '%06d'%(int(pix_id)) + '%08d'%(istars) + param['id'] = '%06d' % (int(pix_id)) + '%08d' % (istars) # param['sed_type'] = istars # param['model_tag'] = '' param['teff'] = stars['teff'][istars] @@ -412,29 +432,28 @@ class Catalog(CatalogBase): param['feh'] = stars['z_met'][istars] param['stellarMass'] = stars['mass'][istars] - param['av'] = stars['AV'][istars] param['DM'] = stars['DM'][istars] # param['z_met'] = stars['z_met'][istars] param['z'] = 0.0 param['star'] = 1 # Star - + try: obj = Star(param, logger=self.logger) except Exception as e: print(e) # Append additional output columns to the .cat file - obj.additional_output_str = self.add_fmt%(param["av"], param['stellarMass'], param['DM'], param['teff'], param['logg'], param['feh'], - 0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.) + obj.additional_output_str = self.add_fmt % (param["av"], param['stellarMass'], param['DM'], param['teff'], param['logg'], param['feh'], + 0., 0., 0., 0., 0., 0., 0., 0., 0., -1, 0.) self.objs.append(obj) def _load(self, **kwargs): self.objs = [] self.ids = 0 - + if "star_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["star_cat"] and not self.config["catalog_options"]["galaxy_only"]: star_cat = h5.File(self.star_path, 'r')['star_catalog'] for pix in self.pix_list: @@ -445,11 +464,11 @@ class Catalog(CatalogBase): except Exception as e: self.logger.error(str(e)) # print(e) - + if "galaxy_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["galaxy_cat"] and not self.config["catalog_options"]["star_only"]: for pix in self.pix_list: try: - bundleID = get_bundleIndex(pix) + bundleID = get_bundleIndex(pix) bundle_file = "galaxies_C6_bundle{:06}.h5".format(bundleID) file_path = os.path.join(self.galaxy_path, bundle_file) gals_cat = h5.File(file_path, 'r')['galaxies'] @@ -460,7 +479,8 @@ class Catalog(CatalogBase): agnsed_path = os.path.join(self.AGN_SED_path, agnsed_file) self.agn_seds[agnsed_file] = fits.open(agnsed_path)[0].data - self._load_gals(gals, pix_id=pix, cat_id=bundleID, agnsed_file=agnsed_file) + self._load_gals(gals, pix_id=pix, + cat_id=bundleID, agnsed_file=agnsed_file) del gals except Exception as e: @@ -469,8 +489,9 @@ class Catalog(CatalogBase): print(e) if self.logger is not None: - self.logger.info("maximum galaxy size: %.4f"%(self.max_size)) - self.logger.info("number of objects in catalog: %d"%(len(self.objs))) + self.logger.info("maximum galaxy size: %.4f" % (self.max_size)) + self.logger.info("number of objects in catalog: %d" % + (len(self.objs))) else: print("number of objects in catalog: ", len(self.objs)) @@ -500,7 +521,8 @@ class Catalog(CatalogBase): ) wave, flux = sed_data[0], sed_data[1] elif obj.type == 'quasar': - flux = self.agn_seds[obj.agnsed_file][int(obj.qsoindex)] * 1e-17 + flux = self.agn_seds[obj.agnsed_file][int( + obj.qsoindex)] * 1e-17 flux[flux < 0] = 0. wave = self.lamb_gal * (1.0 + obj.z) else: @@ -514,10 +536,14 @@ class Catalog(CatalogBase): 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) + 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'])) del wave diff --git a/Catalog/Catalog_example.py b/catalog/Catalog_example.py similarity index 94% rename from Catalog/Catalog_example.py rename to catalog/Catalog_example.py index 24c6cf66abab5fb67623c397cc4df3c320fc7495..99fb1768beac34319c2ef1efcbc4e743b72478f3 100644 --- a/Catalog/Catalog_example.py +++ b/catalog/Catalog_example.py @@ -4,15 +4,16 @@ import astropy.constants as cons from astropy.table import Table from scipy import interpolate -from ObservationSim.MockObject import CatalogBase, Star, Galaxy, Quasar +from observation_sim.mock_objects import CatalogBase, Star, Galaxy, Quasar + class Catalog(CatalogBase): """An user customizable class for reading in catalog(s) of objects and SEDs. - + NOTE: must inherit the "CatalogBase" abstract class ... - + Attributes ---------- cat_dir : str @@ -24,7 +25,7 @@ class Catalog(CatalogBase): objs : list a list of ObservationSim.MockObject (Star, Galaxy, or Quasar) NOTE: must have "obj" list when implement your own Catalog - + Methods ---------- load_sed(obj, **kwargs): @@ -32,9 +33,10 @@ class Catalog(CatalogBase): load_norm_filt(obj): load the filter throughput for the input catalog's photometric system. """ + def __init__(self, config, chip, **kwargs): """Constructor method. - + Parameters ---------- config : dict @@ -44,20 +46,22 @@ class Catalog(CatalogBase): **kwargs : dict other needed input parameters (in key-value pairs), please modify corresponding initialization call in "ObservationSim.py" as you need. - + Returns ---------- None """ - + super().__init__() - self.cat_dir = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["cat_dir"]) + self.cat_dir = os.path.join( + config["data_dir"], config["catalog_options"]["input_path"]["cat_dir"]) self.chip = chip if "star_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["star_cat"]: star_file = config["catalog_options"]["input_path"]["star_cat"] star_SED_file = config["catalog_options"]["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.star_SED_path = os.path.join( + config["data_dir"], star_SED_file) # NOTE: must call _load() method here to read in all objects self.objs = [] self._load() @@ -67,7 +71,7 @@ class Catalog(CatalogBase): This is a must implemented method which is used to read in all objects, and then convert them to ObservationSim.MockObject (Star, Galaxy, or Quasar). - + Currently, the model of ObservationSim.MockObject.Star class requires: param["star"] : int @@ -83,7 +87,7 @@ class Catalog(CatalogBase): NOTE: if that filter is not the corresponding CSST filter, the load_norm_filt(obj) function must be implemented to load the filter throughput of that particular photometric system - + the model of ObservationSim.MockObject.Galaxy class requires: param["star"] : int specify the object type: 0: galaxy, 1: star, 2: quasar @@ -173,7 +177,8 @@ class Catalog(CatalogBase): """ if obj.type == 'star': - wave = Table.read(self.star_SED_path, path=f"/SED/wave_{obj.model_tag}") + wave = Table.read(self.star_SED_path, + path=f"/SED/wave_{obj.model_tag}") flux = Table.read(self.star_SED_path, path=f"/SED/{obj.sed_type}") wave, flux = wave['col0'].data, flux['col0'].data else: @@ -203,4 +208,4 @@ class Catalog(CatalogBase): norm_filt["WAVELENGTH"] : wavelengthes in Angstroms norm_filt["SENSITIVITY"] : efficiencies """ - return None \ No newline at end of file + return None diff --git a/Catalog/data/SLOAN_SDSS.g.fits b/catalog/data/SLOAN_SDSS.g.fits similarity index 100% rename from Catalog/data/SLOAN_SDSS.g.fits rename to catalog/data/SLOAN_SDSS.g.fits diff --git a/Catalog/data/__init__.py b/catalog/data/__init__.py similarity index 100% rename from Catalog/data/__init__.py rename to catalog/data/__init__.py diff --git a/Catalog/data/lsst_throuput_g.fits b/catalog/data/lsst_throuput_g.fits similarity index 100% rename from Catalog/data/lsst_throuput_g.fits rename to catalog/data/lsst_throuput_g.fits diff --git a/Catalog/data/starSpecInterp.so b/catalog/data/starSpecInterp.so similarity index 100% rename from Catalog/data/starSpecInterp.so rename to catalog/data/starSpecInterp.so diff --git a/Catalog/testCat_fits.py b/catalog/testCat_fits.py similarity index 67% rename from Catalog/testCat_fits.py rename to catalog/testCat_fits.py index b148431b8489c92357fce6798596d63ba3c5c75d..6ae1bada7eb8b6ff34db22ec4aaa6f725de69219 100644 --- a/Catalog/testCat_fits.py +++ b/catalog/testCat_fits.py @@ -11,12 +11,12 @@ from astropy.table import Table from scipy import interpolate from datetime import datetime -from ObservationSim.MockObject import CatalogBase, Star, Galaxy, Quasar, Stamp -from ObservationSim.MockObject._util import tag_sed, getObservedSED, getABMAG, integrate_sed_bandpass, comoving_dist -from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position +from observation_sim.mock_objects import CatalogBase, Star, Galaxy, Quasar, Stamp +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 import astropy.io.fits as fitsio -from ObservationSim.MockObject._util import seds, sed_assign, extAv +from observation_sim.mock_objects._util import seds, sed_assign, extAv # (TEST) from astropy.cosmology import FlatLambdaCDM @@ -31,11 +31,12 @@ except ImportError: NSIDE = 128 + class Catalog(CatalogBase): def __init__(self, config, chip, pointing, chip_output, filt, **kwargs): super().__init__() - self.cat_dir = os.path.join(config["data_dir"], config["catalog_options"]["input_path"]["cat_dir"]) - self.seed_Av = config["catalog_options"]["seed_Av"] + self.cat_dir = config["catalog_options"]["input_path"]["cat_dir"] + self.seed_Av = 121212 # config["catalog_options"]["seed_Av"] # (TEST) self.cosmo = FlatLambdaCDM(H0=67.66, Om0=0.3111) @@ -44,9 +45,11 @@ class Catalog(CatalogBase): self.filt = filt self.logger = chip_output.logger - with pkg_resources.path('Catalog.data', 'SLOAN_SDSS.g.fits') as filter_path: + 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 @@ -56,31 +59,27 @@ class Catalog(CatalogBase): if "stamp_cat" in config["catalog_options"]["input_path"] and config["catalog_options"]["input_path"]["stamp_cat"] and config["catalog_options"]["stamp_yes"]: stamp_file = config["catalog_options"]["input_path"]["stamp_cat"] self.stamp_path = os.path.join(self.cat_dir, stamp_file) - #self.stamp_SED_path = os.path.join(config["data_dir"], config["SED_templates_path"]["stamp_SED"]) ###shoule be stamp-SED - #self._load_SED_lib_stamps() ###shoule be stamp-SED - self.tempSed_gal, self.tempRed_gal = seds("galaxy.list", seddir="/share/simudata/CSSOSDataProductsSims/data/Templates/Galaxy/") #only for test - - if "rotateEll" in config["catalog_options"]: - self.rotation = float(int(config["catalog_options"]["rotateEll"]/45.)) - else: - self.rotation = 0. + # self.stamp_SED_path = os.path.join(config["data_dir"], config["SED_templates_path"]["stamp_SED"]) ###shoule be stamp-SED + # self._load_SED_lib_stamps() ###shoule be stamp-SED + self.tempSed_gal, self.tempRed_gal = seds( + "galaxy.list", seddir="/public/home/chengliang/CSSOSDataProductsSims/testCats/Templates/Galaxy/") # only for test - # Update output .cat header with catalog specific output columns self._add_output_columns_header() - self._get_healpix_list() self._load() - + def _add_output_columns_header(self): self.add_hdr = " model_tag teff logg feh" self.add_hdr += " bulgemass diskmass detA e1 e2 kappa g1 g2 size galType veldisp " self.add_fmt = " %10s %8.4f %8.4f %8.4f" self.add_fmt += " %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %4d %8.4f " - self.chip_output.update_output_header(additional_column_names=self.add_hdr) + self.chip_output.update_output_header( + additional_column_names=self.add_hdr) def _get_healpix_list(self): - self.sky_coverage = self.chip.getSkyCoverageEnlarged(self.chip.img.wcs, margin=0.2) + 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])) @@ -99,41 +98,46 @@ class Catalog(CatalogBase): def load_norm_filt(self, obj): if obj.type == "stamp": - #return self.normF_galaxy ###normalize_filter for stamp - return None + return self.normF_galaxy # normalize_filter for stamp else: return None def _load_stamps(self, stamps, pix_id=None): + print("debug:: load_stamps") nstamps = len(stamps['filename']) self.rng_sedGal = random.Random() - self.rng_sedGal.seed(pix_id) # Use healpix index as the random seed + # Use healpix index as the random seed + self.rng_sedGal.seed(float(pix_id)) self.ud = galsim.UniformDeviate(pix_id) for istamp in range(nstamps): - fitsfile = os.path.join(self.cat_dir, "stampCats/"+stamps['filename'][istamp].decode('utf-8')) - hdu=fitsio.open(fitsfile) + print("debug::", istamp) + fitsfile = os.path.join( + self.cat_dir, "stampCats/"+stamps['filename'][istamp].decode('utf-8')) + print("debug::", istamp, fitsfile) + hdu = fitsio.open(fitsfile) param = self.initialize_param() - param['id'] = hdu[0].header['index'] #istamp + param['id'] = hdu[0].header['index'] # istamp param['star'] = 3 # Stamp type in .cat file param['ra'] = hdu[0].header['ra'] - param['dec']= hdu[0].header['dec'] - param['pixScale']= hdu[0].header['pixScale'] - #param['srcGalaxyID'] = hdu[0].header['srcGID'] - #param['mu']= hdu[0].header['mu'] - #param['PA']= hdu[0].header['PA'] - #param['bfrac']= hdu[0].header['bfrac'] - #param['z']= hdu[0].header['z'] - param['mag_use_normal'] = hdu[0].header['mag_g'] #gals['mag_true_g_lsst'] + param['dec'] = hdu[0].header['dec'] + param['pixScale'] = hdu[0].header['pixScale'] + # param['srcGalaxyID'] = hdu[0].header['srcGID'] + # param['mu']= hdu[0].header['mu'] + # param['PA']= hdu[0].header['PA'] + # param['bfrac']= hdu[0].header['bfrac'] + # param['z']= hdu[0].header['z'] + # gals['mag_true_g_lsst'] + param['mag_use_normal'] = hdu[0].header['mag_g'] # Apply astrometric modeling # in C3 case only aberration param['ra_orig'] = param['ra'] - param['dec_orig']= param['dec'] + param['dec_orig'] = param['dec'] if self.config["obs_setting"]["enable_astrometric_model"]: - ra_list = [param['ra']] #ra_arr.tolist() - dec_list= [param['dec']] #dec_arr.tolist() + ra_list = [param['ra']] # ra_arr.tolist() + dec_list = [param['dec']] # dec_arr.tolist() pmra_list = np.zeros(1).tolist() pmdec_list = np.zeros(1).tolist() rv_list = np.zeros(1).tolist() @@ -160,18 +164,20 @@ class Catalog(CatalogBase): input_time_str=time_str ) param['ra'] = ra_arr[0] - param['dec']= dec_arr[0] + param['dec'] = dec_arr[0] # Assign each galaxy a template SED - param['sed_type'] = sed_assign(phz=param['z'], btt=param['bfrac'], rng=self.rng_sedGal) + 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'] = 0.0 param['redden'] = 0 + param['mu'] = 1 - #param["CSSTmag"]= True - #param["mag_r"] = 20. - #param[''] - ###more keywords for stamp### + # param["CSSTmag"]= True + # param["mag_r"] = 20. + # param[''] + ### more keywords for stamp### param['image'] = hdu[0].data param['image'] = param['image']/(np.sum(param['image'])) obj = Stamp(param) @@ -183,9 +189,12 @@ class Catalog(CatalogBase): if "stamp_cat" in self.config["catalog_options"]["input_path"] and self.config["catalog_options"]["input_path"]["stamp_cat"] and self.config["catalog_options"]["stamp_yes"]: stamps_cat = h5.File(self.stamp_path, 'r')['Stamps'] + print("debug::", stamps_cat.keys()) + for pix in self.pix_list: try: stamps = stamps_cat[str(pix)] + print("debug::", stamps.keys()) self._load_stamps(stamps, pix_id=pix) del stamps except Exception as e: @@ -193,12 +202,12 @@ class Catalog(CatalogBase): print(e) if self.logger is not None: - self.logger.info("maximum galaxy size: %.4f"%(self.max_size)) - self.logger.info("number of objects in catalog: %d"%(len(self.objs))) + self.logger.info("maximum galaxy size: %.4f" % (self.max_size)) + self.logger.info("number of objects in catalog: %d" % + (len(self.objs))) else: print("number of objects in catalog: ", len(self.objs)) - def load_sed(self, obj, **kwargs): if obj.type == 'stamp': sed_data = getObservedSED( @@ -216,7 +225,7 @@ class Catalog(CatalogBase): # 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')) - + del wave del flux return sed diff --git a/config/config_50sqdeg.yaml b/config/config_50sqdeg.yaml deleted file mode 100644 index f28a4cc01bfdcc891b036a8be3fcde11a86d20cc..0000000000000000000000000000000000000000 --- a/config/config_50sqdeg.yaml +++ /dev/null @@ -1,222 +0,0 @@ ---- -############################################### -# -# Configuration file for CSST simulation -# CSST-Sim Group, 2023/04/25 -# -############################################### - -# Base diretories and naming setup -# 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: "/share/home/weichengliang/CSST_git/test_new_sim/outputs/" -data_dir: "/share/simudata/CSSOSDataProductsSims/data/" -run_name: "testRun0" - -# Whether to use MPI -run_option: - # NOTE: "n_threads" paramters is currently not used in the backend - # simulation codes. It should be implemented later in the web frontend - # in order to config the number of threads to request from NAOC cluster - n_threads: 80 - - # Output catalog only? - # If yes, no imaging simulation will run - out_cat_only: NO - -############################################### -# Catalog setting -############################################### -# Configure your catalog: options to be implemented -# in the corresponding (user defined) 'Catalog' class -catalog_options: - input_path: - cat_dir: "" - # star_cat: "C6_MMW_GGC_Astrometry_healpix.hdf5" - star_cat: "starcat/" - galaxy_cat: "qsocat/cat2CSSTSim_bundle-50sqDeg/" - # AGN_cat: "AGN_C6_ross13_rand_pos_rmax-1.3.fits" - - SED_templates_path: - star_SED: "Catalog_20210126/SpecLib.hdf5" - galaxy_SED: "Catalog_C6_20221212/sedlibs/" - AGN_SED: "qsocat/qsosed/" - # AGN_SED_WAVE: "wave_ross13.npy" - - # Only simulate stars? - star_only: YES - - # Only simulate galaxies? - galaxy_only: NO - - # rotate galaxy ellipticity - rotateEll: 0. # [degree] - - seed_Av: 121212 # Seed for generating random intrinsic extinction - -############################################### -# Observation setting -############################################### -obs_setting: - - # Options for survey types: - # "Photometric": simulate photometric chips only - # "Spectroscopic": simulate slitless spectroscopic chips only - # "FGS": simulate FGS chips only (31-42) - # "All": simulate full focal plane - survey_type: "Photometric" - - # Exposure time [seconds] - exp_time: 150. - - # Observation starting date & time - date_obs: "210525" # [yymmdd] - time_obs: "120000" # [hhmmss] - - # Default Pointing [degrees] - # Note: NOT valid when a pointing list file is specified - ra_center: 192.8595 - dec_center: 27.1283 - # Image rotation [degree] - image_rot: -113.4333 - - # (Optional) a file of point list - # if you just want to run default pointing: - # - pointing_dir: null - # - pointing_file: null - pointing_dir: "/share/simudata/CSSOSDataProductsSims/data/" - pointing_file: "pointing_50_combined.dat" - - # Number of calibration pointings - np_cal: 0 - - # Run specific pointing(s): - # - 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: [0] - - # Run specific chip(s): - # - give a list of indexes of chips: [ip_1, ip_2...] - # - run all chips: null - # Note: for all pointings - run_chips: [8] - - # Whether to enable astrometric modeling - enable_astrometric_model: True - - # Whether to enable straylight model - enable_straylight_model: True - - # Cut by saturation magnitude in which band? - cut_in_band: "z" - - # saturation magnitude margin - mag_sat_margin: -2.5 - - # limiting magnitude margin - mag_lim_margin: +1.0 - -############################################### -# PSF setting -############################################### -psf_setting: - - # Which PSF model to use: - # "Gauss": simple gaussian profile - # "Interp": Interpolated PSF from sampled ray-tracing data - psf_model: "Interp" - - # PSF size [arcseconds] - # radius of 80% energy encircled - # NOTE: only valid for "Gauss" PSF - psf_rcont: 0.15 - - # path to PSF data - # NOTE: only valid for "Interp" PSF - psf_dir: "/share/simudata/CSSOSDataProductsSims/data/psfCube1" - -############################################### -# Shear setting -############################################### - -shear_setting: - # Options to generate mock shear field: - # "constant": all galaxies are assigned a constant reduced shear - # "catalog": from catalog - shear_type: "catalog" - - # For constant shear filed - reduced_g1: 0. - reduced_g2: 0. - -############################################### -# Instrumental effects setting -############################################### -ins_effects: - # switches - # Note: bias_16channel, gain_16channel, and shutter_effect - # is currently not applicable to "FGS" observations - field_dist: ON # Whether to add field distortions - add_back: ON # Whether to add sky background - add_dark: ON # Whether to add dark noise - add_readout: ON # Whether to add read-out (Gaussian) noise - add_bias: ON # Whether to add bias-level to images - add_prescan: OFF - bias_16channel: ON # Whether to add different biases for 16 channels - gain_16channel: ON # Whether to make different gains for 16 channels - shutter_effect: ON # Whether to add shutter effect - flat_fielding: ON # Whether to add flat-fielding effect - prnu_effect: ON # Whether to add PRNU effect - non_linear: ON # Whether to add non-linearity - cosmic_ray: ON # Whether to add cosmic-ray - cray_differ: ON # Whether to generate different cosmic ray maps CAL and MS output - cte_trail: OFF # Whether to simulate CTE trails - saturbloom: ON # Whether to simulate Saturation & Blooming - add_badcolumns: ON # Whether to add bad columns - add_hotpixels: ON # Whether to add hot pixels - add_deadpixels: ON # Whether to add dead(dark) pixels - bright_fatter: ON # Whether to simulate Brighter-Fatter (also diffusion) effect - format_output: OFF - - # Values: - # default values have been defined individually for each chip in: - # ObservationSim/Instrument/data/ccd/chip_definition.json - # Set them here will override the default values - # dark_exptime: 300 # Exposure time for dark current frames [seconds] - # flat_exptime: 150 # Exposure time for flat-fielding frames [seconds] - # readout_time: 40 # The read-out time for each channel [seconds] - # df_strength: 2.3 # Sillicon sensor diffusion strength - # bias_level: 500 # bias level [e-/pixel] - # gain: 1.1 # Gain - # full_well: 90000 # Full well depth [e-] - -############################################### -# Output options (for calibration pointings only) -############################################### -output_setting: - readout16: OFF # Whether to export as 16 channels (subimages) with pre- and over-scan - shutter_output: OFF # Whether to export shutter effect 16-bit image - bias_output: ON # Whether to export bias frames - dark_output: ON # Whether to export the combined dark current files - flat_output: ON # Whether to export the combined flat-fielding files - prnu_output: OFF # Whether to export the PRNU (pixel-to-pixel flat-fielding) files - NBias: 1 # Number of bias frames to be exported for each exposure - NDark: 1 # Number of dark frames to be exported for each exposure - NFlat: 1 # Number of flat frames to be exported for each exposure - -############################################### -# Random seeds -############################################### -random_seeds: - seed_poisson: 20210601 # Seed for Poisson noise - seed_CR: 20210317 # Seed for generating random cosmic ray maps - seed_flat: 20210101 # Seed for generating random flat fields - seed_prnu: 20210102 # Seed for photo-response non-uniformity - seed_gainNonUniform: 20210202 # Seed for gain nonuniformity - seed_biasNonUniform: 20210203 # Seed for bias nonuniformity - seed_rnNonUniform: 20210204 # Seed for readout-noise nonuniformity - seed_badcolumns: 20240309 # Seed for bad columns - seed_defective: 20210304 # Seed for defective (bad) pixels - seed_readout: 20210601 # Seed for read-out gaussian noise -... diff --git a/config/config_C6.yaml b/config/config_C6.yaml deleted file mode 100644 index 5c7ebe6ede17d86d41d3366c3dfdd5627698844d..0000000000000000000000000000000000000000 --- a/config/config_C6.yaml +++ /dev/null @@ -1,223 +0,0 @@ ---- -############################################### -# -# Configuration file for CSST simulation -# CSST-Sim Group, 2023/04/25 -# -############################################### - -# Base diretories and naming setup -# 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: "/share/home/fangyuedong/new_sim/workplace/" -# work_dir: "/share/C6_new_sim_2sq" -data_dir: "/share/simudata/CSSOSDataProductsSims/data/" -run_name: "C6_new_sim_2sq_run1" -project_cycle: 6 -run_counter: 1 - -# Whether to use MPI -run_option: - # NOTE: "n_threads" paramters is currently not used in the backend - # simulation codes. It should be implemented later in the web frontend - # in order to config the number of threads to request from NAOC cluster - n_threads: 80 - - # Output catalog only? - # If yes, no imaging simulation will run - out_cat_only: NO - -############################################### -# Catalog setting -############################################### -# Configure your catalog: options to be implemented -# in the corresponding (user defined) 'Catalog' class -catalog_options: - input_path: - cat_dir: "Catalog_C6_20221212" - star_cat: "C6_MMW_GGC_Astrometry_healpix.hdf5" - galaxy_cat: "cat2CSSTSim_bundle/" - AGN_cat: "AGN_C6_ross13_rand_pos_rmax-1.3.fits" - - SED_templates_path: - star_SED: "Catalog_20210126/SpecLib.hdf5" - galaxy_SED: "Catalog_C6_20221212/sedlibs/" - AGN_SED: "quickspeclib_ross13.fits" - AGN_SED_WAVE: "wave_ross13.npy" - - # Only simulate stars? - star_only: YES - - # Only simulate galaxies? - galaxy_only: NO - - # rotate galaxy ellipticity - rotateEll: 0. # [degree] - - seed_Av: 121212 # Seed for generating random intrinsic extinction - -############################################### -# Observation setting -############################################### -obs_setting: - - # Options for survey types: - # "Photometric": simulate photometric chips only - # "Spectroscopic": simulate slitless spectroscopic chips only - # "FGS": simulate FGS chips only (31-42) - # "All": simulate full focal plane - survey_type: "Photometric" - - # Exposure time [seconds] - exp_time: 150. - - # Observation starting date & time - date_obs: "210525" # [yymmdd] - time_obs: "120000" # [hhmmss] - - # Default Pointing [degrees] - # Note: NOT valid when a pointing list file is specified - ra_center: 192.8595 - dec_center: 27.1283 - # Image rotation [degree] - image_rot: -113.4333 - - # (Optional) a file of point list - # if you just want to run default pointing: - # - pointing_dir: null - # - pointing_file: null - pointing_dir: "/share/simudata/CSSOSDataProductsSims/data/" - pointing_file: "pointing_radec_246.5_40.dat" - - # Number of calibration pointings - np_cal: 0 - - # Run specific pointing(s): - # - 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: [0] - - # Run specific chip(s): - # - give a list of indexes of chips: [ip_1, ip_2...] - # - run all chips: null - # Note: for all pointings - run_chips: [8] - - # Whether to enable astrometric modeling - enable_astrometric_model: True - - # Whether to enable straylight model - enable_straylight_model: True - - # Cut by saturation magnitude in which band? - cut_in_band: "z" - - # saturation magnitude margin - # mag_sat_margin: -2.5 - mag_sat_margin: -15. - - # limiting magnitude margin - mag_lim_margin: +1.0 - -############################################### -# PSF setting -############################################### -psf_setting: - - # Which PSF model to use: - # "Gauss": simple gaussian profile - # "Interp": Interpolated PSF from sampled ray-tracing data - psf_model: "Interp" - - # PSF size [arcseconds] - # radius of 80% energy encircled - # NOTE: only valid for "Gauss" PSF - psf_rcont: 0.15 - - # path to PSF data - # NOTE: only valid for "Interp" PSF - psf_dir: "/share/simudata/CSSOSDataProductsSims/data/psfCube1" - psf_sls_dir: "/share/simudata/CSSOSDataProductsSims/data/SLS_PSF_PCA_fp/" -############################################### -# Shear setting -############################################### - -shear_setting: - # Options to generate mock shear field: - # "constant": all galaxies are assigned a constant reduced shear - # "catalog": from catalog - shear_type: "catalog" - - # For constant shear filed - reduced_g1: 0. - reduced_g2: 0. - -############################################### -# Instrumental effects setting -############################################### -ins_effects: - # switches - # Note: bias_16channel, gain_16channel, and shutter_effect - # is currently not applicable to "FGS" observations - field_dist: YES # Whether to add field distortions - add_back: YES # Whether to add sky background - add_dark: YES # Whether to add dark noise - add_readout: YES # Whether to add read-out (Gaussian) noise - add_bias: YES # Whether to add bias-level to images - bias_16channel: YES # Whether to add different biases for 16 channels - gain_16channel: YES # Whether to make different gains for 16 channels - shutter_effect: YES # Whether to add shutter effect - flat_fielding: YES # Whether to add flat-fielding effect - prnu_effect: YES # Whether to add PRNU effect - non_linear: YES # Whether to add non-linearity - cosmic_ray: YES # Whether to add cosmic-ray - cray_differ: YES # Whether to generate different cosmic ray maps CAL and MS output - cte_trail: YES # Whether to simulate CTE trails - saturbloom: YES # Whether to simulate Saturation & Blooming - add_badcolumns: YES # Whether to add bad columns - add_hotpixels: YES # Whether to add hot pixels - add_deadpixels: YES # Whether to add dead(dark) pixels - bright_fatter: YES # Whether to simulate Brighter-Fatter (also diffusion) effect - - # Values: - # default values have been defined individually for each chip in: - # ObservationSim/Instrument/data/ccd/chip_definition.json - # Set them here will override the default values - # dark_exptime: 300 # Exposure time for dark current frames [seconds] - # flat_exptime: 150 # Exposure time for flat-fielding frames [seconds] - # readout_time: 40 # The read-out time for each channel [seconds] - # df_strength: 2.3 # Sillicon sensor diffusion strength - # bias_level: 500 # bias level [e-/pixel] - # gain: 1.1 # Gain - # full_well: 90000 # Full well depth [e-] - -############################################### -# Output options (for calibration pointings only) -############################################### -output_setting: - readout16: OFF # Whether to export as 16 channels (subimages) with pre- and over-scan - shutter_output: OFF # Whether to export shutter effect 16-bit image - bias_output: ON # Whether to export bias frames - dark_output: ON # Whether to export the combined dark current files - flat_output: ON # Whether to export the combined flat-fielding files - prnu_output: OFF # Whether to export the PRNU (pixel-to-pixel flat-fielding) files - NBias: 1 # Number of bias frames to be exported for each exposure - NDark: 1 # Number of dark frames to be exported for each exposure - NFlat: 1 # Number of flat frames to be exported for each exposure - -############################################### -# Random seeds -############################################### -random_seeds: - seed_poisson: 20210601 # Seed for Poisson noise - seed_CR: 20210317 # Seed for generating random cosmic ray maps - seed_flat: 20210101 # Seed for generating random flat fields - seed_prnu: 20210102 # Seed for photo-response non-uniformity - seed_gainNonUniform: 20210202 # Seed for gain nonuniformity - seed_biasNonUniform: 20210203 # Seed for bias nonuniformity - seed_rnNonUniform: 20210204 # Seed for readout-noise nonuniformity - seed_badcolumns: 20240309 # Seed for bad columns - seed_defective: 20210304 # Seed for defective (bad) pixels - seed_readout: 20210601 # Seed for read-out gaussian noise -... diff --git a/config/config_C6_dev.yaml b/config/config_C6_dev.yaml deleted file mode 100644 index dd619d58f6f4607253e399cccccaa61167147d14..0000000000000000000000000000000000000000 --- a/config/config_C6_dev.yaml +++ /dev/null @@ -1,234 +0,0 @@ ---- -############################################### -# -# Configuration file for CSST simulation -# CSST-Sim Group, 2023/04/25 -# -############################################### - -# Base diretories and naming setup -# 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: "/share/home/fangyuedong/20231211/workplace/" -data_dir: "/share/simudata/CSSOSDataProductsSims/data/" -run_name: "test_spec" -project_cycle: 6 -run_counter: 1 - -# Whether to use MPI -run_option: - # NOTE: "n_threads" paramters is currently not used in the backend - # simulation codes. It should be implemented later in the web frontend - # in order to config the number of threads to request from NAOC cluster - n_threads: 80 - - # Output catalog only? - # If yes, no imaging simulation will run - out_cat_only: NO - -############################################### -# Catalog setting -############################################### -# Configure your catalog: options to be implemented -# in the corresponding (user defined) 'Catalog' class -catalog_options: - input_path: - cat_dir: "Catalog_C6_20221212" - star_cat: "C6_MMW_GGC_Astrometry_healpix.hdf5" - galaxy_cat: "cat2CSSTSim_bundle/" - AGN_cat: "AGN_C6_ross13_rand_pos_rmax-1.3.fits" - - SED_templates_path: - star_SED: "Catalog_20210126/SpecLib.hdf5" - galaxy_SED: "Catalog_C6_20221212/sedlibs/" - AGN_SED: "quickspeclib_ross13.fits" - AGN_SED_WAVE: "wave_ross13.npy" - - # Only simulate stars? - star_only: NO - - # Only simulate galaxies? - galaxy_only: NO - - # rotate galaxy ellipticity - rotateEll: 0. # [degree] - - seed_Av: 121212 # Seed for generating random intrinsic extinction - -############################################### -# Observation setting -############################################### -obs_setting: - - # Options for survey types: - # "Photometric": simulate photometric chips only - # "Spectroscopic": simulate slitless spectroscopic chips only - # "FGS": simulate FGS chips only (31-42) - # "All": simulate full focal plane - # "CALIBRATION": falt, bias, dark with or without postflash - survey_type: "Spectroscopic" - #"LED": ['LED1','LED2','LED3','LED4','LED5','LED6','LED7','LED8','LED9','LED10','LED11','LED12','LED13','LED14'] or null - #'LED1': '275', 'LED2': '310', 'LED3': '430', 'LED4': '505', 'LED5': '545', 'LED6': '590', 'LED7': '670', - #'LED8': '760', 'LED9': '940', 'LED10': '940', 'LED11': '1050', 'LED12': '1050','LED13': '340', 'LED14': '365' - LED_TYPE: ['LED5'] - LED_TIME: [1.] - # unit e- ,flat level - FLAT_LEVEL: 20000 - FLAT_LEVEL_FIL: 'g' - - # Exposure time [seconds] - exp_time: 150. - - # Observation starting date & time - date_obs: "210525" # [yymmdd] - time_obs: "120000" # [hhmmss] - - # Default Pointing [degrees] - # Note: NOT valid when a pointing list file is specified - ra_center: 192.8595 - dec_center: 27.1283 - # Image rotation [degree] - image_rot: -113.4333 - - # (Optional) a file of point list - # if you just want to run default pointing: - # - pointing_dir: null - # - pointing_file: null - pointing_dir: "/share/simudata/CSSOSDataProductsSims/data/" - pointing_file: "pointing_radec_246.5_40.dat" - - # Number of calibration pointings - np_cal: 0 - - # Run specific pointing(s): - # - 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: [0] - - # Run specific chip(s): - # - give a list of indexes of chips: [ip_1, ip_2...] - # - run all chips: null - # Note: for all pointings - run_chips: [1] - - # Whether to enable astrometric modeling - enable_astrometric_model: True - - # Whether to enable straylight model - enable_straylight_model: True - - # Cut by saturation magnitude in which band? - cut_in_band: "z" - - # saturation magnitude margin - # mag_sat_margin: -2.5 - mag_sat_margin: -15. - - # limiting magnitude margin - mag_lim_margin: +1.0 - -############################################### -# PSF setting -############################################### -psf_setting: - - # Which PSF model to use: - # "Gauss": simple gaussian profile - # "Interp": Interpolated PSF from sampled ray-tracing data - psf_model: "Interp" - - # PSF size [arcseconds] - # radius of 80% energy encircled - # NOTE: only valid for "Gauss" PSF - psf_rcont: 0.15 - - # path to PSF data - # NOTE: only valid for "Interp" PSF - psf_dir: "/share/simudata/CSSOSDataProductsSims/data/psfCube1" - psf_sls_dir: "/share/simudata/CSSOSDataProductsSims/data/SLS_PSF_PCA_fp/" -############################################### -# Shear setting -############################################### - -shear_setting: - # Options to generate mock shear field: - # "constant": all galaxies are assigned a constant reduced shear - # "catalog": from catalog - shear_type: "catalog" - - # For constant shear filed - reduced_g1: 0. - reduced_g2: 0. - -############################################### -# Instrumental effects setting -############################################### -ins_effects: - # switches - # Note: bias_16channel, gain_16channel, and shutter_effect - # is currently not applicable to "FGS" observations - field_dist: YES # Whether to add field distortions - add_back: YES # Whether to add sky background - add_dark: YES # Whether to add dark noise - add_readout: YES # Whether to add read-out (Gaussian) noise - add_bias: YES # Whether to add bias-level to images - add_prescan: YES - bias_16channel: YES # Whether to add different biases for 16 channels - gain_16channel: YES # Whether to make different gains for 16 channels - shutter_effect: YES # Whether to add shutter effect - flat_fielding: YES # Whether to add flat-fielding effect - prnu_effect: YES # Whether to add PRNU effect - non_linear: YES # Whether to add non-linearity - cosmic_ray: YES # Whether to add cosmic-ray - cray_differ: YES # Whether to generate different cosmic ray maps CAL and MS output - cte_trail: YES # Whether to simulate CTE trails, CTI_lgl_v0.3.tar.gz - saturbloom: YES # Whether to simulate Saturation & Blooming - add_badcolumns: YES # Whether to add bad columns - add_hotpixels: YES # Whether to add hot pixels - add_deadpixels: YES # Whether to add dead(dark) pixels - bright_fatter: YES # Whether to simulate Brighter-Fatter (also diffusion) effect - add_prescan: YES # Whether to add pre/over-scan - format_output: YES ##1*16 output - - # Values: - # default values have been defined individually for each chip in: - # ObservationSim/Instrument/data/ccd/chip_definition.json - # Set them here will override the default values - # dark_exptime: 300 # Exposure time for dark current frames [seconds] - # flat_exptime: 150 # Exposure time for flat-fielding frames [seconds] - # readout_time: 40 # The read-out time for each channel [seconds] - # df_strength: 2.3 # Sillicon sensor diffusion strength - # bias_level: 500 # bias level [e-/pixel] - # gain: 1.1 # Gain - # full_well: 90000 # Full well depth [e-] - -############################################### -# Output options (for calibration pointings only) -############################################### -output_setting: - readout16: OFF # Whether to export as 16 channels (subimages) with pre- and over-scan - shutter_output: OFF # Whether to export shutter effect 16-bit image - bias_output: ON # Whether to export bias frames - dark_output: ON # Whether to export the combined dark current files - flat_output: ON # Whether to export the combined flat-fielding files - prnu_output: OFF # Whether to export the PRNU (pixel-to-pixel flat-fielding) files - NBias: 1 # Number of bias frames to be exported for each exposure - NDark: 1 # Number of dark frames to be exported for each exposure - NFlat: 1 # Number of flat frames to be exported for each exposure - -############################################### -# Random seeds -############################################### -random_seeds: - seed_poisson: 20210601 # Seed for Poisson noise - seed_CR: 20210317 # Seed for generating random cosmic ray maps - seed_flat: 20210101 # Seed for generating random flat fields - seed_prnu: 20210102 # Seed for photo-response non-uniformity - seed_gainNonUniform: 20210202 # Seed for gain nonuniformity - seed_biasNonUniform: 20210203 # Seed for bias nonuniformity - seed_rnNonUniform: 20210204 # Seed for readout-noise nonuniformity - seed_badcolumns: 20240309 # Seed for bad columns - seed_defective: 20210304 # Seed for defective (bad) pixels - seed_readout: 20210601 # Seed for read-out gaussian noise -... diff --git a/config/config_C6_fits.yaml b/config/config_C6_fits.yaml deleted file mode 100644 index 2c91057b4b51c376a6905c11f2daabad6bc92ebc..0000000000000000000000000000000000000000 --- a/config/config_C6_fits.yaml +++ /dev/null @@ -1,241 +0,0 @@ ---- -############################################### -# -# Configuration file for CSST simulation -# CSST-Sim Group, 2023/04/25 -# -############################################### - -# Base diretories and naming setup -# 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: "/share/simudata/CSSOSDataProductsSims/data/CSSTSimImage_C8/" -data_dir: "/share/simudata/CSSOSDataProductsSims/data/" -run_name: "testRun_FGS" -project_cycle: 6 -run_counter: 1 - -# Whether to use MPI -run_option: - # NOTE: "n_threads" paramters is currently not used in the backend - # simulation codes. It should be implemented later in the web frontend - # in order to config the number of threads to request from NAOC cluster - n_threads: 80 - - # Output catalog only? - # If yes, no imaging simulation will run - out_cat_only: NO - - #output PSF - out_psf: YES - -############################################### -# Catalog setting -############################################### -# Configure your catalog: options to be implemented -# in the corresponding (user defined) 'Catalog' class -catalog_options: - input_path: - cat_dir: "Catalog_C6_20221212" - star_cat: "C6_MMW_GGC_Astrometry_healpix.hdf5" - galaxy_cat: "cat2CSSTSim_bundle/" - AGN_cat: "AGN_C6_ross13_rand_pos_rmax-1.3.fits" - stamp_cat: "stampCatsIndex.hdf5" - - SED_templates_path: - star_SED: "Catalog_20210126/SpecLib.hdf5" - galaxy_SED: "Catalog_C6_20221212/sedlibs/" - AGN_SED: "quickspeclib_ross13.fits" - AGN_SED_WAVE: "wave_ross13.npy" - #stamp_SED: - - # Only simulate stars? - star_only: YES - - # Only simulate galaxies? - galaxy_only: NO - - # With stamp? - stamp_yes: NO - - # rotate galaxy ellipticity - rotateEll: 0. # [degree] - - seed_Av: 121212 # Seed for generating random intrinsic extinction - -############################################### -# Observation setting -############################################### -obs_setting: - - # Options for survey types: - # "Photometric": simulate photometric chips only - # "Spectroscopic": simulate slitless spectroscopic chips only - # "FGS": simulate FGS chips only (31-42) - # "All": simulate full focal plane - # "CALIBRATION": falt, bias, dark with or without postflash - survey_type: "All" - # "LED": ['LED1','LED2','LED3','LED4','LED5','LED6','LED7','LED8','LED9','LED10','LED11','LED12','LED13','LED14'] or null - # 'LED1': '275', 'LED2': '310', 'LED3': '430', 'LED4': '505', 'LED5': '545', 'LED6': '590', 'LED7': '670', - # 'LED8': '760', 'LED9': '940', 'LED10': '940', 'LED11': '1050', 'LED12': '1050','LED13': '340', 'LED14': '365' - # LED_TYPE: ['LED5'] - # LED_TIME: [1.] - # # unit e- ,flat level - # FLAT_LEVEL: 20000 - # FLAT_LEVEL_FIL: 'g' - - # Exposure time [seconds] - exp_time: 150. - - # Observation starting date & time - date_obs: "210525" # [yymmdd] - time_obs: "120000" # [hhmmss] - - # Default Pointing [degrees] - # Note: NOT valid when a pointing list file is specified - ra_center: 192.8595 - dec_center: 27.1283 - # Image rotation [degree] - image_rot: -113.4333 - - # (Optional) a file of point list - # if you just want to run default pointing: - # - pointing_dir: null - # - pointing_file: null - pointing_dir: "/share/simudata/CSSOSDataProductsSims/data/" - pointing_file: "pointing_radec_246.5_40.dat" - - # Number of calibration pointings - np_cal: 0 - - # Run specific pointing(s): - # - 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: [0] - - # Run specific chip(s): - # - give a list of indexes of chips: [ip_1, ip_2...] - # - run all chips: null - # Note: for all pointings - run_chips: [39,40,41,42] - - # Whether to enable astrometric modeling - enable_astrometric_model: True - - # Whether to enable straylight model - enable_straylight_model: True - - # Cut by saturation magnitude in which band? - cut_in_band: "z" - - # saturation magnitude margin - # mag_sat_margin: -2.5 - mag_sat_margin: -15. - - # limiting magnitude margin - mag_lim_margin: +1.0 - -############################################### -# PSF setting -############################################### -psf_setting: - - # Which PSF model to use: - # "Gauss": simple gaussian profile - # "Interp": Interpolated PSF from sampled ray-tracing data - psf_model: "Interp" - - # PSF size [arcseconds] - # radius of 80% energy encircled - # NOTE: only valid for "Gauss" PSF - psf_rcont: 0.15 - - # path to PSF data - # NOTE: only valid for "Interp" PSF - psf_dir: "/share/simudata/CSSOSDataProductsSims/data/psfCube1" - psf_sls_dir: "/share/simudata/CSSOSDataProductsSims/data/SLS_PSF_PCA_fp/" -############################################### -# Shear setting -############################################### - -shear_setting: - # Options to generate mock shear field: - # "constant": all galaxies are assigned a constant reduced shear - # "catalog": from catalog - shear_type: "catalog" - - # For constant shear filed - reduced_g1: 0. - reduced_g2: 0. - -############################################### -# Instrumental effects setting -############################################### -ins_effects: - # switches - # Note: bias_16channel, gain_16channel, and shutter_effect - # is currently not applicable to "FGS" observations - field_dist: YES # Whether to add field distortions - add_back: YES # Whether to add sky background - add_dark: YES # Whether to add dark noise - add_readout: YES # Whether to add read-out (Gaussian) noise - add_bias: YES # Whether to add bias-level to images - bias_16channel: YES # Whether to add different biases for 16 channels - gain_16channel: YES # Whether to make different gains for 16 channels - shutter_effect: NO # Whether to add shutter effect - flat_fielding: YES # Whether to add flat-fielding effect - prnu_effect: YES # Whether to add PRNU effect - non_linear: YES # Whether to add non-linearity - cosmic_ray: YES # Whether to add cosmic-ray - cray_differ: YES # Whether to generate different cosmic ray maps CAL and MS output - cte_trail: NO # Whether to simulate CTE trails, CTI_lgl_v0.3.tar.gz - saturbloom: YES # Whether to simulate Saturation & Blooming - add_badcolumns: YES # Whether to add bad columns - add_hotpixels: YES # Whether to add hot pixels - add_deadpixels: YES # Whether to add dead(dark) pixels - bright_fatter: YES # Whether to simulate Brighter-Fatter (also diffusion) effect - add_prescan: NO # Whether to add pre/over-scan - format_output: NO ##1*16 output - - # Values: - # default values have been defined individually for each chip in: - # ObservationSim/Instrument/data/ccd/chip_definition.json - # Set them here will override the default values - # dark_exptime: 300 # Exposure time for dark current frames [seconds] - # flat_exptime: 150 # Exposure time for flat-fielding frames [seconds] - # readout_time: 0.01 # The read-out time for each channel [seconds] - # df_strength: 2.3 # Sillicon sensor diffusion strength - # bias_level: 2000 # bias level [e-/pixel] - # gain: 1. # Gain - # full_well: 90000 # Full well depth [e-] - -############################################### -# Output options (for calibration pointings only) -############################################### -output_setting: - readout16: OFF # Whether to export as 16 channels (subimages) with pre- and over-scan - shutter_output: OFF # Whether to export shutter effect 16-bit image - bias_output: ON # Whether to export bias frames - dark_output: ON # Whether to export the combined dark current files - flat_output: ON # Whether to export the combined flat-fielding files - prnu_output: OFF # Whether to export the PRNU (pixel-to-pixel flat-fielding) files - NBias: 1 # Number of bias frames to be exported for each exposure - NDark: 1 # Number of dark frames to be exported for each exposure - NFlat: 1 # Number of flat frames to be exported for each exposure - -############################################### -# Random seeds -############################################### -random_seeds: - seed_poisson: 20210601 # Seed for Poisson noise - seed_CR: 20210317 # Seed for generating random cosmic ray maps - seed_flat: 20210101 # Seed for generating random flat fields - seed_prnu: 20210102 # Seed for photo-response non-uniformity - seed_gainNonUniform: 20210202 # Seed for gain nonuniformity - seed_biasNonUniform: 20210203 # Seed for bias nonuniformity - seed_rnNonUniform: 20210204 # Seed for readout-noise nonuniformity - seed_badcolumns: 20240309 # Seed for bad columns - seed_defective: 20210304 # Seed for defective (bad) pixels - seed_readout: 20210601 # Seed for read-out gaussian noise -... diff --git a/config/config_ooc_c6.yaml b/config/config_ooc_c6.yaml deleted file mode 100644 index 54d6ef5a0809c08f3a37f949e3e1839aac0e0626..0000000000000000000000000000000000000000 --- a/config/config_ooc_c6.yaml +++ /dev/null @@ -1,233 +0,0 @@ ---- -############################################### -# -# Configuration file for CSST simulation -# CSST-Sim Group, 2023/04/25 -# -############################################### - -# Base diretories and naming setup -# 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: "/share/home/fangyuedong/20231211/workplace/" -data_dir: "/share/simudata/CSSOSDataProductsSims/data/" -run_name: "test20231218_c6_onlyCat" -project_cycle: 6 -run_counter: 1 - -# Whether to use MPI -run_option: - # NOTE: "n_threads" paramters is currently not used in the backend - # simulation codes. It should be implemented later in the web frontend - # in order to config the number of threads to request from NAOC cluster - n_threads: 80 - - # Output catalog only? - # If yes, no imaging simulation will run - out_cat_only: YES - -############################################### -# Catalog setting -############################################### -# Configure your catalog: options to be implemented -# in the corresponding (user defined) 'Catalog' class -catalog_options: - input_path: - cat_dir: "Catalog_C6_20221212" - star_cat: "C6_MMW_GGC_Astrometry_healpix.hdf5" - galaxy_cat: "cat2CSSTSim_bundle/" - AGN_cat: "AGN_C6_ross13_rand_pos_rmax-1.3.fits" - - SED_templates_path: - star_SED: "Catalog_20210126/SpecLib.hdf5" - galaxy_SED: "Catalog_C6_20221212/sedlibs/" - AGN_SED: "quickspeclib_ross13.fits" - AGN_SED_WAVE: "wave_ross13.npy" - - # Only simulate stars? - star_only: YES - - # Only simulate galaxies? - galaxy_only: NO - - # rotate galaxy ellipticity - rotateEll: 0. # [degree] - - seed_Av: 121212 # Seed for generating random intrinsic extinction - -############################################### -# Observation setting -############################################### -obs_setting: - - # Options for survey types: - # "Photometric": simulate photometric chips only - # "Spectroscopic": simulate slitless spectroscopic chips only - # "FGS": simulate FGS chips only (31-42) - # "All": simulate full focal plane - # "CALIBRATION": falt, bias, dark with or without postflash - survey_type: "Photometric" - #"LED": ['LED1','LED2','LED3','LED4','LED5','LED6','LED7','LED8','LED9','LED10','LED11','LED12','LED13','LED14'] or null - #'LED1': '275', 'LED2': '310', 'LED3': '430', 'LED4': '505', 'LED5': '545', 'LED6': '590', 'LED7': '670', - #'LED8': '760', 'LED9': '940', 'LED10': '940', 'LED11': '1050', 'LED12': '1050','LED13': '340', 'LED14': '365' - LED_TYPE: ['LED5'] - LED_TIME: [1.] - # unit e- ,flat level - FLAT_LEVEL: 20000 - FLAT_LEVEL_FIL: 'g' - - # Exposure time [seconds] - exp_time: 150. - - # Observation starting date & time - date_obs: "210525" # [yymmdd] - time_obs: "120000" # [hhmmss] - - # Default Pointing [degrees] - # Note: NOT valid when a pointing list file is specified - ra_center: 192.8595 - dec_center: 27.1283 - # Image rotation [degree] - image_rot: -113.4333 - - # (Optional) a file of point list - # if you just want to run default pointing: - # - pointing_dir: null - # - pointing_file: null - pointing_dir: "/share/simudata/CSSOSDataProductsSims/data/" - pointing_file: "pointing_radec_246.5_40.dat" - - # Number of calibration pointings - np_cal: 0 - - # Run specific pointing(s): - # - 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: [0] - - # Run specific chip(s): - # - give a list of indexes of chips: [ip_1, ip_2...] - # - run all chips: null - # Note: for all pointings - run_chips: [8] - - # Whether to enable astrometric modeling - enable_astrometric_model: False - - # Whether to enable straylight model - enable_straylight_model: True - - # Cut by saturation magnitude in which band? - cut_in_band: "z" - - # saturation magnitude margin - mag_sat_margin: -2.5 - # mag_sat_margin: -15. - - # limiting magnitude margin - mag_lim_margin: +1.0 - -############################################### -# PSF setting -############################################### -psf_setting: - - # Which PSF model to use: - # "Gauss": simple gaussian profile - # "Interp": Interpolated PSF from sampled ray-tracing data - psf_model: "Interp" - - # PSF size [arcseconds] - # radius of 80% energy encircled - # NOTE: only valid for "Gauss" PSF - psf_rcont: 0.15 - - # path to PSF data - # NOTE: only valid for "Interp" PSF - psf_dir: "/share/simudata/CSSOSDataProductsSims/data/psfCube1" - psf_sls_dir: "/share/simudata/CSSOSDataProductsSims/data/SLS_PSF_PCA_fp/" -############################################### -# Shear setting -############################################### - -shear_setting: - # Options to generate mock shear field: - # "constant": all galaxies are assigned a constant reduced shear - # "catalog": from catalog - shear_type: "constant" - - # For constant shear filed - reduced_g1: 0. - reduced_g2: 0. - -############################################### -# Instrumental effects setting -############################################### -ins_effects: - # switches - # Note: bias_16channel, gain_16channel, and shutter_effect - # is currently not applicable to "FGS" observations - field_dist: YES # Whether to add field distortions - add_back: YES # Whether to add sky background - add_dark: YES # Whether to add dark noise - add_readout: YES # Whether to add read-out (Gaussian) noise - add_bias: YES # Whether to add bias-level to images - bias_16channel: YES # Whether to add different biases for 16 channels - gain_16channel: YES # Whether to make different gains for 16 channels - shutter_effect: YES # Whether to add shutter effect - flat_fielding: YES # Whether to add flat-fielding effect - prnu_effect: YES # Whether to add PRNU effect - non_linear: YES # Whether to add non-linearity - cosmic_ray: YES # Whether to add cosmic-ray - cray_differ: YES # Whether to generate different cosmic ray maps CAL and MS output - cte_trail: YES # Whether to simulate CTE trails, CTI_lgl_v0.3.tar.gz - saturbloom: YES # Whether to simulate Saturation & Blooming - add_badcolumns: YES # Whether to add bad columns - add_hotpixels: YES # Whether to add hot pixels - add_deadpixels: YES # Whether to add dead(dark) pixels - bright_fatter: YES # Whether to simulate Brighter-Fatter (also diffusion) effect - add_prescan: YES # Whether to add pre/over-scan - format_output: YES ##1*16 output - - # Values: - # default values have been defined individually for each chip in: - # ObservationSim/Instrument/data/ccd/chip_definition.json - # Set them here will override the default values - # dark_exptime: 300 # Exposure time for dark current frames [seconds] - # flat_exptime: 150 # Exposure time for flat-fielding frames [seconds] - # readout_time: 40 # The read-out time for each channel [seconds] - # df_strength: 2.3 # Sillicon sensor diffusion strength - # bias_level: 500 # bias level [e-/pixel] - # gain: 1.1 # Gain - # full_well: 90000 # Full well depth [e-] - -############################################### -# Output options (for calibration pointings only) -############################################### -output_setting: - readout16: OFF # Whether to export as 16 channels (subimages) with pre- and over-scan - shutter_output: OFF # Whether to export shutter effect 16-bit image - bias_output: ON # Whether to export bias frames - dark_output: ON # Whether to export the combined dark current files - flat_output: ON # Whether to export the combined flat-fielding files - prnu_output: OFF # Whether to export the PRNU (pixel-to-pixel flat-fielding) files - NBias: 1 # Number of bias frames to be exported for each exposure - NDark: 1 # Number of dark frames to be exported for each exposure - NFlat: 1 # Number of flat frames to be exported for each exposure - -############################################### -# Random seeds -############################################### -random_seeds: - seed_poisson: 20210601 # Seed for Poisson noise - seed_CR: 20210317 # Seed for generating random cosmic ray maps - seed_flat: 20210101 # Seed for generating random flat fields - seed_prnu: 20210102 # Seed for photo-response non-uniformity - seed_gainNonUniform: 20210202 # Seed for gain nonuniformity - seed_biasNonUniform: 20210203 # Seed for bias nonuniformity - seed_rnNonUniform: 20210204 # Seed for readout-noise nonuniformity - seed_badcolumns: 20240309 # Seed for bad columns - seed_defective: 20210304 # Seed for defective (bad) pixels - seed_readout: 20210601 # Seed for read-out gaussian noise -... diff --git a/config/config_overall.yaml b/config/config_overall.yaml index 85b6e933a83fe2a7a7abb0af644f993bf78a0530..8624cc04df45e706214fcd17c1a904184555985f 100644 --- a/config/config_overall.yaml +++ b/config/config_overall.yaml @@ -32,12 +32,10 @@ run_option: catalog_options: input_path: cat_dir: "/public/share/yangxuliu/CSSOSDataProductsSims/data_50sqDeg/" - # star_cat: "starcat/" star_cat: "starcat_C9/" galaxy_cat: "qsocat/cat2CSSTSim_bundle-50sqDeg/" SED_templates_path: - # star_SED: "/public/share/yangxuliu/CSSOSDataProductsSims/data_50sqDeg/SpecLib.hdf5" star_SED: "/public/share/yangxuliu/CSSOSDataProductsSims/data_50sqDeg/starcat_C9/" galaxy_SED: "/public/share/yangxuliu/CSSOSDataProductsSims/data_50sqDeg/sedlibs/" AGN_SED: "/public/share/yangxuliu/CSSOSDataProductsSims/data_50sqDeg/qsocat/qsosed/" @@ -59,10 +57,9 @@ obs_setting: # if you just want to run default pointing: # - pointing_dir: null # - pointing_file: null - # pointing_file: "/public/share/yangxuliu/CSSOSDataProductsSims/data_50sqDeg/pointing50_C9/pointing_50_1_n.dat" - pointing_file: "/public/home/fangyuedong/project/unit_test_data/pointing_for_test.dat" + pointing_file: "/public/share/yangxuliu/CSSOSDataProductsSims/data_50sqDeg/pointing50_C9/pointing_50_1_n.dat" - obs_config_file: "/public/home/fangyuedong/project/csst_msc_sim/config/obs_config_SCI_WIDE_phot.yaml" + obs_config_file: "/public/home/fangyuedong/project/csst_msc_sim/config/obs_config_SCI.yaml" # Run specific pointing(s): # - give a list of indexes of pointings: [ip_1, ip_2...] @@ -103,7 +100,7 @@ psf_setting: # PSF models for photometry survey simulation psf_pho_dir: "/public/share/yangxuliu/CSSOSDataProductsSims/dataC6/psfCube1" # PSF models for slitless spectrum survey simulation - psf_sls_dir: "/share/simudata/CSSOSDataProductsSims/data/SLS_PSF_PCA_fp/" + psf_sls_dir: "/public/share/yangxuliu/CSSOSDataProductsSims/data_50sqDeg/SLS_PSF_PCA_fp/" ############################################### # Shear setting diff --git a/config/config_overall_newStar.yaml b/config/config_overall_fits_stamp.yaml similarity index 84% rename from config/config_overall_newStar.yaml rename to config/config_overall_fits_stamp.yaml index fb6fbbb26e38c1060e38514287916cba8a70d375..cac80ea6c35676f921789e14cc4bb944cfab7c31 100644 --- a/config/config_overall_newStar.yaml +++ b/config/config_overall_fits_stamp.yaml @@ -10,8 +10,8 @@ # Base diretories and naming setup # 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: "/home/zhangxin/CSST_SIM/CSST_sim_scheduler/" -run_name: "QSO_50sqdeg_test" +work_dir: "/public/share/yangxuliu/CSSOSDataProductsSims/outputs_C9Tests/" +run_name: "testRun0" # Project cycle and run counter are used to name the outputs project_cycle: 9 @@ -31,21 +31,26 @@ run_option: # in the corresponding (user defined) 'Catalog' class catalog_options: input_path: - cat_dir: "/nfsdata/share/CSSOSDataProductsSims/data/Catalog_C6_20221212/" - star_cat: "star_catalog/" + cat_dir: "/public/home/chengliang/CSSOSDataProductsSims/testCats/" + # star_cat: "star_catalog/" # galaxy_cat: "qsocat/cat2CSSTSim_bundle-50sqDeg/" + stamp_cat: "stampCatsIndex.hdf5" SED_templates_path: - star_SED: "/nfsdata/share/CSSOSDataProductsSims/data/Catalog_C6_20221212/star_catalog/" + # star_SED: # galaxy_SED: "/public/share/yangxuliu/CSSOSDataProductsSims/data_50sqDeg/sedlibs/" # AGN_SED: "/public/share/yangxuliu/CSSOSDataProductsSims/data_50sqDeg/qsocat/qsosed/" + # stamp_SED: # Only simulate stars? - star_only: YES + star_only: NO # Only simulate galaxies? galaxy_only: NO + # With stamp? + stamp_yes: YES + # rotate galaxy ellipticity rotateEll: 0. # [degree] @@ -57,18 +62,18 @@ obs_setting: # if you just want to run default pointing: # - pointing_dir: null # - pointing_file: null - pointing_file: "/nfsdata/share/CSSOSDataProductsSims/data/pointing_50_1_n.dat" + pointing_file: "/public/share/yangxuliu/CSSOSDataProductsSims/data_50sqDeg/pointing50_C9/pointing_50_1_n.dat" - obs_config_file: "/home/zhangxin/CSST_SIM/CSST_sim_scheduler/csst-simulation/config/obs_config_SCI_WIDE_phot.yaml" + obs_config_file: "/public/home/chengliang/CSSOSDataProductsSims/csst_msc_sim/config/obs_config_SCI.yaml" # Run specific pointing(s): # - 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] # Whether to enable astrometric modeling - enable_astrometric_model: NO + enable_astrometric_model: YES # Cut by saturation magnitude in which band? cut_in_band: "z" @@ -98,9 +103,9 @@ psf_setting: # path to PSF data # NOTE: only valid for "Interp" PSF # PSF models for photometry survey simulation - psf_pho_dir: "/nfsdata/share/CSSOSDataProductsSims/data/psfCube1" + psf_pho_dir: "/public/share/yangxuliu/CSSOSDataProductsSims/psfCube/set1_dynamic/" # PSF models for slitless spectrum survey simulation - psf_sls_dir: "/nfsdata/share/CSSOSDataProductsSims/data/SLS_PSF_PCA_fp/" + psf_sls_dir: "/public/share/yangxuliu/CSSOSDataProductsSims/data_50sqDeg/SLS_PSF_PCA_fp/" ############################################### # Shear setting @@ -138,4 +143,4 @@ random_seeds: seed_badcolumns: 20240309 # Seed for bad columns seed_defective: 20210304 # Seed for defective (bad) pixels seed_readout: 20210601 # Seed for read-out gaussian noise -... \ No newline at end of file +... diff --git a/config/config_testCASE.yaml b/config/config_testCASE.yaml deleted file mode 100644 index f44cf5c972c1d0d53a5772a1b97c94e306917653..0000000000000000000000000000000000000000 --- a/config/config_testCASE.yaml +++ /dev/null @@ -1,221 +0,0 @@ ---- -############################################### -# -# Configuration file for CSST simulation -# CSST-Sim Group, 2023/04/30 -# -############################################### - -# Base diretories and naming setup -# 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: "/share/simudata/CSSOSDataProductsSims/data/CSSTSimImage_C6/" -data_dir: "/share/home/weichengliang/CSST_git/csst-simulation/tools/" -run_name: "C6_fits_testRun" - -# Whether to use MPI -run_option: - # NOTE: "n_threads" paramters is currently not used in the backend - # simulation codes. It should be implemented later in the web frontend - # in order to config the number of threads to request from NAOC cluster - n_threads: 80 - - # Output catalog only? - # If yes, no imaging simulation will run - out_cat_only: NO - -############################################### -# Catalog setting -############################################### -# Configure your catalog: options to be implemented -# in the corresponding (user defined) 'Catalog' class -catalog_options: - input_path: - cat_dir: "Catalog_test" - star_cat: "testStarCat.h5" - galaxy_cat: "testGalaxyCat.h5" - AGN_cat: "AGN_C6_ross13_rand_pos_rmax-1.3.fits" - stamp_cat: "stampCatsIndex.hdf5" - - SED_templates_path: - star_SED: "SpecLib.hdf5" - galaxy_SED: "sedlibs/" - AGN_SED: "quickspeclib_ross13.fits" - AGN_SED_WAVE: "wave_ross13.npy" - #stamp_SED: - - # simulate stars? - star_yes: NO - - # simulate galaxies? - galaxy_yes: NO - - # With stamp? - stamp_yes: YES - - # rotate galaxy ellipticity - rotateEll: 0. # [degree] - - seed_Av: 121212 # Seed for generating random intrinsic extinction - -############################################### -# Observation setting -############################################### -obs_setting: - - # Options for survey types: - # "Photometric": simulate photometric chips only - # "Spectroscopic": simulate slitless spectroscopic chips only - # "FGS": simulate FGS chips only (31-42) - # "All": simulate full focal plane - survey_type: "Photometric" - - # Exposure time [seconds] - exp_time: 150. - - # Observation starting date & time - date_obs: "210525" # [yymmdd] - time_obs: "120000" # [hhmmss] - - # Default Pointing [degrees] - # Note: NOT valid when a pointing list file is specified - ra_center: 60.11828178499743 #244.972773 - dec_center: -39.75897455697294 #39.895901 - # Image rotation [degree] - image_rot: 112.23685624012192 #109.59 - - # (Optional) a file of point list - # if you just want to run default pointing: - # - pointing_dir: null - # - pointing_file: null - pointing_dir: null #"/share/simudata/CSSOSDataProductsSims/data/" - pointing_file: null #"pointing_radec_246.5_40.dat" - - # Number of calibration pointings - np_cal: 0 - - # Run specific pointing(s): - # - 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: [0] - - # Run specific chip(s): - # - give a list of indexes of chips: [ip_1, ip_2...] - # - run all chips: null - # Note: for all pointings - run_chips: [7, 8, 9] - - # Whether to enable astrometric modeling - enable_astrometric_model: False - - # Cut by saturation magnitude in which band? - cut_in_band: "z" - - # saturation magnitude margin - mag_sat_margin: -2.5 - - # limiting magnitude margin - mag_lim_margin: +1.0 - -############################################### -# PSF setting -############################################### -psf_setting: - - # Which PSF model to use: - # "Gauss": simple gaussian profile - # "Interp": Interpolated PSF from sampled ray-tracing data - psf_model: "Interp" - - # PSF size [arcseconds] - # radius of 80% energy encircled - # NOTE: only valid for "Gauss" PSF - psf_rcont: 0.15 - - # path to PSF data - # NOTE: only valid for "Interp" PSF - psf_dir: "/share/simudata/CSSOSDataProductsSims/data/psfCube1" - -############################################### -# Shear setting -############################################### - -shear_setting: - # Options to generate mock shear field: - # "constant": all galaxies are assigned a constant reduced shear - # "catalog": from catalog - shear_type: "catalog" - - # For constant shear filed - reduced_g1: 0. - reduced_g2: 0. - -############################################### -# Instrumental effects setting -############################################### -ins_effects: - # switches - # Note: bias_16channel, gain_16channel, and shutter_effect - # is currently not applicable to "FGS" observations - field_dist: ON # Whether to add field distortions - add_back: OFF # Whether to add sky background - add_dark: OFF # Whether to add dark noise - add_readout: OFF # Whether to add read-out (Gaussian) noise - add_bias: OFF # Whether to add bias-level to images - bias_16channel: OFF # Whether to add different biases for 16 channels - gain_16channel: OFF # Whether to make different gains for 16 channels - shutter_effect: OFF # Whether to add shutter effect - flat_fielding: OFF # Whether to add flat-fielding effect - prnu_effect: OFF # Whether to add PRNU effect - non_linear: OFF # Whether to add non-linearity - cosmic_ray: OFF # Whether to add cosmic-ray - cray_differ: OFF # Whether to generate different cosmic ray maps CAL and MS output - cte_trail: OFF # Whether to simulate CTE trails - saturbloom: OFF # Whether to simulate Saturation & Blooming - add_badcolumns: OFF # Whether to add bad columns - add_hotpixels: OFF # Whether to add hot pixels - add_deadpixels: OFF # Whether to add dead(dark) pixels - bright_fatter: OFF # Whether to simulate Brighter-Fatter (also diffusion) effect - - # Values: - # default values have been defined individually for each chip in: - # ObservationSim/Instrument/data/ccd/chip_definition.json - # Set them here will override the default values - # dark_exptime: 300 # Exposure time for dark current frames [seconds] - # flat_exptime: 150 # Exposure time for flat-fielding frames [seconds] - # readout_time: 0.01 # The read-out time for each channel [seconds] - # df_strength: 2.3 # Sillicon sensor diffusion strength - # bias_level: 2000 # bias level [e-/pixel] - # gain: 1. # Gain - # full_well: 90000 # Full well depth [e-] - -############################################### -# Output options (for calibration pointings only) -############################################### -output_setting: - readout16: OFF # Whether to export as 16 channels (subimages) with pre- and over-scan - shutter_output: OFF # Whether to export shutter effect 16-bit image - bias_output: ON # Whether to export bias frames - dark_output: ON # Whether to export the combined dark current files - flat_output: ON # Whether to export the combined flat-fielding files - prnu_output: OFF # Whether to export the PRNU (pixel-to-pixel flat-fielding) files - NBias: 1 # Number of bias frames to be exported for each exposure - NDark: 1 # Number of dark frames to be exported for each exposure - NFlat: 1 # Number of flat frames to be exported for each exposure - -############################################### -# Random seeds -############################################### -random_seeds: - seed_poisson: 20210601 # Seed for Poisson noise - seed_CR: 20210317 # Seed for generating random cosmic ray maps - seed_flat: 20210101 # Seed for generating random flat fields - seed_prnu: 20210102 # Seed for photo-response non-uniformity - seed_gainNonUniform: 20210202 # Seed for gain nonuniformity - seed_biasNonUniform: 20210203 # Seed for bias nonuniformity - seed_rnNonUniform: 20210204 # Seed for readout-noise nonuniformity - seed_badcolumns: 20240309 # Seed for bad columns - seed_defective: 20210304 # Seed for defective (bad) pixels - seed_readout: 20210601 # Seed for read-out gaussian noise -... \ No newline at end of file diff --git a/config/obs_config_SCI_WIDE_phot.yaml b/config/obs_config_SCI.yaml similarity index 96% rename from config/obs_config_SCI_WIDE_phot.yaml rename to config/obs_config_SCI.yaml index e491daefc542b7043bc6752a72a8977b504479d6..405950f5005a54583ebdea71369c25a176228d08 100644 --- a/config/obs_config_SCI_WIDE_phot.yaml +++ b/config/obs_config_SCI.yaml @@ -14,9 +14,9 @@ obs_type_code: "101" obs_id: "00000001" # this setting will only be used if pointing list file is not given # Define list of chips -# run_chips: [6,7,8,9,11,12,13,14,15,16,17,18,19,20,22,23,24,25] -#run_chips: [1,2,3,4,5,10,21,26,27,28,29,30] -run_chips: [9] +# 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] # Define observation sequence call_sequence: diff --git a/example.sh b/example.sh deleted file mode 100755 index 5e93491ffc5cf673dd25f3b49f681f1eecd9f47e..0000000000000000000000000000000000000000 --- a/example.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -date - -python3 /share/home/fangyuedong/fgs_sim/csst-simulation/run_sim.py \ - --config_file config_example.yaml \ - --catalog Catalog_example \ - -c /share/home/fangyuedong/fgs_sim/csst-simulation/config diff --git a/mpi_example.pbs b/mpi_example.pbs deleted file mode 100755 index 2dbcc53e7ca19aca1437b42afb5d6fe97f0f6446..0000000000000000000000000000000000000000 --- a/mpi_example.pbs +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -#PBS -N SIMS -##PBS -l walltime=70:00:00 - -##mpdallexit -##mpdboot -n 10 -f ./mpd.hosts - -##PBS -j oe -#PBS -l nodes=comput108:ppn=80 -#####PBS -q longq -#PBS -q batch -#PBS -u fangyuedong - -NP=40 -date -echo $NP - -mpirun -np $NP python /share/home/fangyuedong/fgs_sim/csst-simulation/run_sim.py \ - --config_file config_example.yaml \ - --catalog Catalog_example \ - -c /share/home/fangyuedong/fgs_sim/csst-simulation/config \ No newline at end of file diff --git a/ObservationSim/ObservationSim.py b/observation_sim/ObservationSim.py similarity index 73% rename from ObservationSim/ObservationSim.py rename to observation_sim/ObservationSim.py index f25551e3e06e5b73786d3bfb893692f742591a49..051d6d18757b97151e4e56b191d6492f8fa6ce0a 100755 --- a/ObservationSim/ObservationSim.py +++ b/observation_sim/ObservationSim.py @@ -8,24 +8,26 @@ from datetime import datetime import traceback -from ObservationSim.Config import ChipOutput -from ObservationSim.Instrument import Telescope, Filter, FilterParam, FocalPlane, Chip -from ObservationSim.Instrument.Chip import Effects -from ObservationSim.Instrument.Chip import ChipUtils as chip_utils -from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position -from ObservationSim.sim_steps import SimSteps, SIM_STEP_TYPES +from observation_sim.config import ChipOutput +from observation_sim.instruments import Telescope, Filter, FilterParam, FocalPlane, Chip +from observation_sim.instruments.chip import effects +from observation_sim.instruments.chip import chip_utils as chip_utils +from observation_sim.astrometry.Astrometry_util import on_orbit_obs_position +from observation_sim.sim_steps import SimSteps, SIM_STEP_TYPES + class Observation(object): def __init__(self, config, Catalog, work_dir=None, data_dir=None): self.config = config self.tel = Telescope() - self.filter_param = FilterParam() + self.filter_param = FilterParam() self.Catalog = Catalog def prepare_chip_for_exposure(self, chip, ra_cen, dec_cen, pointing, wcs_fp=None): # Get WCS for the focal plane if wcs_fp == None: - wcs_fp = self.focal_plane.getTanWCS(ra_cen, dec_cen, pointing.img_pa, chip.pix_scale) + wcs_fp = self.focal_plane.getTanWCS( + ra_cen, dec_cen, pointing.img_pa, chip.pix_scale) # Create chip Image chip.img = galsim.ImageF(chip.npix_x, chip.npix_y) @@ -35,29 +37,36 @@ class Observation(object): # 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.) - + # Get flat, shutter, and PRNU images - chip.flat_img, _ = chip_utils.get_flat(img=chip.img, seed=int(self.config["random_seeds"]["seed_flat"])) + chip.flat_img, _ = chip_utils.get_flat( + img=chip.img, seed=int(self.config["random_seeds"]["seed_flat"])) if chip.chipID > 30: 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.prnu_img = Effects.PRNU_Img(xsize=chip.npix_x, ysize=chip.npix_y, sigma=0.01, + chip.shutter_img = effects.ShutterEffectArr( + chip.img, 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)) - + return chip def run_one_chip(self, chip, filt, pointing, chip_output, wcs_fp=None, psf_model=None, cat_dir=None, sed_dir=None): - chip_output.Log_info(':::::::::::::::::::Current Pointing Information::::::::::::::::::') + chip_output.Log_info( + ':::::::::::::::::::Current Pointing Information::::::::::::::::::') chip_output.Log_info("RA: %f, DEC; %f" % (pointing.ra, pointing.dec)) - chip_output.Log_info("Time: %s" % datetime.utcfromtimestamp(pointing.timestamp).isoformat()) + chip_output.Log_info("Time: %s" % datetime.utcfromtimestamp( + pointing.timestamp).isoformat()) chip_output.Log_info("Exposure time: %f" % pointing.exp_time) - chip_output.Log_info("Satellite Position (x, y, z): (%f, %f, %f)" % (pointing.sat_x, pointing.sat_y, pointing.sat_z)) - chip_output.Log_info("Satellite Velocity (x, y, z): (%f, %f, %f)" % (pointing.sat_vx, pointing.sat_vy, pointing.sat_vz)) + chip_output.Log_info("Satellite Position (x, y, z): (%f, %f, %f)" % ( + pointing.sat_x, pointing.sat_y, pointing.sat_z)) + chip_output.Log_info("Satellite Velocity (x, y, z): (%f, %f, %f)" % ( + pointing.sat_vx, pointing.sat_vy, pointing.sat_vz)) chip_output.Log_info("Position Angle: %f" % pointing.img_pa.deg) chip_output.Log_info('Chip : %d' % chip.chipID) - chip_output.Log_info(':::::::::::::::::::::::::::END:::::::::::::::::::::::::::::::::::') + chip_output.Log_info( + ':::::::::::::::::::::::::::END:::::::::::::::::::::::::::::::::::') # Apply astrometric simulation for pointing if self.config["obs_setting"]["enable_astrometric_model"]: @@ -91,32 +100,35 @@ class Observation(object): chip = self.prepare_chip_for_exposure(chip, ra_cen, dec_cen, pointing) # Initialize SimSteps - sim_steps = SimSteps(overall_config=self.config, chip_output=chip_output, all_filters=self.all_filters) + sim_steps = SimSteps(overall_config=self.config, + chip_output=chip_output, all_filters=self.all_filters) for step in pointing.obs_param["call_sequence"]: if self.config["run_option"]["out_cat_only"]: if step != "scie_obs": continue - chip_output.Log_info("Starting simulation step: %s, calling function: %s"%(step, SIM_STEP_TYPES[step])) + chip_output.Log_info("Starting simulation step: %s, calling function: %s" % ( + step, SIM_STEP_TYPES[step])) obs_param = pointing.obs_param["call_sequence"][step] step_name = SIM_STEP_TYPES[step] try: step_func = getattr(sim_steps, step_name) chip, filt, tel, pointing = step_func( - chip=chip, - filt=filt, + chip=chip, + filt=filt, tel=self.tel, - pointing=pointing, - catalog=self.Catalog, + pointing=pointing, + catalog=self.Catalog, obs_param=obs_param) - chip_output.Log_info("Finished simulation step: %s"%(step)) + chip_output.Log_info("Finished simulation step: %s" % (step)) except Exception as e: traceback.print_exc() chip_output.Log_error(e) - chip_output.Log_error("Failed simulation on step: %s"%(step)) + chip_output.Log_error("Failed simulation on step: %s" % (step)) break - 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) )) + 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 def runExposure_MPI_PointingList(self, pointing_list, chips=None): @@ -131,9 +143,11 @@ class Observation(object): # pointing_ID = pointing.id pointing_ID = pointing.obs_id - pointing.make_output_pointing_dir(overall_config=self.config, copy_obs_config=True) + pointing.make_output_pointing_dir( + overall_config=self.config, copy_obs_config=True) - self.focal_plane = FocalPlane(chip_list=pointing.obs_param["run_chips"]) + self.focal_plane = FocalPlane( + chip_list=pointing.obs_param["run_chips"]) # Make Chip & Filter lists self.chip_list = [] self.filter_list = [] @@ -167,7 +181,7 @@ class Observation(object): run_chips.append(chip) run_filts.append(filt) nchips_per_fp = len(chips) - + for ichip in range(nchips_per_fp): i_process = process_counter + ichip if i_process % num_thread != ind_thread: @@ -176,20 +190,22 @@ class Observation(object): chip = run_chips[ichip] filt = run_filts[ichip] - + chip_output = ChipOutput( - config = self.config, - chip = chip, - filt = filt, - pointing = pointing + config=self.config, + chip=chip, + filt=filt, + pointing=pointing ) - chip_output.Log_info("running pointing#%d, chip#%d, at PID#%d..."%(int(pointing_ID), chip.chipID, pid)) + chip_output.Log_info("running pointing#%d, chip#%d, at PID#%d..." % ( + int(pointing_ID), chip.chipID, pid)) self.run_one_chip( chip=chip, filt=filt, chip_output=chip_output, pointing=pointing) - chip_output.Log_info("finished running chip#%d..."%(chip.chipID)) + chip_output.Log_info( + "finished running chip#%d..." % (chip.chipID)) for handler in chip_output.logger.handlers[:]: chip_output.logger.removeHandler(handler) gc.collect() diff --git a/ObservationSim/Astrometry/__init__.py b/observation_sim/__init__.py old mode 100644 new mode 100755 similarity index 100% rename from ObservationSim/Astrometry/__init__.py rename to observation_sim/__init__.py diff --git a/ObservationSim/_util.py b/observation_sim/_util.py similarity index 83% rename from ObservationSim/_util.py rename to observation_sim/_util.py index 1009ec07d170873ab3bf322574b7c0eba47103a7..47c91ce66d01ce7c06b119ee02822b112dc5f7d7 100755 --- a/ObservationSim/_util.py +++ b/observation_sim/_util.py @@ -4,7 +4,8 @@ from datetime import datetime import argparse from astropy.time import Time -from ObservationSim.Config import Pointing +from observation_sim.config import Pointing + def parse_args(): ''' @@ -12,19 +13,25 @@ def parse_args(): can be set in the .yaml config file as well. ''' parser = argparse.ArgumentParser() - parser.add_argument('--config_file', type=str, required=True, help='.yaml config file for simulation settings.') - parser.add_argument('--catalog', type=str, help='name of the catalog interface class to be loaded.') - parser.add_argument('-c', '--config_dir', type=str, help='Directory that houses the .yaml config file.') - parser.add_argument('-d', '--data_dir', type=str, help='Directory that houses the input data.') - parser.add_argument('-w', '--work_dir', type=str, help='The path for output.') + parser.add_argument('--config_file', type=str, required=True, + help='.yaml config file for simulation settings.') + parser.add_argument('--catalog', type=str, + help='name of the catalog interface class to be loaded.') + parser.add_argument('-c', '--config_dir', type=str, + help='Directory that houses the .yaml config file.') + parser.add_argument('-d', '--data_dir', type=str, + help='Directory that houses the input data.') + parser.add_argument('-w', '--work_dir', type=str, + help='The path for output.') return parser.parse_args() + def generate_pointing_list(config, pointing_filename=None, data_dir=None): pointing_list = [] # Only valid when the pointing list does not contain time stamp column t0 = datetime(2021, 5, 25, 12, 0, 0) - delta_t = 10. # Time elapsed between exposures (minutes) + delta_t = 10. # Time elapsed between exposures (minutes) # Calculate starting time(s) for CAL exposures # NOTE: temporary implementation @@ -36,7 +43,7 @@ def generate_pointing_list(config, pointing_filename=None, data_dir=None): obs_config_file = config['obs_setting']["obs_config_file"] else: obs_config_file = None - + # if pointing_filename and data_dir: if pointing_filename: if data_dir: @@ -48,7 +55,7 @@ def generate_pointing_list(config, pointing_filename=None, data_dir=None): # header = f.readline() iline = 0 for line in f: - if len(line.strip()) == 0 or line[0]=='#': + if len(line.strip()) == 0 or line[0] == '#': continue if run_pointings and iline not in run_pointings: iline += 1 @@ -77,12 +84,13 @@ def generate_pointing_list(config, pointing_filename=None, data_dir=None): exp_time=exp_time, pointing_type='SCI', obs_config_file=obs_config_file - ) + ) t += delta_t * 60. pointing_list.append(pointing) ipoint += 1 return pointing_list + def make_run_dirs(work_dir, run_name, pointing_list): if not os.path.exists(work_dir): try: @@ -97,6 +105,7 @@ def make_run_dirs(work_dir, run_name, pointing_list): pass return imgDir + def make_output_pointing_dir(path_dict, config, pointing_ID=0): imgDir = os.path.join(path_dict["work_dir"], config["run_name"]) if not os.path.exists(imgDir): @@ -113,6 +122,7 @@ def make_output_pointing_dir(path_dict, config, pointing_ID=0): pass return subImgdir, prefix + def get_shear_field(config): if not config["shear_setting"]["shear_type"] in ["constant", "catalog"]: raise ValueError("Please set a right 'shear_method' parameter.") @@ -125,4 +135,4 @@ def get_shear_field(config): else: g1, g2 = 0., 0. nshear = 0 - return g1, g2, nshear \ No newline at end of file + return g1, g2, nshear diff --git a/ObservationSim/Astrometry/Astrometry_util.py b/observation_sim/astrometry/Astrometry_util.py similarity index 66% rename from ObservationSim/Astrometry/Astrometry_util.py rename to observation_sim/astrometry/Astrometry_util.py index 58f5fd0a5c2d759a02975af88ff57f6b9add67be..dba4466365299b584422dbad4833e342e25bcac8 100644 --- a/ObservationSim/Astrometry/Astrometry_util.py +++ b/observation_sim/astrometry/Astrometry_util.py @@ -7,28 +7,32 @@ except ImportError: # Try backported to PY<37 'importlib_resources' import importlib_resources as pkg_resources + def checkInputList(input_list, n): if not isinstance(input_list, list): raise TypeError("Input type is not list!", input_list) for i in input_list: if type(i) != type(1.1): if type(i) != type(1): - raise TypeError("Input list's element is not float or int!", input_list) + raise TypeError( + "Input list's element is not float or int!", input_list) if len(input_list) != n: - raise RuntimeError("Length of input list is not equal to stars' number!", input_list) - + raise RuntimeError( + "Length of input list is not equal to stars' number!", input_list) + + def on_orbit_obs_position(input_ra_list, input_dec_list, input_pmra_list, input_pmdec_list, input_rv_list, input_parallax_list, input_nstars, input_x, input_y, input_z, input_vx, input_vy, input_vz, input_epoch, input_date_str, input_time_str, lib_path=None): - #Check input parameters + # Check input parameters if not isinstance(input_nstars, int): raise TypeError("Parameter 7 is not int!", input_nstars) - + checkInputList(input_ra_list, input_nstars) checkInputList(input_dec_list, input_nstars) checkInputList(input_pmra_list, input_nstars) checkInputList(input_pmdec_list, input_nstars) checkInputList(input_rv_list, input_nstars) checkInputList(input_parallax_list, input_nstars) - + if not isinstance(input_x, float): raise TypeError("Parameter 8 is not double!", input_x) if not isinstance(input_y, float): @@ -41,69 +45,77 @@ def on_orbit_obs_position(input_ra_list, input_dec_list, input_pmra_list, input_ raise TypeError("Parameter 12 is not double!", input_vy) if not isinstance(input_vz, float): raise TypeError("Parameter 13 is not double!", input_vz) - #Convert km -> m - input_x = input_x*1000.0 - input_y = input_y*1000.0 + # Convert km -> m + input_x = input_x*1000.0 + input_y = input_y*1000.0 input_z = input_z*1000.0 input_vx = input_vx*1000.0 input_vy = input_vy*1000.0 - input_vz = input_vz*1000.0 - + input_vz = input_vz*1000.0 + if not isinstance(input_date_str, str): raise TypeError("Parameter 15 is not string!", input_date_str) else: input_date_str = input_date_str.strip() - if not (input_date_str[4]=="-" and input_date_str[7]=="-"): + if not (input_date_str[4] == "-" and input_date_str[7] == "-"): raise TypeError("Parameter 15 format error (1)!", input_date_str) else: tmp = input_date_str.split("-") if len(tmp) != 3: - raise TypeError("Parameter 15 format error (2)!", input_date_str) + raise TypeError( + "Parameter 15 format error (2)!", input_date_str) input_year = int(tmp[0]) input_month = int(tmp[1]) input_day = int(tmp[2]) - if not (input_year>=1900 and input_year<=2100): - raise TypeError("Parameter 15 year range error [1900 ~ 2100]!", input_year) - if not (input_month>=1 and input_month<=12): - raise TypeError("Parameter 15 month range error [1 ~ 12]!", input_month) - if not (input_day>=1 and input_day<=31): - raise TypeError("Parameter 15 day range error [1 ~ 31]!", input_day) - + if not (input_year >= 1900 and input_year <= 2100): + raise TypeError( + "Parameter 15 year range error [1900 ~ 2100]!", input_year) + if not (input_month >= 1 and input_month <= 12): + raise TypeError( + "Parameter 15 month range error [1 ~ 12]!", input_month) + if not (input_day >= 1 and input_day <= 31): + raise TypeError( + "Parameter 15 day range error [1 ~ 31]!", input_day) + if not isinstance(input_time_str, str): raise TypeError("Parameter 16 is not string!", input_time_str) else: input_time_str = input_time_str.strip() - if not (input_time_str[2]==":" and input_time_str[5]==":"): + if not (input_time_str[2] == ":" and input_time_str[5] == ":"): raise TypeError("Parameter 16 format error (1)!", input_time_str) else: tmp = input_time_str.split(":") if len(tmp) != 3: - raise TypeError("Parameter 16 format error (2)!", input_time_str) + raise TypeError( + "Parameter 16 format error (2)!", input_time_str) input_hour = int(tmp[0]) input_minute = int(tmp[1]) input_second = float(tmp[2]) - if not (input_hour>=0 and input_hour<=23): - raise TypeError("Parameter 16 hour range error [0 ~ 23]!", input_hour) - if not (input_minute>=0 and input_minute<=59): - raise TypeError("Parameter 16 minute range error [0 ~ 59]!", input_minute) - if not (input_second>=0 and input_second<60.0): - raise TypeError("Parameter 16 second range error [0 ~ 60)!", input_second) - - #Inital dynamic lib + if not (input_hour >= 0 and input_hour <= 23): + raise TypeError( + "Parameter 16 hour range error [0 ~ 23]!", input_hour) + if not (input_minute >= 0 and input_minute <= 59): + raise TypeError( + "Parameter 16 minute range error [0 ~ 59]!", input_minute) + if not (input_second >= 0 and input_second < 60.0): + raise TypeError( + "Parameter 16 second range error [0 ~ 60)!", input_second) + + # Inital dynamic lib try: - with pkg_resources.files('ObservationSim.Astrometry.lib').joinpath("libshao.so") as lib_path: + with pkg_resources.files('observation_sim.astrometry.lib').joinpath("libshao.so") as lib_path: shao = cdll.LoadLibrary(lib_path) except AttributeError: - with pkg_resources.path('ObservationSim.Astrometry.lib', "libshao.so") as lib_path: + with pkg_resources.path('observation_sim.astrometry.lib', "libshao.so") as lib_path: shao = cdll.LoadLibrary(lib_path) shao.onOrbitObs.restype = c_int - + d3 = c_double * 3 - shao.onOrbitObs.argtypes = [c_double, c_double, c_double, c_double, c_double, c_double, \ - c_int, c_int, c_int, c_int, c_int, c_double, \ - c_double, POINTER(d3), POINTER(d3), \ - c_int, c_int, c_int, c_int, c_int, c_double, \ - POINTER(c_double), POINTER(c_double) ] + shao.onOrbitObs.argtypes = [c_double, c_double, c_double, c_double, c_double, c_double, + c_int, c_int, c_int, c_int, c_int, c_double, + c_double, POINTER(d3), POINTER(d3), + c_int, c_int, c_int, c_int, c_int, c_double, + POINTER(c_double), POINTER(c_double)] output_ra_list = list() output_dec_list = list() for i in range(input_nstars): @@ -118,17 +130,17 @@ def on_orbit_obs_position(input_ra_list, input_dec_list, input_pmra_list, input_ v3 = d3(input_vx, input_vy, input_vz) input_year_c = c_int(input_year) input_month_c = c_int(input_month) - input_day_c = c_int(input_day) + input_day_c = c_int(input_day) input_hour_c = c_int(input_hour) input_minute_c = c_int(input_minute) - input_second_c = c_double(input_second) + input_second_c = c_double(input_second) DAT = c_double(37.0) output_ra = c_double(0.0) output_dec = c_double(0.0) - rs = shao.onOrbitObs(input_ra, input_dec, input_parallax, input_pmra, input_pmdec, input_rv, \ - input_year_c, input_month_c, input_day_c, input_hour_c, input_minute_c, input_second_c, \ - DAT, byref(p3), byref(v3), \ - input_year_c, input_month_c, input_day_c, input_hour_c, input_minute_c, input_second_c, \ + rs = shao.onOrbitObs(input_ra, input_dec, input_parallax, input_pmra, input_pmdec, input_rv, + input_year_c, input_month_c, input_day_c, input_hour_c, input_minute_c, input_second_c, + DAT, byref(p3), byref(v3), + input_year_c, input_month_c, input_day_c, input_hour_c, input_minute_c, input_second_c, byref(output_ra), byref(output_dec)) if rs != 0: raise RuntimeError("Calculate error!") diff --git a/ObservationSim/Astrometry/lib/__init__.py b/observation_sim/astrometry/__init__.py similarity index 100% rename from ObservationSim/Astrometry/lib/__init__.py rename to observation_sim/astrometry/__init__.py diff --git a/ObservationSim/Instrument/Chip/libBF/__init__.py b/observation_sim/astrometry/lib/__init__.py similarity index 100% rename from ObservationSim/Instrument/Chip/libBF/__init__.py rename to observation_sim/astrometry/lib/__init__.py diff --git a/ObservationSim/Astrometry/lib/libshao.so b/observation_sim/astrometry/lib/libshao.so similarity index 100% rename from ObservationSim/Astrometry/lib/libshao.so rename to observation_sim/astrometry/lib/libshao.so diff --git a/ObservationSim/Config/ChipOutput.py b/observation_sim/config/ChipOutput.py similarity index 94% rename from ObservationSim/Config/ChipOutput.py rename to observation_sim/config/ChipOutput.py index 8b6c8a39339d6bd81ea988fc1eebabfa15e6cdfe..5efd0616e8870d90a0844279d476d4817a9a2135 100755 --- a/ObservationSim/Config/ChipOutput.py +++ b/observation_sim/config/ChipOutput.py @@ -1,7 +1,7 @@ import os import logging -import ObservationSim.Config._util as _util -from ObservationSim.Config.Header import generatePrimaryHeader +import observation_sim.config._util as _util +from observation_sim.config.header import generatePrimaryHeader class ChipOutput(object): diff --git a/ObservationSim/Config/Pointing.py b/observation_sim/config/Pointing.py similarity index 84% rename from ObservationSim/Config/Pointing.py rename to observation_sim/config/Pointing.py index 378c4db5e0e4e906bdb718ed1486a9986dac83da..1b399596e8789ef8de1e8a78a2d437cca88565af 100644 --- a/ObservationSim/Config/Pointing.py +++ b/observation_sim/config/Pointing.py @@ -5,11 +5,12 @@ import galsim import numpy as np from astropy.time import Time -from ObservationSim.Config._util import get_obs_id -import ObservationSim.Instrument._util as _util +from observation_sim.config._util import get_obs_id +import observation_sim.instruments._util as _util + class Pointing(object): - def __init__(self, id=0, ra=0., dec=0., img_pa=0., timestamp=1621915200, sat_x=0., sat_y=0., sat_z=0., sun_x=0., sun_y=0., sun_z=0., sat_vx=0., sat_vy=0., sat_vz=0., exp_time=150., pointing_type='SCI', pointing_type_code='101', pointing_id = '00000001', obs_config_file=None, t_shutter_open = 1.3, t_shutter_close = 1.3): + def __init__(self, id=0, ra=0., dec=0., img_pa=0., timestamp=1621915200, sat_x=0., sat_y=0., sat_z=0., sun_x=0., sun_y=0., sun_z=0., sat_vx=0., sat_vy=0., sat_vz=0., exp_time=150., pointing_type='SCI', pointing_type_code='101', pointing_id='00000001', obs_config_file=None, t_shutter_open=1.3, t_shutter_close=1.3): self.id = id self.ra = ra self.dec = dec @@ -23,7 +24,7 @@ class Pointing(object): self.pointing_type_code = pointing_type_code self.obs_id = pointing_id self.survey_field_type = 'WIDE' - self.jdt = 0. + self.jdt = 0. self.obs_config_file = obs_config_file self.t_shutter_open = t_shutter_open self.t_shutter_close = t_shutter_close @@ -41,7 +42,6 @@ class Pointing(object): if self.obs_param["obs_id"]: self.obs_id = str(self.obs_param["obs_id"]) - def get_full_depth_exptime(self, filter_type): if self.survey_field_type == 'WIDE': if filter_type in _util.SPEC_FILTERS: @@ -52,7 +52,7 @@ class Pointing(object): elif filter_type.lower() in ['u', 'g', 'r', 'i', 'z']: return 150. * 2 else: - return max(150., self.exp_time) # [TODO] for FGS + return max(150., self.exp_time) # [TODO] for FGS elif self.survey_field_type == 'DEEP': if filter_type in _util.SPEC_FILTERS: return 250. * 4 * 4 @@ -62,8 +62,7 @@ class Pointing(object): elif filter_type.lower() in ['u', 'g', 'r', 'i', 'z']: return 250. * 2 * 4 else: - return max(150., self.exp_time) # [TODO] for FGS - + return max(150., self.exp_time) # [TODO] for FGS def read_pointing_columns(self, columns, id=0, t=1621915200, pointing_type='SCI'): self.id = id @@ -91,7 +90,7 @@ class Pointing(object): # [TODO] Can also define other survey types if is_deep != -1.0: self.survey_field_type = "DEEP" - + if not self.obs_config_file: self.obs_config_file = str(columns[20]) with open(self.obs_config_file, "r") as stream: @@ -99,7 +98,7 @@ class Pointing(object): self.obs_param = yaml.safe_load(stream) except yaml.YAMLError as exc: print(exc) - + self.pointing_type_code = columns[21][0:3] self.obs_id = columns[21][3:] @@ -108,18 +107,19 @@ class Pointing(object): self.timestamp = t def make_output_pointing_dir(self, overall_config, copy_obs_config=False): - run_dir = os.path.join(overall_config["work_dir"], overall_config["run_name"]) + run_dir = os.path.join( + overall_config["work_dir"], overall_config["run_name"]) if not os.path.exists(run_dir): try: os.makedirs(run_dir, exist_ok=True) except OSError: pass self.output_prefix = get_obs_id( - img_type=self.pointing_type, - project_cycle=overall_config["project_cycle"], - run_counter=overall_config["run_counter"], - pointing_id=self.obs_id, - pointing_type_code = self.pointing_type_code) + img_type=self.pointing_type, + project_cycle=overall_config["project_cycle"], + run_counter=overall_config["run_counter"], + pointing_id=self.obs_id, + pointing_type_code=self.pointing_type_code) self.output_dir = os.path.join(run_dir, self.output_prefix) if not os.path.exists(self.output_dir): try: @@ -127,10 +127,10 @@ class Pointing(object): except OSError: pass if copy_obs_config and self.obs_config_file: - obs_config_output_path = os.path.join(self.output_dir, os.path.basename(self.obs_config_file)) + obs_config_output_path = os.path.join( + self.output_dir, os.path.basename(self.obs_config_file)) if not os.path.exists(obs_config_output_path): try: shutil.copy(self.obs_config_file, self.output_dir) except OSError: pass - diff --git a/ObservationSim/Config/__init__.py b/observation_sim/config/__init__.py similarity index 100% rename from ObservationSim/Config/__init__.py rename to observation_sim/config/__init__.py diff --git a/observation_sim/config/_util.py b/observation_sim/config/_util.py new file mode 100644 index 0000000000000000000000000000000000000000..7ab0f59d663cf9ad36bf5c63abb9c63e2cd4cdb0 --- /dev/null +++ b/observation_sim/config/_util.py @@ -0,0 +1,14 @@ + +def get_obs_id(img_type='SCI', project_cycle=6, run_counter=0, pointing_id='00000001', pointing_type_code='101'): + # obs_type = {'SCI': '01', 'BIAS': '03', 'DARK': '07', 'FLAT': '11', 'CRS': '98', 'CRD': '99'} + # obs_type = {'SCIE': '01', 'BIAS': '03', 'DARK': '07', 'FLAT': '11', 'CRS': '98', 'CRD': '99', 'CAL': '01'} + obs_id = pointing_type_code + \ + str(int(project_cycle)).rjust(2, '0') + \ + str(int(run_counter)) + pointing_id + return obs_id + + +def get_file_type(img_type='SCI'): + file_type = {'SCI': 'SCI', 'BIAS': 'BIAS', 'DARK': 'DARK', 'FLAT': 'FLAT', + 'CRS': 'CRS', 'CRD': 'CRD', 'CALS': 'CALS', 'CALF': 'CALF'} + return file_type[img_type] diff --git a/ObservationSim/Config/Header/ImageHeader.py b/observation_sim/config/header/ImageHeader.py similarity index 74% rename from ObservationSim/Config/Header/ImageHeader.py rename to observation_sim/config/header/ImageHeader.py index 516cd260d95c90d296f922291e01e3e7f111efeb..7fc3444c1e48d712673ad67c2dadd3cf0e1eb6b6 100644 --- a/ObservationSim/Config/Header/ImageHeader.py +++ b/observation_sim/config/header/ImageHeader.py @@ -17,13 +17,14 @@ from astropy.coordinates import SkyCoord from astropy.wcs.utils import fit_wcs_from_points from astropy.time import Time from astropy import wcs -from ObservationSim.Config._util import get_obs_id, get_file_type +from observation_sim.config._util import get_obs_id, get_file_type from datetime import datetime, timezone # import socket import platform import toml + def chara2digit(char): """ Function to judge and convert characters to digitals @@ -33,7 +34,7 @@ def chara2digit(char): """ try: - float(char) # for int, long and float + float(char) # for int, long and float except ValueError: pass return char @@ -66,41 +67,43 @@ def read_header_parameter(filename='global_header.param'): # print(value) return name, value, description + def rotate_CD_matrix(cd, pa_aper): """Rotate CD matrix - + Parameters ---------- cd: (2,2) array CD matrix - + pa_aper: float Position angle, in degrees E from N, of y axis of the detector - + Returns ------- cd_rot: (2,2) array Rotated CD matrix - + Comments -------- `astropy.wcs.WCS.rotateCD` doesn't work for non-square pixels in that it doesn't preserve the pixel scale! The bug seems to come from the fact that `rotateCD` assumes a transposed version of its own CD matrix. - + """ rad = np.deg2rad(-pa_aper) - mat = np.zeros((2,2)) - mat[0,:] = np.array([np.cos(rad),-np.sin(rad)]) - mat[1,:] = np.array([np.sin(rad),np.cos(rad)]) + mat = np.zeros((2, 2)) + mat[0, :] = np.array([np.cos(rad), -np.sin(rad)]) + mat[1, :] = np.array([np.sin(rad), np.cos(rad)]) cd_rot = np.dot(mat, cd) return cd_rot -def calcaluteSLSRotSkyCoor(pix_xy = None,rot_angle = 1, xlen = 9216, ylen = 9232, w = None): + +def calcaluteSLSRotSkyCoor(pix_xy=None, rot_angle=1, xlen=9216, ylen=9232, w=None): rad = np.deg2rad(rot_angle) - mat = np.zeros((2,2)) - mat[0,:] = np.array([np.cos(rad),-np.sin(rad)]) - mat[1,:] = np.array([np.sin(rad),np.cos(rad)]) + mat = np.zeros((2, 2)) + mat[0, :] = np.array([np.cos(rad), -np.sin(rad)]) + mat[1, :] = np.array([np.sin(rad), np.cos(rad)]) center = np.array([xlen/2, ylen/2]) rot_pix = np.dot(mat, pix_xy-center) + center skyCoor = w.wcs_pix2world(np.array([rot_pix]), 1) @@ -172,10 +175,9 @@ def calcaluteSLSRotSkyCoor(pix_xy = None,rot_angle = 1, xlen = 9216, ylen = 9232 # return name, value, description -##9232 9216 898 534 1309 60 -40 -23.4333 -def WCS_def(xlen = 9216, ylen = 9232, gapy = 898.0, gapx1 = 534, gapx2 = 1309, ra_ref = 60, dec_ref = -40, pa = -23.433, pixel_scale = 0.074, pixel_size=1e-2, - rotate_chip=0., filter = 'GI', row_num = None, col_num = None, xcen = None, ycen = None): - +# 9232 9216 898 534 1309 60 -40 -23.4333 +def WCS_def(xlen=9216, ylen=9232, gapy=898.0, gapx1=534, gapx2=1309, ra_ref=60, dec_ref=-40, pa=-23.433, pixel_scale=0.074, pixel_size=1e-2, + rotate_chip=0., filter='GI', row_num=None, col_num=None, xcen=None, ycen=None): """ Creat a wcs frame for CCST with multiple extensions Parameters @@ -189,11 +191,11 @@ def WCS_def(xlen = 9216, ylen = 9232, gapy = 898.0, gapx1 = 534, gapx2 = 1309, r r_dat['CTYPE2'] = 'DEC--TAN' r_dat['CRVAL1'] = ra_ref r_dat['CRVAL2'] = dec_ref - + flag_x = [0, 1, -1, 1, -1] flag_y = [0, 1, 1, -1, -1] - flag_ext_x = [0,-1,1,-1,1] - flag_ext_y = [0,-1,-1,1,1] + flag_ext_x = [0, -1, 1, -1, 1] + flag_ext_y = [0, -1, -1, 1, 1] pa_aper = pa if (row_num is not None) and (col_num is not None): @@ -205,35 +207,42 @@ def WCS_def(xlen = 9216, ylen = 9232, gapy = 898.0, gapx1 = 534, gapx2 = 1309, r detector_size_x = xlen detector_size_y = ylen gap_y = gapy - gap_x = [gapx1,gapx2] + gap_x = [gapx1, gapx2] gap_x1_num = 3 gap_x2_num = 2 y_center = (detector_size_y*y_num+gap_y*(y_num-1))/2 - x_center = (detector_size_x*x_num+gap_x[0]*gap_x1_num+gap_x[1]*gap_x2_num)/2 + x_center = (detector_size_x*x_num + + gap_x[0]*gap_x1_num+gap_x[1]*gap_x2_num)/2 + + gap_x_map = np.array([[0, 0, 0, 0, 0], [gap_x[0], gap_x[1], gap_x[1], gap_x[1], gap_x[1]], [gap_x[1], gap_x[0], gap_x[0], gap_x[0], gap_x[0]], [ + gap_x[0], gap_x[0], gap_x[0], gap_x[0], gap_x[0]], [gap_x[0], gap_x[0], gap_x[0], gap_x[0], gap_x[1]], [gap_x[1], gap_x[1], gap_x[1], gap_x[1], gap_x[0]]]) - gap_x_map = np.array([[0,0,0,0,0],[gap_x[0],gap_x[1],gap_x[1],gap_x[1],gap_x[1]],[gap_x[1],gap_x[0],gap_x[0],gap_x[0],gap_x[0]],[gap_x[0],gap_x[0],gap_x[0],gap_x[0],gap_x[0]],[gap_x[0],gap_x[0],gap_x[0],gap_x[0],gap_x[1]],[gap_x[1],gap_x[1],gap_x[1],gap_x[1],gap_x[0]]]) - j = row_num i = col_num # ccdnum = str((j-1)*5+i) - x_ref, y_ref = detector_size_x*i + sum(gap_x_map[0:i,j-1]) - detector_size_x/2. , (detector_size_y+gap_y)*j-gap_y-detector_size_y/2 - - for k in range(1,2): - - cd = np.array([[ pixel_scale, 0], [0, pixel_scale]])/3600.*flag_x[k] + x_ref, y_ref = detector_size_x*i + \ + sum(gap_x_map[0:i, j-1]) - detector_size_x / \ + 2., (detector_size_y+gap_y)*j-gap_y-detector_size_y/2 + + for k in range(1, 2): + + cd = np.array([[pixel_scale, 0], [0, pixel_scale]]) / \ + 3600.*flag_x[k] cd_rot = rotate_CD_matrix(cd, pa_aper) # f = open("CCD"+ccdnum.rjust(2,'0')+"_extension"+str(k)+"_wcs.param","w") - r_dat['CRPIX1'] = flag_ext_x[k]*((x_ref+flag_ext_x[k]*detector_size_x/2)-x_center) - r_dat['CRPIX2'] = flag_ext_y[k]*((y_ref+flag_ext_y[k]*detector_size_y/2)-y_center) - r_dat['CD1_1'] = cd_rot[0,0] - r_dat['CD1_2'] = cd_rot[0,1] - r_dat['CD2_1'] = cd_rot[1,0] - r_dat['CD2_2'] = cd_rot[1,1] + r_dat['CRPIX1'] = flag_ext_x[k] * \ + ((x_ref+flag_ext_x[k]*detector_size_x/2)-x_center) + r_dat['CRPIX2'] = flag_ext_y[k] * \ + ((y_ref+flag_ext_y[k]*detector_size_y/2)-y_center) + r_dat['CD1_1'] = cd_rot[0, 0] + r_dat['CD1_2'] = cd_rot[0, 1] + r_dat['CD2_1'] = cd_rot[1, 0] + r_dat['CD2_2'] = cd_rot[1, 1] if filter in ['GU', 'GV', 'GI']: @@ -265,12 +274,13 @@ def WCS_def(xlen = 9216, ylen = 9232, gapy = 898.0, gapx1 = 534, gapx2 = 1309, r y_pixs[i_pix] = y pix_coor = np.array([x, y]) - sc1 = calcaluteSLSRotSkyCoor(pix_xy=pix_coor, rot_angle=sls_rot, xlen=xlen, ylen=ylen, w=w) + sc1 = calcaluteSLSRotSkyCoor( + pix_xy=pix_coor, rot_angle=sls_rot, xlen=xlen, ylen=ylen, w=w) # print(sc1[0,0],sc1[0,1]) sky_coors.append((sc1[0, 0], sc1[0, 1])) wcs_new = fit_wcs_from_points(xy=np.array([x_pixs, y_pixs]), - world_coords=SkyCoord(sky_coors, frame="icrs", unit="deg"), projection='TAN') + world_coords=SkyCoord(sky_coors, frame="icrs", unit="deg"), projection='TAN') # print(wcs_new) # test_center = wcs_new.wcs_pix2world(np.array([[xlen / 2, ylen / 2]]), 1) @@ -294,12 +304,12 @@ def WCS_def(xlen = 9216, ylen = 9232, gapy = 898.0, gapx1 = 534, gapx2 = 1309, r r_dat['CRPIX2'] = -y1 # cd = np.array([[ pixel_scale, 0], [0, pixel_scale]])/3600.*flag_x[1] - cd = np.array([[ pixel_scale, 0], [0, -pixel_scale]])/3600. + cd = np.array([[pixel_scale, 0], [0, -pixel_scale]])/3600. cd_rot = rotate_CD_matrix(cd, pa_aper) - r_dat['CD1_1'] = cd_rot[0,0] - r_dat['CD1_2'] = cd_rot[0,1] - r_dat['CD2_1'] = cd_rot[1,0] - r_dat['CD2_2'] = cd_rot[1,1] + r_dat['CD1_1'] = cd_rot[0, 0] + r_dat['CD1_2'] = cd_rot[0, 1] + r_dat['CD2_1'] = cd_rot[1, 0] + r_dat['CD2_2'] = cd_rot[1, 1] w = wcs.WCS(naxis=2) w.wcs.crpix = [r_dat['CRPIX1'], r_dat['CRPIX2']] @@ -320,10 +330,12 @@ def WCS_def(xlen = 9216, ylen = 9232, gapy = 898.0, gapx1 = 534, gapx2 = 1309, r x_pixs[i_pix] = x y_pixs[i_pix] = y pix_coor = np.array([x, y]) - sc1 = calcaluteSLSRotSkyCoor(pix_xy=pix_coor, rot_angle=rotate_chip, xlen=xlen, ylen=ylen, w=w) + sc1 = calcaluteSLSRotSkyCoor( + pix_xy=pix_coor, rot_angle=rotate_chip, xlen=xlen, ylen=ylen, w=w) sky_coors.append((sc1[0, 0], sc1[0, 1])) - wcs_new = fit_wcs_from_points(xy=np.array([x_pixs, y_pixs]), - world_coords=SkyCoord(sky_coors, frame="icrs", unit="deg"), + wcs_new = fit_wcs_from_points(xy=np.array([x_pixs, y_pixs]), + world_coords=SkyCoord( + sky_coors, frame="icrs", unit="deg"), projection='TAN') r_dat['CD1_1'] = wcs_new.wcs.cd[0, 0] r_dat['CD1_2'] = wcs_new.wcs.cd[0, 1] @@ -336,30 +348,31 @@ def WCS_def(xlen = 9216, ylen = 9232, gapy = 898.0, gapx1 = 534, gapx2 = 1309, r r_dat['CRVAL2'] = wcs_new.wcs.crval[1] else: - raise ValueError('In function WCS_def(): Either (row_num, col_num) or (xcen, ycen, pixel_size) should be given') - - return r_dat + raise ValueError( + 'In function WCS_def(): Either (row_num, col_num) or (xcen, ycen, pixel_size) should be given') + return r_dat -#TODO project_cycle is temporary, is not in header defined, delete in future -def generatePrimaryHeader(xlen = 9216, ylen = 9232, pointing_id = '00000001', pointing_type_code='101', ra = 60, dec = -40, pixel_scale = 0.074, time_pt = None, im_type = 'SCI', exptime=150., sat_pos = [0.,0.,0.], sat_vel = [0., 0., 0.], project_cycle=6, run_counter=0, chip_name="01"): +# TODO project_cycle is temporary, is not in header defined, delete in future +def generatePrimaryHeader(xlen=9216, ylen=9232, pointing_id='00000001', pointing_type_code='101', ra=60, dec=-40, pixel_scale=0.074, time_pt=None, im_type='SCI', exptime=150., sat_pos=[0., 0., 0.], sat_vel=[0., 0., 0.], project_cycle=6, run_counter=0, chip_name="01"): # array_size1, array_size2, flux, sigma = int(argv[1]), int(argv[2]), 1000.0, 5.0 - # k = (row_num-1)*6+col_num # ccdnum = str(k) datetime_obs = datetime.utcfromtimestamp(time_pt) datetime_obs = datetime_obs.replace(tzinfo=timezone.utc) # print(datetime_obs.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]) - datetime_obs = datetime.utcfromtimestamp(np.round(datetime_obs.timestamp(), 1)) + datetime_obs = datetime.utcfromtimestamp( + np.round(datetime_obs.timestamp(), 1)) # print(datetime_obs.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]) # date_obs = datetime_obs.strftime("%y%m%d") # time_obs = datetime_obs.strftime("%H%M%S%f")[:-5] - g_header_fn = os.path.split(os.path.realpath(__file__))[0] + '/csst_msc_l0_ms.fits' + g_header_fn = os.path.split(os.path.realpath(__file__))[ + 0] + '/csst_msc_l0_ms.fits' f = open(os.path.split(os.path.realpath(__file__))[0] + '/filter.lst') s = f.readline() s = s.strip("\n") @@ -386,7 +399,6 @@ def generatePrimaryHeader(xlen = 9216, ylen = 9232, pointing_id = '00000001', po # h_card = fits.card.Card(header_toml[h_key][key]['key'],header_toml[h_key][key]['example'],header_toml[h_key][key]['comment']) # h_prim.append(h_card) - # h_prim['PIXSIZE1'] = xlen # h_prim['PIXSIZE2'] = ylen @@ -404,14 +416,15 @@ def generatePrimaryHeader(xlen = 9216, ylen = 9232, pointing_id = '00000001', po # # OBS_id = '1'+ obs_type[im_type] + str(int(project_cycle)) + pointNum.rjust(7,'0') # OBS_id = '1'+ obs_type[im_type] + str(int(project_cycle)) + str(int(run_counter)).rjust(2, '0') + pointNum.rjust(5,'0') - OBS_id = get_obs_id(img_type=im_type, project_cycle=project_cycle, run_counter=run_counter, pointing_id=pointing_id, pointing_type_code = pointing_type_code) + OBS_id = get_obs_id(img_type=im_type, project_cycle=project_cycle, run_counter=run_counter, + pointing_id=pointing_id, pointing_type_code=pointing_type_code) # h_prim['OBJECT'] = str(int(project_cycle)) + pointNum.rjust(7, '0') h_prim['OBJECT'] = pointing_id h_prim['OBSID'] = OBS_id # h_prim['TELFOCUS'] = 'f/14' h_prim['EXPTIME'] = exptime - + # # Define file types # file_type = {'SCI':'SCIE', 'BIAS':'BIAS', 'DARK':'DARK', 'FLAT':'FLAT', 'CRS':'CRS', 'CRD':'CRD','CALS':'CALS','CALF':'CALF'} # h_prim['FILETYPE'] = file_type[im_type] @@ -420,8 +433,10 @@ def generatePrimaryHeader(xlen = 9216, ylen = 9232, pointing_id = '00000001', po co = coord.SkyCoord(ra, dec, unit='deg') - ra_hms = format(co.ra.hms.h, '02.0f') + format(co.ra.hms.m, '02.0f') + format(co.ra.hms.s, '02.1f') - dec_hms = format(co.dec.dms.d, '02.0f') + format(abs(co.dec.dms.m), '02.0f') + format(abs(co.dec.dms.s), '02.0f') + ra_hms = format(co.ra.hms.h, '02.0f') + format(co.ra.hms.m, + '02.0f') + format(co.ra.hms.s, '02.1f') + dec_hms = format(co.dec.dms.d, '02.0f') + format(abs(co.dec.dms.m), + '02.0f') + format(abs(co.dec.dms.s), '02.0f') if dec >= 0: h_prim['TARGET'] = ra_hms + '+' + dec_hms else: @@ -435,8 +450,6 @@ def generatePrimaryHeader(xlen = 9216, ylen = 9232, pointing_id = '00000001', po h_prim['RA_PNT1'] = ra h_prim['DEC_PNT1'] = dec - - # h_prim['PIXSCAL1'] = pixel_scale # h_prim['PIXSCAL2'] = pixel_scale @@ -452,11 +465,13 @@ def generatePrimaryHeader(xlen = 9216, ylen = 9232, pointing_id = '00000001', po # file_start_time = '20' + date[0:6] + time_obs[0:6] file_start_time = datetime_obs.strftime("%Y%m%d%H%M%S") end_time_str = str(tend.datetime) - file_end_time = end_time_str[0:4] + end_time_str[5:7]+end_time_str[8:10] + end_time_str[11:13] + end_time_str[14:16] + end_time_str[17:19] + file_end_time = end_time_str[0:4] + end_time_str[5:7]+end_time_str[8:10] + \ + end_time_str[11:13] + end_time_str[14:16] + end_time_str[17:19] # h_prim['FILENAME'] = 'CSST_MSC_MS_' + im_type + '_' + file_start_time + '_' + file_end_time + '_' + OBS_id + '_' + CCDID[ # k - 1].rjust(2, '0') + '_L0_V01' - h_prim['FILENAME'] = 'CSST_MSC_MS_' + h_prim['FILETYPE'] + '_' + file_start_time + '_' + file_end_time + '_' + OBS_id + '_' + chip_name + '_L0_V01' - + h_prim['FILENAME'] = 'CSST_MSC_MS_' + h_prim['FILETYPE'] + '_' + \ + file_start_time + '_' + file_end_time + \ + '_' + OBS_id + '_' + chip_name + '_L0_V01' h_prim['POSI0_X'] = sat_pos[0] h_prim['POSI0_Y'] = sat_pos[1] @@ -467,21 +482,25 @@ def generatePrimaryHeader(xlen = 9216, ylen = 9232, pointing_id = '00000001', po h_prim['VELO0_Z'] = sat_vel[2] # h_prim['RA_PNT0'] = ra_hms # h_prim['DEC_PNT0'] = dec_hms - + # Get version of CSSTSim Package from pkg_resources import get_distribution # h_prim['SIM_VER'] = (get_distribution("CSSTSim").version, "Version of CSST MSC simulation software") currentDateAndTime = datetime.now() compute_name = platform.node() - h_prim['FITSSWV'] = get_distribution("csst_msc_sim").version +'_' + currentDateAndTime.strftime("%Y%m%d") + '_' +compute_name - h_prim['EPOCH'] = round((Time(h_prim['EXPSTART'], format='mjd', scale='tcb')).jyear, 1) + h_prim['FITSSWV'] = get_distribution( + "csst_msc_sim").version + '_' + currentDateAndTime.strftime("%Y%m%d") + '_' + compute_name + h_prim['EPOCH'] = round( + (Time(h_prim['EXPSTART'], format='mjd', scale='tcb')).jyear, 1) return h_prim -def generateExtensionHeader(chip, xlen = 9216, ylen = 9232,ra = 60, dec = -40, pa = -23.433, gain = 1.0, readout = 5.0, dark = 0.02, saturation=90000, pixel_scale = 0.074, pixel_size=1e-2, - extName='SCIE', row_num = None, col_num = None, xcen=None, ycen=None, timestamp = 1621915200,exptime = 150., readoutTime = 40., t_shutter_open = 1.3, t_shutter_close = 1.3): - e_header_fn = os.path.split(os.path.realpath(__file__))[0] + '/csst_msc_l0_ms.fits' +def generateExtensionHeader(chip, xlen=9216, ylen=9232, ra=60, dec=-40, pa=-23.433, gain=1.0, readout=5.0, dark=0.02, saturation=90000, pixel_scale=0.074, pixel_size=1e-2, + extName='SCIE', row_num=None, col_num=None, xcen=None, ycen=None, timestamp=1621915200, exptime=150., readoutTime=40., t_shutter_open=1.3, t_shutter_close=1.3): + + e_header_fn = os.path.split(os.path.realpath(__file__))[ + 0] + '/csst_msc_l0_ms.fits' f = open(os.path.split(os.path.realpath(__file__))[0] + '/filter.lst') s = f.readline() s = s.strip("\n") @@ -562,28 +581,35 @@ def generateExtensionHeader(chip, xlen = 9216, ylen = 9232,ra = 60, dec = -40, p t_shutter_os = tstart t_shutter_oe = Time(tstart.mjd + t_shutter_open / 86400., format="mjd") t_shutter_co = Time(tstart.mjd + exptime / 86400., format="mjd") - t_shutter_ce = Time(tstart.mjd + (exptime + t_shutter_close) / 86400., format="mjd") - t_shutter_os1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(t_shutter_os.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) + t_shutter_ce = Time( + tstart.mjd + (exptime + t_shutter_close) / 86400., format="mjd") + t_shutter_os1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp( + t_shutter_os.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) h_ext['SHTOPEN0'] = t_shutter_os1.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5] - t_shutter_oe1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(t_shutter_oe.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) + t_shutter_oe1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp( + t_shutter_oe.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) h_ext['SHTOPEN1'] = t_shutter_oe1.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5] - t_shutter_co1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(t_shutter_co.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) + t_shutter_co1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp( + t_shutter_co.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) h_ext['SHTCLOS0'] = t_shutter_co1.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5] - t_shutter_ce1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(t_shutter_ce.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) + t_shutter_ce1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp( + t_shutter_ce.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) h_ext['SHTCLOS1'] = t_shutter_ce1.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5] - tstart_read = Time(tstart.mjd + exptime / 86400., format="mjd") - tend_read = Time(tstart.mjd + (exptime + readoutTime) / 86400., format="mjd") + tend_read = Time(tstart.mjd + (exptime + readoutTime) / + 86400., format="mjd") # tstart1=tstart.datetime.replace(microsecond=round(tstart.datetime.microsecond, -5)) - tstart1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(tstart_read.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) + tstart1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp( + tstart_read.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) h_ext['ROTIME0'] = tstart1.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5] # tend_read1 = tend_read.datetime.replace(microsecond=round(tend_read.datetime.microsecond, -5)) - tend_read1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(tend_read.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) + tend_read1 = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp( + tend_read.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) h_ext['ROTIME1'] = tend_read1.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5] # h_ext['POS_ANG'] = pa - header_wcs = WCS_def(xlen=xlen, ylen=ylen, gapy=898.0, gapx1=534, gapx2=1309, ra_ref=ra, dec_ref=dec, pa=pa, pixel_scale=pixel_scale, pixel_size=pixel_size, - rotate_chip=chip.rotate_angle, filter = h_ext['FILTER'], row_num=row_num, col_num=col_num, xcen = xcen, ycen = ycen) + header_wcs = WCS_def(xlen=xlen, ylen=ylen, gapy=898.0, gapx1=534, gapx2=1309, ra_ref=ra, dec_ref=dec, pa=pa, pixel_scale=pixel_scale, pixel_size=pixel_size, + rotate_chip=chip.rotate_angle, filter=h_ext['FILTER'], row_num=row_num, col_num=col_num, xcen=xcen, ycen=ycen) h_ext['CRPIX1'] = header_wcs['CRPIX1'] h_ext['CRPIX2'] = header_wcs['CRPIX2'] @@ -604,7 +630,6 @@ def generateExtensionHeader(chip, xlen = 9216, ylen = 9232,ra = 60, dec = -40, p return h_ext - def main(argv): xlen = int(argv[1]) @@ -621,17 +646,17 @@ def main(argv): dark = float(argv[12]) fw = float(argv[13]) + h_prim = generatePrimaryHeader(xlen=xlen, ylen=ylen, ra=ra, dec=dec, psize=pSize, + row_num=ccd_row_num, col_num=ccd_col_num, pointNum=pointingNum) - - h_prim = generatePrimaryHeader(xlen = xlen, ylen = ylen,ra = ra, dec = dec, psize = pSize, row_num = ccd_row_num, col_num = ccd_col_num, pointNum = pointingNum) - - h_ext = generateExtensionHeader(xlen = xlen, ylen = ylen,ra = ra, dec = dec, pa = pa_aper, gain = gain, readout = readout, dark = dark, saturation=fw, psize = pSize, row_num = ccd_row_num, col_num = ccd_col_num) + h_ext = generateExtensionHeader(xlen=xlen, ylen=ylen, ra=ra, dec=dec, pa=pa_aper, gain=gain, + readout=readout, dark=dark, saturation=fw, psize=pSize, row_num=ccd_row_num, col_num=ccd_col_num) hdu1 = fits.PrimaryHDU(header=h_prim) - hdu2 = fits.ImageHDU(np.zeros([ylen,xlen]),header = h_ext) + hdu2 = fits.ImageHDU(np.zeros([ylen, xlen]), header=h_ext) - hdul = fits.HDUList([hdu1,hdu2]) + hdul = fits.HDUList([hdu1, hdu2]) - hdul.writeto(h_prim['FILENAME']+'.fits',output_verify='ignore') + hdul.writeto(h_prim['FILENAME']+'.fits', output_verify='ignore') # if __name__ == "__main__": # main(sys.argv) diff --git a/ObservationSim/Config/Header/Readme.pdf b/observation_sim/config/header/Readme.pdf similarity index 100% rename from ObservationSim/Config/Header/Readme.pdf rename to observation_sim/config/header/Readme.pdf diff --git a/ObservationSim/Config/Header/__init__.py b/observation_sim/config/header/__init__.py similarity index 100% rename from ObservationSim/Config/Header/__init__.py rename to observation_sim/config/header/__init__.py diff --git a/ObservationSim/Config/Header/csst_msc_l0_ms.fits b/observation_sim/config/header/csst_msc_l0_ms.fits similarity index 100% rename from ObservationSim/Config/Header/csst_msc_l0_ms.fits rename to observation_sim/config/header/csst_msc_l0_ms.fits diff --git a/ObservationSim/Config/Header/extension_header.header b/observation_sim/config/header/extension_header.header similarity index 100% rename from ObservationSim/Config/Header/extension_header.header rename to observation_sim/config/header/extension_header.header diff --git a/ObservationSim/Config/Header/extension_header.param b/observation_sim/config/header/extension_header.param similarity index 100% rename from ObservationSim/Config/Header/extension_header.param rename to observation_sim/config/header/extension_header.param diff --git a/ObservationSim/Config/Header/filter.lst b/observation_sim/config/header/filter.lst similarity index 100% rename from ObservationSim/Config/Header/filter.lst rename to observation_sim/config/header/filter.lst diff --git a/ObservationSim/Config/Header/global_header.header b/observation_sim/config/header/global_header.header similarity index 100% rename from ObservationSim/Config/Header/global_header.header rename to observation_sim/config/header/global_header.header diff --git a/ObservationSim/Config/Header/global_header.param b/observation_sim/config/header/global_header.param similarity index 100% rename from ObservationSim/Config/Header/global_header.param rename to observation_sim/config/header/global_header.param diff --git a/ObservationSim/Instrument/Filter.py b/observation_sim/instruments/Filter.py similarity index 58% rename from ObservationSim/Instrument/Filter.py rename to observation_sim/instruments/Filter.py index efc58694b2a75b6016b4653689be89bf24fda151..6a01ca972d59ec767694de21009f769ae160c2ff 100755 --- a/ObservationSim/Instrument/Filter.py +++ b/observation_sim/instruments/Filter.py @@ -4,9 +4,9 @@ import os import numpy as np import gc -import ObservationSim.Instrument._util as _util -from ObservationSim.Instrument.FilterParam import FilterParam -from ObservationSim.Straylight import Straylight +import observation_sim.instruments._util as _util +from observation_sim.instruments.FilterParam import FilterParam +from observation_sim.sky_background import Straylight try: import importlib.resources as pkg_resources @@ -14,6 +14,7 @@ except ImportError: # Try backported to PY<37 'importlib_resources' import importlib_resources as pkg_resources + class Filter(object): def __init__(self, filter_id, filter_type, filter_param, ccd_bandpass=None): self.filter_id = filter_id @@ -52,57 +53,67 @@ class Filter(object): def _get_bandpasses(self, filter_dir=None, unit='A'): if self.filter_id < 7: # Photometric try: - with pkg_resources.files('ObservationSim.Instrument.data.filters').joinpath(self.filter_type.lower() + '.txt') as filter_file: - self.filter_bandpass = galsim.Bandpass(str(filter_file), wave_type=unit) + with pkg_resources.files('observation_sim.instruments.data.filters').joinpath(self.filter_type.lower() + '.txt') as filter_file: + self.filter_bandpass = galsim.Bandpass( + str(filter_file), wave_type=unit) except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data.filters', self.filter_type.lower() + '.txt') as filter_file: - self.filter_bandpass = galsim.Bandpass(str(filter_file), wave_type=unit) + with pkg_resources.path('observation_sim.instruments.data.filters', self.filter_type.lower() + '.txt') as filter_file: + self.filter_bandpass = galsim.Bandpass( + str(filter_file), wave_type=unit) try: - with pkg_resources.files('ObservationSim.Instrument.data.throughputs').joinpath(self.filter_type.lower() + '_throughput.txt') as filter_file: - bandpass_full = galsim.Bandpass(str(filter_file), wave_type=unit) + with pkg_resources.files('observation_sim.instruments.data.throughputs').joinpath(self.filter_type.lower() + '_throughput.txt') as filter_file: + bandpass_full = galsim.Bandpass( + str(filter_file), wave_type=unit) except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data.throughputs', self.filter_type.lower() + '_throughput.txt') as filter_file: - bandpass_full = galsim.Bandpass(str(filter_file), wave_type=unit) + with pkg_resources.path('observation_sim.instruments.data.throughputs', self.filter_type.lower() + '_throughput.txt') as filter_file: + bandpass_full = galsim.Bandpass( + str(filter_file), wave_type=unit) # bandpass_full = bandpass_full * self.ccd_bandpass # Get sub-bandpasses bandpass_sub_list = [] try: - with pkg_resources.files('ObservationSim.Instrument.data.filters').joinpath(self.filter_type.lower() + "_sub.list") as wave_bin_file: + with pkg_resources.files('observation_sim.instruments.data.filters').joinpath(self.filter_type.lower() + "_sub.list") as wave_bin_file: wave_points = open(wave_bin_file).read().splitlines() except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data.filters', self.filter_type.lower() + "_sub.list") as wave_bin_file: + with pkg_resources.path('observation_sim.instruments.data.filters', self.filter_type.lower() + "_sub.list") as wave_bin_file: wave_points = open(wave_bin_file).read().splitlines() for i in range(2, len(wave_points), 2): - blim = max(float(wave_points[i-2])*0.1, bandpass_full.blue_limit) + blim = max(float(wave_points[i-2]) + * 0.1, bandpass_full.blue_limit) rlim = min(float(wave_points[i])*0.1, bandpass_full.red_limit) if blim >= rlim: continue - bandpass = bandpass_full.truncate(blue_limit=blim, red_limit=rlim) + bandpass = bandpass_full.truncate( + blue_limit=blim, red_limit=rlim) bandpass_sub_list.append(bandpass) # print("num of sub-bandpasses for filter#%d(%s) = "%(self.filter_id, self.filter_type), len(bandpass_sub_list), flush=True) else: # Spectroscopic sls_lamb = np.linspace(self.blue_limit, self.red_limit, 100) sls_flux = np.ones_like(sls_lamb) - con_spec = galsim.LookupTable(sls_lamb, sls_flux, interpolant='nearest') + con_spec = galsim.LookupTable( + sls_lamb, sls_flux, interpolant='nearest') bandpass_full = galsim.Bandpass(con_spec, wave_type=unit) bandpass_sub_list = [] try: - with pkg_resources.files('ObservationSim.Instrument.data.filters').joinpath(self.filter_type.lower() + "_sub.list") as wave_bin_file: + with pkg_resources.files('observation_sim.instruments.data.filters').joinpath(self.filter_type.lower() + "_sub.list") as wave_bin_file: wave_points = open(wave_bin_file).read().splitlines() except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data.filters', self.filter_type.lower() + "_sub.list") as wave_bin_file: + with pkg_resources.path('observation_sim.instruments.data.filters', self.filter_type.lower() + "_sub.list") as wave_bin_file: wave_points = open(wave_bin_file).read().splitlines() for i in range(2, len(wave_points), 2): - blim = max(float(wave_points[i - 2]) * 0.1, bandpass_full.blue_limit) - rlim = min(float(wave_points[i]) * 0.1, bandpass_full.red_limit) + blim = max(float(wave_points[i - 2]) + * 0.1, bandpass_full.blue_limit) + rlim = min(float(wave_points[i]) + * 0.1, bandpass_full.red_limit) if blim >= rlim: continue - bandpass = bandpass_full.truncate(blue_limit=blim, red_limit=rlim) + bandpass = bandpass_full.truncate( + blue_limit=blim, red_limit=rlim) bandpass_sub_list.append(bandpass) # print("num of sub-bandpasses for filter#%d(%s) = " % (self.filter_id, self.filter_type), len(bandpass_sub_list), flush=True) - + return bandpass_full, bandpass_sub_list def getPhotonE(self): @@ -111,17 +122,20 @@ class Filter(object): def getSkyNoise(self, exptime, gain=1.): return self.sky_background * exptime / gain - def setFilterStrayLightPixel(self,jtime = 2460843., sat_pos = np.array([0,0,0]), pointing_radec = np.array([0,0]), sun_pos = np.array([0,0,0])): - sl = Straylight(jtime=jtime, sat_pos=sat_pos, pointing_radec=pointing_radec,sun_pos=sun_pos) + def setFilterStrayLightPixel(self, jtime=2460843., sat_pos=np.array([0, 0, 0]), pointing_radec=np.array([0, 0]), sun_pos=np.array([0, 0, 0])): + sl = Straylight(jtime=jtime, sat_pos=sat_pos, + pointing_radec=pointing_radec, sun_pos=sun_pos) if self.filter_type in _util.SPEC_FILTERS: - s_pix, spec = sl.calculateStrayLightGrating(grating = self.filter_type.upper()) - if s_pix>0.8: + s_pix, spec = sl.calculateStrayLightGrating( + grating=self.filter_type.upper()) + if s_pix > 0.8: s_pix = 0.8 self.sky_background = s_pix self.zodical_spec = spec elif self.filter_type.lower() in [x.lower for x in _util.PHOT_FILTERS]: - s_pix = sl.calculateStrayLightFilter(filter=self.filter_type.lower()) - if s_pix>1: + s_pix = sl.calculateStrayLightFilter( + filter=self.filter_type.lower()) + if s_pix > 1: s_pix = 1 self.sky_background = s_pix self.zodical_spec = None @@ -144,6 +158,8 @@ class Filter(object): full_well = 90000 throughput_file = self.filter_type.lower() + '_throughput.txt' - self.mag_limiting, self.mag_saturation = _util.calculateLimitMag(psf_fwhm=psf_fwhm, pixelSize=pix_scale, throughputFn=throughput_file, readout=5.0, skyFn=skyFn, darknoise=dark_noise, exTime=exptime, fw=full_well) + self.mag_limiting, self.mag_saturation = _util.calculateLimitMag( + psf_fwhm=psf_fwhm, pixelSize=pix_scale, throughputFn=throughput_file, readout=5.0, skyFn=skyFn, darknoise=dark_noise, exTime=exptime, fw=full_well) - print("for filter %s: mag_limiting: %.3f, mag_saturation: %.3f"%(self.filter_type, self.mag_limiting, self.mag_saturation)) + print("for filter %s: mag_limiting: %.3f, mag_saturation: %.3f" % + (self.filter_type, self.mag_limiting, self.mag_saturation)) diff --git a/ObservationSim/Instrument/FilterParam.py b/observation_sim/instruments/FilterParam.py similarity index 52% rename from ObservationSim/Instrument/FilterParam.py rename to observation_sim/instruments/FilterParam.py index 8f87b8fffd1f661b7c1eb2ef3eec352a5e24f94f..fe109274d48f88d71a8f97cfc1004aa4858f829b 100755 --- a/ObservationSim/Instrument/FilterParam.py +++ b/observation_sim/instruments/FilterParam.py @@ -1,6 +1,7 @@ import galsim import numpy as np + class FilterParam(object): def __init__(self, filter_dir=None, filter_param=None): self.param = self._filtParam(filter_param) @@ -14,7 +15,7 @@ class FilterParam(object): TODO: subject to change Basic parameters of the CSSOS filters. """ - # filter parameters: name: + # filter parameters: name: # 1) effective wavelength # 2) effective width # 3) blue end @@ -26,19 +27,20 @@ class FilterParam(object): # 8) dim end magnitude if filter_param == None: filtP = { - "NUV": [2867.7, 705.4, 2470.0, 3270.0, 0.1404, 0.004, 15.7, 25.4], - "u": [3601.1, 852.1, 3120.0, 4090.0, 0.2176, 0.021, 16.1, 25.4], - "g": [4754.5, 1569.8, 3900.0, 5620.0, 0.4640, 0.164, 17.2, 26.3], - "r": [6199.8, 1481.2, 5370.0, 7030.0, 0.5040, 0.207, 17.0, 26.0], - "i": [7653.2, 1588.1, 6760.0, 8550.0, 0.4960, 0.212, 16.7, 25.9], - "z": [9600.6, 2490.5, 8240.0, 11000.0, 0.2000, 0.123, 15.7, 25.2], - "y": [10051.0, 1590.6, 9130.0, 11000.0, 0.0960, 0.037, 14.4, 24.4], - "FGS": [5000.0, 8000.0, 3000.0, 11000.0, 0.6500, 0.164, 0., 30.], # [TODO] - - "GU": [0.0, 0.0, 2550.0, 4200.0, 1.0, 0.037, 14.0, 26.0], - "GV": [0.0, 0.0, 4000.0, 6500.0, 1.0, 0.037, 14.0, 26.0], - "GI": [0.0, 0.0, 6200.0, 10000.0, 1.0, 0.037, 14.0, 26.0], - } + "NUV": [2867.7, 705.4, 2470.0, 3270.0, 0.1404, 0.004, 15.7, 25.4], + "u": [3601.1, 852.1, 3120.0, 4090.0, 0.2176, 0.021, 16.1, 25.4], + "g": [4754.5, 1569.8, 3900.0, 5620.0, 0.4640, 0.164, 17.2, 26.3], + "r": [6199.8, 1481.2, 5370.0, 7030.0, 0.5040, 0.207, 17.0, 26.0], + "i": [7653.2, 1588.1, 6760.0, 8550.0, 0.4960, 0.212, 16.7, 25.9], + "z": [9600.6, 2490.5, 8240.0, 11000.0, 0.2000, 0.123, 15.7, 25.2], + "y": [10051.0, 1590.6, 9130.0, 11000.0, 0.0960, 0.037, 14.4, 24.4], + # [TODO] + "FGS": [5000.0, 8000.0, 3000.0, 11000.0, 0.6500, 0.164, 0., 30.], + + "GU": [0.0, 0.0, 2550.0, 4200.0, 1.0, 0.037, 14.0, 26.0], + "GV": [0.0, 0.0, 4000.0, 6500.0, 1.0, 0.037, 14.0, 26.0], + "GI": [0.0, 0.0, 6200.0, 10000.0, 1.0, 0.037, 14.0, 26.0], + } else: filtP = filter_param @@ -48,10 +50,10 @@ class FilterParam(object): """ read filters and save into Python dictionary NOTE: the wavelength unit must be in "Angstrom" - + Parameters: Same as function 'seds' - + Return: Same as function 'seds' """ @@ -65,9 +67,10 @@ class FilterParam(object): ifiltn = filtdir+itype+".dat" iblim = filtParams[itype][2] irlim = filtParams[itype][3] - ifilt = galsim.Bandpass(ifiltn,wave_type=unit,blue_limit=iblim,red_limit=irlim) - wave = ifilt.wave_list + ifilt = galsim.Bandpass( + ifiltn, wave_type=unit, blue_limit=iblim, red_limit=irlim) + wave = ifilt.wave_list ifilt = ifilt.func(wave) - filts[itype] = np.transpose(np.array([wave*10.0,ifilt])) + filts[itype] = np.transpose(np.array([wave*10.0, ifilt])) - return filtype, filts \ No newline at end of file + return filtype, filts diff --git a/ObservationSim/Instrument/FocalPlane.py b/observation_sim/instruments/FocalPlane.py similarity index 81% rename from ObservationSim/Instrument/FocalPlane.py rename to observation_sim/instruments/FocalPlane.py index b3e309cf2a7b6f659794dece5de2ae326ee0757b..90c2e0e7372cc2d398ab694248364e8fb73da097 100755 --- a/ObservationSim/Instrument/FocalPlane.py +++ b/observation_sim/instruments/FocalPlane.py @@ -40,18 +40,6 @@ class FocalPlane(object): for i in range(1, 31): self.ignore_chips.append(i) - # if config is not None: - # self.nchip_x = config["nchip_x"] - # self.nchip_y = config["nchip_y"] - # self.npix_tot_x = config["npix_tot_x"] - # self.npix_tot_y = config["npix_tot_y"] - # self.npix_gap_x = config["npix_gap_x"] - # self.npix_gap_y = config["npix_gap_y"] - # if "chipLabelIDs" in config: - # self.chipLabelIDs = config["chipLabelIDs"] - # if "bad_chips" in config: - # self.bad_chips = config["bad_chips"] - # else: self.nchip_x = 6 self.nchip_y = 5 self.npix_tot_x = 59516 @@ -95,10 +83,6 @@ class FocalPlane(object): if (xcen == None) or (ycen == None): xcen = self.cen_pix_x ycen = self.cen_pix_y - # dudx = -np.cos(img_rot.rad) * pix_scale - # dudy = -np.sin(img_rot.rad) * pix_scale - # dvdx = -np.sin(img_rot.rad) * pix_scale - # dvdy = +np.cos(img_rot.rad) * pix_scale dudx = -np.cos(img_rot.rad) * pix_scale dudy = +np.sin(img_rot.rad) * pix_scale diff --git a/observation_sim/instruments/Telescope.py b/observation_sim/instruments/Telescope.py new file mode 100755 index 0000000000000000000000000000000000000000..d6c1d2fabc50ab3540026b6655e58f55ad546794 --- /dev/null +++ b/observation_sim/instruments/Telescope.py @@ -0,0 +1,45 @@ +import numpy as np + +try: + import importlib.resources as pkg_resources +except ImportError: + # Try backported to PY<37 'importlib_resources' + import importlib_resources as pkg_resources + + +class Telescope(object): + def __init__(self, param=None, optEffCurve_path=None): + self.diameter = 2.0 # in unit of meter + if param is not None: + self.diameter = param["diameter"] + self.pupil_area = np.pi * (0.5 * self.diameter)**2 + if optEffCurve_path is not None: + self.efficiency = self._get_efficiency(optEffCurve_path) + else: + try: + with pkg_resources.files('observation_sim.instruments.data').joinpath('mirror_ccdnote.txt') as optEffCurve_path: + self.efficiency = self._get_efficiency(optEffCurve_path) + except AttributeError: + with pkg_resources.path('observation_sim.instruments.data', 'mirror_ccdnote.txt') as optEffCurve_path: + self.efficiency = self._get_efficiency(optEffCurve_path) + + def _get_efficiency(self, effCurve_path): + """ Read in the efficiency of optics + for each band + Parameters: + effCurve_path: the path for efficiency file + Returns: + opticsEff: a dictionary of efficiency (a scalar) for each band + """ + f = open(effCurve_path, 'r') + for _ in range(2): + header = f.readline() + + iline = 0 + opticsEff = {} + for line in f: + line = line.strip() + columns = line.split() + opticsEff[str(columns[0])] = float(columns[2]) + f.close() + return opticsEff diff --git a/ObservationSim/Instrument/__init__.py b/observation_sim/instruments/__init__.py similarity index 82% rename from ObservationSim/Instrument/__init__.py rename to observation_sim/instruments/__init__.py index 9382b644e158ac51e146154936c506d3c599474a..75773a6e43e81a36d8363461aeea30ff0903c527 100755 --- a/ObservationSim/Instrument/__init__.py +++ b/observation_sim/instruments/__init__.py @@ -2,4 +2,4 @@ from .Telescope import Telescope from .Filter import Filter from .FilterParam import FilterParam from .FocalPlane import FocalPlane -from .Chip import Chip \ No newline at end of file +from .chip import Chip diff --git a/observation_sim/instruments/_util.py b/observation_sim/instruments/_util.py new file mode 100755 index 0000000000000000000000000000000000000000..953d229d49e04e8818427d8c26fb9e12fbf80780 --- /dev/null +++ b/observation_sim/instruments/_util.py @@ -0,0 +1,134 @@ +import numpy as np +import os +import math +from pylab import * +from scipy import interpolate + +try: + import importlib.resources as pkg_resources +except ImportError: + # Try backported to PY<37 'importlib_resources' + import importlib_resources as pkg_resources + +VC_A = 2.99792458e+18 # speed of light: A/s +VC_M = 2.99792458e+8 # speed of light: m/s +H_PLANK = 6.626196e-27 # Plank constant: erg s + +ALL_FILTERS = ["NUV", "u", "g", "r", "i", "z", "y", "GU", "GV", "GI", "FGS"] +PHOT_FILTERS = ["NUV", "u", "g", 'r', 'i', 'z', 'y', 'FGS'] +SPEC_FILTERS = ["GI", "GV", "GU"] + + +def rotate_conterclockwise(x0, y0, x, y, angle): + """ +Rotate a point counterclockwise by a given angle around a given origin. + +The angle should be given in radians. +""" + angle = np.deg2rad(angle) + qx = x0 + np.cos(angle)*(x - x0) - np.sin(angle) * (y - y0) + qy = y0 + np.sin(angle)*(x - x0) + np.cos(angle) * (y - y0) + return qx, qy + + +def photonEnergy(lambd): + """ The energy of photon at a given wavelength + + Parameter: + lambd: the wavelength in unit of Angstrom + Return: + eph: energy of photon in unit of erg + """ + nu = VC_A / lambd + eph = H_PLANK * nu + return eph + + +def calculateLimitMag(aperture=2.0, psf_fwhm=0.1969, pixelSize=0.074, pmRation=0.8, throughputFn='i_throughput.txt', readout=5.0, skyFn='sky_emiss_hubble_50_50_A.dat', darknoise=0.02, exTime=150, exNum=1, fw=90000): + ''' + description: + param {*} aperture: unit m, default 2 m + param {*} psf_fwhm: psf fwhm, default 0.1969" + param {*} pixelSize: pixel size, default 0.074" + param {*} pmRation: the ratio of souce flux in the limit mag calculation + param {*} throughputFn: throuput file name + param {*} readout: unit, e-/pixel + param {*} skyFn: sky sed file name, average of hst, 'sky_emiss_hubble_50_50_A.dat' + param {*} darknoise: unit, e-/pixel/s + param {*} exTime: exposure time one time, default 150s + param {*} exNum: exposure number, defautl 1 + param {*} fw, full well value( or saturation value),default 90000e-/pixel + return {*} limit mag and saturation mag + ''' + try: + with pkg_resources.files('observation_sim.instruments.data.throughputs').joinpath(throughputFn) as data_file: + throughput_f = np.loadtxt(data_file) + except AttributeError: + with pkg_resources.path('observation_sim.instruments.data.throughputs', throughputFn) as data_file: + throughput_f = np.loadtxt(data_file) + thr_i = interpolate.interp1d( + throughput_f[:, 0]/10, throughput_f[:, 1]) # wavelength in anstrom + f_s = 200 + f_e = 1100 + delt_f = 0.5 + + data_num = int((f_e-f_s)/delt_f+1) + + eff = np.zeros([data_num, 2]) + eff[:, 0] = np.arange(f_s, f_e+delt_f, delt_f) + eff[:, 1] = thr_i(eff[:, 0]) + + wave = np.arange(f_s, f_e+delt_f, delt_f) + wavey = np.ones(wave.shape[0]) + + try: + with pkg_resources.files('observation_sim.instruments.data.throughputs').joinpath(skyFn) as data_file: + skydata = np.loadtxt(data_file) + except AttributeError: + with pkg_resources.path('observation_sim.instruments.data.throughputs', skyFn) as data_file: + skydata = np.loadtxt(data_file) + skydatai = interpolate.interp1d(skydata[:, 0]/10, skydata[:, 1]*10) + + sky_data = np.zeros([data_num, 2]) + sky_data[:, 0] = np.arange(f_s, f_e+delt_f, delt_f) + sky_data[:, 1] = skydatai(sky_data[:, 0]) + + flux_sky = trapz((sky_data[:, 1])*eff[:, 1], sky_data[:, 0]) + skyPix = flux_sky*pixelSize*pixelSize*pi*(aperture*aperture/4) + + # limit mag + + r_pix = psf_fwhm*0.7618080243778568/pixelSize # radius RE80, pixel + cnum = math.pi * r_pix * r_pix + sn = 5 + + d = skyPix*exTime*exNum*cnum + darknoise * \ + exTime*exNum*cnum+readout*readout*cnum*exNum + a = 1 + b = -sn*sn + c = -sn*sn*d + + flux = (-b+sqrt(b*b-4*a*c))/(2*a)/pmRation + limitMag = -2.5*log10(flux/(54799275581.04437 * trapz(wavey * + eff[:, 1]/wave, wave, 0.1)*exTime*exNum*pi*(aperture/2)*(aperture/2))) + + # saturation mag + + from astropy.modeling.models import Gaussian2D + m_size = int(20 * psf_fwhm/pixelSize) + if m_size % 2 == 0: + m_size + 1 + m_cen = m_size//2 + psf_sigma = psf_fwhm/2.355/pixelSize + + gaussShape = Gaussian2D(1, m_cen, m_cen, psf_sigma, psf_sigma) + yp, xp = np.mgrid[0:m_size, 0:m_size] + psfMap = gaussShape(xp, yp) + maxRatio = np.amax(psfMap)/np.sum(psfMap) + # print(maxRatio) + + flux_sat = fw/maxRatio*exNum + satMag = -2.5*log10(flux_sat/(54799275581.04437 * trapz(wavey * + eff[:, 1]/wave, wave, 0.1)*exTime*exNum*pi*(aperture/2)*(aperture/2))) + + return limitMag, satMag diff --git a/observation_sim/instruments/chip/Chip.py b/observation_sim/instruments/chip/Chip.py new file mode 100755 index 0000000000000000000000000000000000000000..e50b6640133512bba4da952d5e80613d01d6eda8 --- /dev/null +++ b/observation_sim/instruments/chip/Chip.py @@ -0,0 +1,280 @@ +import galsim +import os +import numpy as np +import pickle +import json +from astropy.table import Table +from numpy.random import Generator, PCG64 +from astropy.io import fits +from datetime import datetime + +import observation_sim.instruments._util as _util +from observation_sim.instruments.chip import effects +from observation_sim.instruments.FocalPlane import FocalPlane +from observation_sim.config.header import generatePrimaryHeader, generateExtensionHeader +from observation_sim.instruments._util import rotate_conterclockwise +from observation_sim.instruments.chip import chip_utils +from observation_sim.instruments.chip.libCTI.CTI_modeling import CTI_sim + +try: + import importlib.resources as pkg_resources +except ImportError: + # Try backported to PY<37 'importlib_resources' + import importlib_resources as pkg_resources + + +class Chip(FocalPlane): + def __init__(self, chipID, ccdEffCurve_dir=None, CRdata_dir=None, sls_dir=None, config=None, treering_func=None, logger=None): + # Get focal plane (instance of paraent class) info + super().__init__() + self.nsecy = 2 + self.nsecx = 8 + self.gain_channel = np.ones(self.nsecy * self.nsecx) + self._set_attributes_from_config(config) + + self.logger = logger + + # A chip ID must be assigned + self.chipID = int(chipID) + self.chip_name = str(chipID).rjust(2, '0') + + # Get corresponding filter info + self.filter_id, self.filter_type = self.getChipFilter() + self.survey_type = self._getSurveyType() + + if self.filter_type != "FGS": + self._getChipRowCol() + + # Set the relavent specs for detectors + try: + with pkg_resources.files('observation_sim.instruments.data.ccd').joinpath("chip_definition.json") as chip_definition: + with open(chip_definition, "r") as f: + chip_dict = json.load(f)[str(self.chipID)] + except AttributeError: + with pkg_resources.path('observation_sim.instruments.data.ccd', "chip_definition.json") as chip_definition: + with open(chip_definition, "r") as f: + chip_dict = json.load(f)[str(self.chipID)] + for key in chip_dict: + setattr(self, key, chip_dict[key]) + + self.fdModel = None + if self.filter_type == "FGS": + fgs_name = self.chip_name[0:4] + try: + with pkg_resources.files('observation_sim.instruments.data.field_distortion').joinpath("FieldDistModelGlobal_pr4_%s.pickle" % (fgs_name.lower())) as field_distortion: + with open(field_distortion, "rb") as f: + self.fdModel = pickle.load(f) + except AttributeError: + with pkg_resources.path('observation_sim.instruments.data.field_distortion', "FieldDistModelGlobal_pr4_%s.pickle" % (fgs_name.lower())) as field_distortion: + with open(field_distortion, "rb") as f: + self.fdModel = pickle.load(f) + else: + # Get the corresponding field distortion model + try: + with pkg_resources.files('observation_sim.instruments.data.field_distortion').joinpath("FieldDistModel_v2.0.pickle") as field_distortion: + with open(field_distortion, "rb") as f: + self.fdModel = pickle.load(f) + except AttributeError: + with pkg_resources.path('observation_sim.instruments.data.field_distortion', "FieldDistModelGlobal_mainFP_v1.0.pickle") as field_distortion: + with open(field_distortion, "rb") as f: + self.fdModel = pickle.load(f) + + # Get boundary (in pix) + self.bound = self.getChipLim() + + self.ccdEffCurve_dir = ccdEffCurve_dir + self.CRdata_dir = CRdata_dir + + slsconfs = chip_utils.getChipSLSConf(chipID=self.chipID) + if np.size(slsconfs) == 1: + try: + with pkg_resources.files('observation_sim.instruments.data.sls_conf').joinpath(slsconfs) as conf_path: + self.sls_conf = str(conf_path) + except AttributeError: + with pkg_resources.path('observation_sim.instruments.data.sls_conf', slsconfs) as conf_path: + self.sls_conf = str(conf_path) + else: + # self.sls_conf = [os.path.join(self.sls_dir, slsconfs[0]), os.path.join(self.sls_dir, slsconfs[1])] + self.sls_conf = [] + try: + with pkg_resources.files('observation_sim.instruments.data.sls_conf').joinpath(slsconfs[0]) as conf_path: + self.sls_conf.append(str(conf_path)) + except AttributeError: + with pkg_resources.path('observation_sim.instruments.data.sls_conf', slsconfs[0]) as conf_path: + self.sls_conf.append(str(conf_path)) + try: + with pkg_resources.files('observation_sim.instruments.data.sls_conf').joinpath(slsconfs[1]) as conf_path: + self.sls_conf.append(str(conf_path)) + except AttributeError: + with pkg_resources.path('observation_sim.instruments.data.sls_conf', slsconfs[1]) as conf_path: + self.sls_conf.append(str(conf_path)) + + self.effCurve = self._getChipEffCurve(self.filter_type) + self._getCRdata() + + # # Define the sensor model + self.sensor = galsim.Sensor() + + self.flat_cube = None # for spectroscopic flat field cube simulation + + def _set_attributes_from_config(self, config): + # Default setting + self.read_noise = 5.0 # e/pix + self.dark_noise = 0.02 # e/pix/s + self.rotate_angle = 0. + self.overscan = 1000 + # Override default values + # for key in ["gain", "bias_level, dark_exptime", "flat_exptime", "readout_time", "full_well", "read_noise", "dark_noise", "overscan"]: + # if key in config["ins_effects"]: + # setattr(self, key, config["ins_effects"][key]) + + def _getChipRowCol(self): + self.rowID, self.colID = self.getChipRowCol(self.chipID) + + def getChipRowCol(self, chipID): + rowID = ((chipID - 1) % 5) + 1 + colID = 6 - ((chipID - 1) // 5) + return rowID, colID + + def _getSurveyType(self): + if self.filter_type in _util.SPEC_FILTERS: + return "spectroscopic" + elif self.filter_type in _util.PHOT_FILTERS: + return "photometric" + # elif self.filter_type in ["FGS"]: + # return "FGS" + + def _getChipEffCurve(self, filter_type): + # CCD efficiency curves + if filter_type in ['NUV', 'u', 'GU']: + filename = 'UV0.txt' + if filter_type in ['g', 'r', 'GV', 'FGS']: + # TODO, need to switch to the right efficiency curvey for FGS CMOS + filename = 'Astro_MB.txt' + if filter_type in ['i', 'z', 'y', 'GI']: + filename = 'Basic_NIR.txt' + try: + with pkg_resources.files('observation_sim.instruments.data.ccd').joinpath(filename) as ccd_path: + table = Table.read(ccd_path, format='ascii') + except AttributeError: + with pkg_resources.path('observation_sim.instruments.data.ccd', filename) as ccd_path: + table = Table.read(ccd_path, format='ascii') + throughput = galsim.LookupTable( + x=table['col1'], f=table['col2'], interpolant='linear') + bandpass = galsim.Bandpass(throughput, wave_type='nm') + return bandpass + + def _getCRdata(self): + try: + with pkg_resources.files('observation_sim.instruments.data').joinpath("wfc-cr-attachpixel.dat") as cr_path: + self.attachedSizes = np.loadtxt(cr_path) + except AttributeError: + with pkg_resources.path('observation_sim.instruments.data', "wfc-cr-attachpixel.dat") as cr_path: + self.attachedSizes = np.loadtxt(cr_path) + + # def loadSLSFLATCUBE(self, flat_fn='flat_cube.fits'): + # try: + # with pkg_resources.files('observation_sim.instruments.data').joinpath(flat_fn) as data_path: + # flat_fits = fits.open(data_path, ignore_missing_simple=True) + # except AttributeError: + # with pkg_resources.path('observation_sim.instruments.data', flat_fn) as data_path: + # flat_fits = fits.open(data_path, ignore_missing_simple=True) + + # fl = len(flat_fits) + # fl_sh = flat_fits[0].data.shape + # assert fl == 4, 'FLAT Field Cube is Not 4 layess!!!!!!!' + # self.flat_cube = np.zeros([fl, fl_sh[0], fl_sh[1]]) + # for i in np.arange(0, fl, 1): + # self.flat_cube[i] = flat_fits[i].data + + def getChipFilter(self, chipID=None): + """Return the filter index and type for a given chip #(chipID) + """ + filter_type_list = _util.ALL_FILTERS + if chipID == None: + chipID = self.chipID + + # updated configurations + if chipID > 42 or chipID < 1: + raise ValueError("!!! Chip ID: [1,42]") + if chipID in [6, 15, 16, 25]: + filter_type = "y" + if chipID in [11, 20]: + filter_type = "z" + if chipID in [7, 24]: + filter_type = "i" + if chipID in [14, 17]: + filter_type = "u" + if chipID in [9, 22]: + filter_type = "r" + if chipID in [12, 13, 18, 19]: + filter_type = "NUV" + if chipID in [8, 23]: + filter_type = "g" + if chipID in [1, 10, 21, 30]: + filter_type = "GI" + if chipID in [2, 5, 26, 29]: + filter_type = "GV" + if chipID in [3, 4, 27, 28]: + filter_type = "GU" + if chipID in range(31, 43): + filter_type = 'FGS' + filter_id = filter_type_list.index(filter_type) + + return filter_id, filter_type + + def getChipLim(self, chipID=None): + """Calculate the edges in pixel for a given CCD chip on the focal plane + NOTE: There are 5*4 CCD chips in the focus plane for photometric / spectroscopic observation. + Parameters: + chipID: int + the index of the chip + Returns: + A galsim BoundsD object + """ + xmin, xmax, ymin, ymax = 1e10, -1e10, 1e10, -1e10 + xcen = self.x_cen / self.pix_size + ycen = self.y_cen / self.pix_size + sign_x = [-1., 1., -1., 1.] + sign_y = [-1., -1., 1., 1.] + for i in range(4): + x = xcen + sign_x[i] * self.npix_x / 2. + y = ycen + sign_y[i] * self.npix_y / 2. + x, y = _util.rotate_conterclockwise( + x0=xcen, y0=ycen, x=x, y=y, angle=self.rotate_angle) + xmin, xmax = min(xmin, x), max(xmax, x) + ymin, ymax = min(ymin, y), max(ymax, y) + return galsim.BoundsD(xmin, xmax, ymin, ymax) + + def getSkyCoverage(self, wcs): + # print("In getSkyCoverage: xmin = %.3f, xmax = %.3f, ymin = %.3f, ymax = %.3f"%(self.bound.xmin, self.bound.xmax, self.bound.ymin, self.bound.ymax)) + return super().getSkyCoverage(wcs, self.bound.xmin, self.bound.xmax, self.bound.ymin, self.bound.ymax) + + def getSkyCoverageEnlarged(self, wcs, margin=0.5): + """The enlarged sky coverage of the chip + """ + margin /= 60.0 + bound = self.getSkyCoverage(wcs) + return galsim.BoundsD(bound.xmin - margin, bound.xmax + margin, bound.ymin - margin, bound.ymax + margin) + + def isContainObj(self, ra_obj=None, dec_obj=None, x_image=None, y_image=None, wcs=None, margin=1): + # magin in number of pix + if (ra_obj is not None) and (dec_obj is not None): + if wcs is None: + wcs = self.img.wcs + pos_obj = wcs.toImage(galsim.CelestialCoord( + ra=ra_obj*galsim.degrees, dec=dec_obj*galsim.degrees)) + x_image, y_image = pos_obj.x, pos_obj.y + elif (x_image is None) or (y_image is None): + raise ValueError( + "Either (ra_obj, dec_obj) or (x_image, y_image) should be given") + + xmin, xmax = self.bound.xmin - margin, self.bound.xmax + margin + ymin, ymax = self.bound.ymin - margin, self.bound.ymax + margin + if (x_image - xmin) * (x_image - xmax) > 0.0 or (y_image - ymin) * (y_image - ymax) > 0.0: + return False + return True + + def getChipNoise(self, exptime=150.0): + noise = self.dark_noise * exptime + self.read_noise**2 + return noise diff --git a/ObservationSim/Instrument/Chip/__init__.py b/observation_sim/instruments/chip/__init__.py similarity index 100% rename from ObservationSim/Instrument/Chip/__init__.py rename to observation_sim/instruments/chip/__init__.py diff --git a/ObservationSim/Instrument/Chip/ChipUtils.py b/observation_sim/instruments/chip/chip_utils.py similarity index 57% rename from ObservationSim/Instrument/Chip/ChipUtils.py rename to observation_sim/instruments/chip/chip_utils.py index 3de5e02d48285a563c0f8b25d6bf6340808c0d23..cb16118e6916d39a850521f6f164c019cddccf3d 100644 --- a/ObservationSim/Instrument/Chip/ChipUtils.py +++ b/observation_sim/instruments/chip/chip_utils.py @@ -5,8 +5,8 @@ import numpy as np from astropy.io import fits from datetime import datetime -from ObservationSim.Instrument.Chip import Effects as effects -from ObservationSim.Config.Header import generatePrimaryHeader, generateExtensionHeader +from observation_sim.instruments.chip import effects +from observation_sim.config.header import generatePrimaryHeader, generateExtensionHeader try: import importlib.resources as pkg_resources @@ -21,52 +21,79 @@ def log_info(msg, logger=None): else: print(msg, flush=True) + def getChipSLSGratingID(chipID): - gratingID = ['',''] - if chipID == 1: gratingID = ['GI2', 'GI1'] - if chipID == 2: gratingID = ['GV4', 'GV3'] - if chipID == 3: gratingID = ['GU2', 'GU1'] - if chipID == 4: gratingID = ['GU4', 'GU3'] - if chipID == 5: gratingID = ['GV2', 'GV1'] - if chipID == 10: gratingID = ['GI4', 'GI3'] - if chipID == 21: gratingID = ['GI6', 'GI5'] - if chipID == 26: gratingID = ['GV8', 'GV7'] - if chipID == 27: gratingID = ['GU6', 'GU5'] - if chipID == 28: gratingID = ['GU8', 'GU7'] - if chipID == 29: gratingID = ['GV6', 'GV5'] - if chipID == 30: gratingID = ['GI8', 'GI7'] + gratingID = ['', ''] + if chipID == 1: + gratingID = ['GI2', 'GI1'] + if chipID == 2: + gratingID = ['GV4', 'GV3'] + if chipID == 3: + gratingID = ['GU2', 'GU1'] + if chipID == 4: + gratingID = ['GU4', 'GU3'] + if chipID == 5: + gratingID = ['GV2', 'GV1'] + if chipID == 10: + gratingID = ['GI4', 'GI3'] + if chipID == 21: + gratingID = ['GI6', 'GI5'] + if chipID == 26: + gratingID = ['GV8', 'GV7'] + if chipID == 27: + gratingID = ['GU6', 'GU5'] + if chipID == 28: + gratingID = ['GU8', 'GU7'] + if chipID == 29: + gratingID = ['GV6', 'GV5'] + if chipID == 30: + gratingID = ['GI8', 'GI7'] return gratingID + def getChipSLSConf(chipID): confFile = '' - if chipID == 1: confFile = ['CSST_GI2.conf', 'CSST_GI1.conf'] - if chipID == 2: confFile = ['CSST_GV4.conf', 'CSST_GV3.conf'] - if chipID == 3: confFile = ['CSST_GU2.conf', 'CSST_GU1.conf'] - if chipID == 4: confFile = ['CSST_GU4.conf', 'CSST_GU3.conf'] - if chipID == 5: confFile = ['CSST_GV2.conf', 'CSST_GV1.conf'] - if chipID == 10: confFile = ['CSST_GI4.conf', 'CSST_GI3.conf'] - if chipID == 21: confFile = ['CSST_GI6.conf', 'CSST_GI5.conf'] - if chipID == 26: confFile = ['CSST_GV8.conf', 'CSST_GV7.conf'] - if chipID == 27: confFile = ['CSST_GU6.conf', 'CSST_GU5.conf'] - if chipID == 28: confFile = ['CSST_GU8.conf', 'CSST_GU7.conf'] - if chipID == 29: confFile = ['CSST_GV6.conf', 'CSST_GV5.conf'] - if chipID == 30: confFile = ['CSST_GI8.conf', 'CSST_GI7.conf'] + if chipID == 1: + confFile = ['CSST_GI2.conf', 'CSST_GI1.conf'] + if chipID == 2: + confFile = ['CSST_GV4.conf', 'CSST_GV3.conf'] + if chipID == 3: + confFile = ['CSST_GU2.conf', 'CSST_GU1.conf'] + if chipID == 4: + confFile = ['CSST_GU4.conf', 'CSST_GU3.conf'] + if chipID == 5: + confFile = ['CSST_GV2.conf', 'CSST_GV1.conf'] + if chipID == 10: + confFile = ['CSST_GI4.conf', 'CSST_GI3.conf'] + if chipID == 21: + confFile = ['CSST_GI6.conf', 'CSST_GI5.conf'] + if chipID == 26: + confFile = ['CSST_GV8.conf', 'CSST_GV7.conf'] + if chipID == 27: + confFile = ['CSST_GU6.conf', 'CSST_GU5.conf'] + if chipID == 28: + confFile = ['CSST_GU8.conf', 'CSST_GU7.conf'] + if chipID == 29: + confFile = ['CSST_GV6.conf', 'CSST_GV5.conf'] + if chipID == 30: + confFile = ['CSST_GI8.conf', 'CSST_GI7.conf'] return confFile + def generateHeader(chip, pointing, img_type=None, img_type_code=None, project_cycle='9', run_counter='1'): if (img_type is None) or (img_type_code is None): img_type = pointing.pointing_type img_type_code = pointing.pointing_type_code h_prim = generatePrimaryHeader( - xlen=chip.npix_x, - ylen=chip.npix_y, - pointing_id = pointing.obs_id, - pointing_type_code = img_type_code, - ra=pointing.ra, - dec=pointing.dec, + xlen=chip.npix_x, + ylen=chip.npix_y, + pointing_id=pointing.obs_id, + pointing_type_code=img_type_code, + ra=pointing.ra, + dec=pointing.dec, pixel_scale=chip.pix_scale, - time_pt = pointing.timestamp, + time_pt=pointing.timestamp, exptime=pointing.exp_time, im_type=img_type, sat_pos=[pointing.sat_x, pointing.sat_y, pointing.sat_z], @@ -76,16 +103,16 @@ def generateHeader(chip, pointing, img_type=None, img_type_code=None, project_cy chip_name=str(chip.chipID).rjust(2, '0')) h_ext = generateExtensionHeader( chip=chip, - xlen=chip.npix_x, - ylen=chip.npix_y, - ra=pointing.ra, - dec=pointing.dec, - pa=pointing.img_pa.deg, - gain=chip.gain, - readout=chip.read_noise, - dark=chip.dark_noise, - saturation=90000, - pixel_scale=chip.pix_scale, + xlen=chip.npix_x, + ylen=chip.npix_y, + ra=pointing.ra, + dec=pointing.dec, + pa=pointing.img_pa.deg, + gain=chip.gain, + readout=chip.read_noise, + dark=chip.dark_noise, + saturation=90000, + pixel_scale=chip.pix_scale, pixel_size=chip.pix_size, xcen=chip.x_cen, ycen=chip.y_cen, @@ -93,15 +120,16 @@ def generateHeader(chip, pointing, img_type=None, img_type_code=None, project_cy timestamp=pointing.timestamp, exptime=pointing.exp_time, readoutTime=chip.readout_time, - t_shutter_open=pointing.t_shutter_open, + t_shutter_open=pointing.t_shutter_open, t_shutter_close=pointing.t_shutter_close) return h_prim, h_ext + def output_fits_image(chip, pointing, img, output_dir, img_type=None, img_type_code=None, project_cycle='9', run_counter='1'): h_prim, h_ext = generateHeader( - chip=chip, - pointing=pointing, - img_type=img_type, + chip=chip, + pointing=pointing, + img_type=img_type, img_type_code=img_type_code, project_cycle=project_cycle, run_counter=run_counter) @@ -118,6 +146,7 @@ def output_fits_image(chip, pointing, img, output_dir, img_type=None, img_type_c fname = os.path.join(output_dir, h_prim['FILENAME']+'.fits') hdu1.writeto(fname, output_verify='ignore', overwrite=True) + def add_sky_background(img, filt, exptime, sky_map=None, tel=None): # Add sky background if sky_map is None: @@ -130,24 +159,26 @@ def add_sky_background(img, filt, exptime, sky_map=None, tel=None): # sky_map.addNoise(poisson_noise) elif img.array.shape != sky_map.shape: raise ValueError("The shape img and sky_map must be equal.") - elif tel is not None: # If sky_map is given in flux + elif tel is not None: # If sky_map is given in flux sky_map = sky_map * tel.pupil_area * exptime img += sky_map return img, sky_map + def get_flat(img, seed): flat_img = effects.MakeFlatSmooth( - GSBounds=img.bounds, - seed=seed) + GSBounds=img.bounds, + seed=seed) flat_normal = flat_img / np.mean(flat_img.array) return flat_img, flat_normal + def add_cosmic_rays(img, chip, exptime=150, seed=0): cr_map, cr_event_num = effects.produceCR_Map( - xLen=chip.npix_x, yLen=chip.npix_y, - exTime=exptime+0.5*chip.readout_time, + xLen=chip.npix_x, yLen=chip.npix_y, + exTime=exptime+0.5*chip.readout_time, cr_pixelRatio=0.003*(exptime+0.5*chip.readout_time)/600., - gain=chip.gain, + gain=chip.gain, attachedSizes=chip.attachedSizes, seed=seed) # seed: obj-imaging:+0; bias:+1; dark:+2; flat:+3; img += cr_map @@ -157,24 +188,27 @@ def add_cosmic_rays(img, chip, exptime=150, seed=0): del cr_map return img, crmap_gsimg, cr_event_num + def add_PRNU(img, chip, seed=0): prnu_img = effects.PRNU_Img( - xsize=chip.npix_x, - ysize=chip.npix_y, - sigma=0.01, + xsize=chip.npix_x, + ysize=chip.npix_y, + sigma=0.01, seed=seed) img *= prnu_img return img, prnu_img + def get_poisson(seed=0, sky_level=0.): rng_poisson = galsim.BaseDeviate(seed) poisson_noise = galsim.PoissonNoise(rng_poisson, sky_level=sky_level) return rng_poisson, poisson_noise + def get_base_img(img, chip, read_noise, readout_time, dark_noise, exptime=150., InputDark=None): if InputDark == None: # base_level = read_noise**2 + dark_noise*(exptime+0.5*readout_time) - ## base_level = dark_noise*(exptime+0.5*readout_time) + # base_level = dark_noise*(exptime+0.5*readout_time) base_level = dark_noise*(exptime) base_img1 = base_level * np.ones_like(img.array) else: @@ -186,53 +220,60 @@ def get_base_img(img, chip, read_noise, readout_time, dark_noise, exptime=150., arr = np.broadcast_to(arr, (ny, nx)) base_img2 = np.zeros_like(img.array) base_img2[:ny, :] = arr - base_img2[ny:, :] = arr[::-1,:] - base_img2[:,:] = base_img2[:,:]*(readout_time/ny)*dark_noise + base_img2[ny:, :] = arr[::-1, :] + base_img2[:, :] = base_img2[:, :]*(readout_time/ny)*dark_noise return base_img1+base_img2 + def add_poisson(img, chip, exptime=150., seed=0, sky_level=0., poisson_noise=None, dark_noise=None, InputDark=None): if poisson_noise is None: _, poisson_noise = get_poisson(seed=seed, sky_level=sky_level) read_noise = chip.read_noise if dark_noise is None: dark_noise = chip.dark_noise - base_img = get_base_img(img=img, chip=chip, read_noise=read_noise, readout_time=chip.readout_time, dark_noise=dark_noise, exptime=exptime, InputDark=InputDark) + base_img = get_base_img(img=img, chip=chip, read_noise=read_noise, readout_time=chip.readout_time, + dark_noise=dark_noise, exptime=exptime, InputDark=InputDark) img += base_img img.addNoise(poisson_noise) # img -= read_noise**2 if InputDark != None: - hdu = fits.open(InputDark) ##"Instrument/data/dark/dark_1000s_example_0.fits" + # "Instrument/data/dark/dark_1000s_example_0.fits" + hdu = fits.open(InputDark) img += hdu[0].data/hdu[0].header['exptime']*exptime hdu.close() return img, base_img + def add_brighter_fatter(img): - #Inital dynamic lib + # Inital dynamic lib try: - with pkg_resources.files('ObservationSim.Instrument.Chip.libBF').joinpath("libmoduleBF.so") as lib_path: + with pkg_resources.files('observation_sim.instruments.chip.libBF').joinpath("libmoduleBF.so") as lib_path: lib_bf = ctypes.CDLL(lib_path) except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.Chip.libBF', "libmoduleBF.so") as lib_path: + with pkg_resources.path('observation_sim.instruments.chip.libBF', "libmoduleBF.so") as lib_path: lib_bf = ctypes.CDLL(lib_path) - lib_bf.addEffects.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_int] - + lib_bf.addEffects.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.POINTER( + ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_int] + # Set bit flag bit_flag = 1 bit_flag = bit_flag | (1 << 2) nx, ny = img.array.shape nn = nx * ny - arr_ima= (ctypes.c_float*nn)() - arr_imc= (ctypes.c_float*nn)() + arr_ima = (ctypes.c_float*nn)() + arr_imc = (ctypes.c_float*nn)() - arr_ima[:]= img.array.reshape(nn) - arr_imc[:]= np.zeros(nn) + arr_ima[:] = img.array.reshape(nn) + arr_imc[:] = np.zeros(nn) lib_bf.addEffects(nx, ny, arr_ima, arr_imc, bit_flag) img.array[:, :] = np.reshape(arr_imc, [nx, ny]) del arr_ima, arr_imc return img + + """ def add_inputdark(img, chip, exptime): fname = "/share/home/weichengliang/CSST_git/test_new_sim/csst-simulation/ObservationSim/Instrument/data/dark/dark_1000s_example_0.fits" @@ -244,65 +285,81 @@ def add_inputdark(img, chip, exptime): del inputdark return img """ -def AddPreScan(GSImage, pre1=27, pre2=4, over1=71, over2=80, nsecy = 2, nsecx=8): - img= GSImage.array + + +def AddPreScan(GSImage, pre1=27, pre2=4, over1=71, over2=80, nsecy=2, nsecx=8): + img = GSImage.array ny, nx = img.shape dx = int(nx/nsecx) dy = int(ny/nsecy) - imgt=np.zeros([int(nsecy*nsecx), int(ny/nsecy+pre2+over2), int(nx/nsecx+pre1+over1)]) + imgt = np.zeros( + [int(nsecy*nsecx), int(ny/nsecy+pre2+over2), int(nx/nsecx+pre1+over1)]) for iy in range(nsecy): for ix in range(nsecx): if iy % 2 == 0: tx = ix else: tx = (nsecx-1)-ix - ty = iy - chunkidx = int(tx+ty*nsecx) #chunk1-[1,2,3,4], chunk2-[5,6,7,8], chunk3-[9,10,11,12], chunk4-[13,14,15,16] + ty = iy + # chunk1-[1,2,3,4], chunk2-[5,6,7,8], chunk3-[9,10,11,12], chunk4-[13,14,15,16] + chunkidx = int(tx+ty*nsecx) - imgtemp = np.zeros([int(ny/nsecy+pre2+over2), int(nx/nsecx+pre1+over1)]) + imgtemp = np.zeros( + [int(ny/nsecy+pre2+over2), int(nx/nsecx+pre1+over1)]) if int(chunkidx/4) == 0: - imgtemp[pre2:pre2+dy, pre1:pre1+dx] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx] + imgtemp[pre2:pre2+dy, pre1:pre1 + + dx] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx] imgt[chunkidx, :, :] = imgtemp if int(chunkidx/4) == 1: - imgtemp[pre2:pre2+dy, over1:over1+dx] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx] - imgt[chunkidx, :, :] = imgtemp #[:, ::-1] + imgtemp[pre2:pre2+dy, over1:over1 + + dx] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx] + imgt[chunkidx, :, :] = imgtemp # [:, ::-1] if int(chunkidx/4) == 2: - imgtemp[over2:over2+dy, over1:over1+dx] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx] - imgt[chunkidx, :, :] = imgtemp #[::-1, ::-1] + imgtemp[over2:over2+dy, over1:over1 + + dx] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx] + imgt[chunkidx, :, :] = imgtemp # [::-1, ::-1] if int(chunkidx/4) == 3: - imgtemp[over2:over2+dy, pre1:pre1+dx] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx] - imgt[chunkidx, :, :] = imgtemp #[::-1, :] + imgtemp[over2:over2+dy, pre1:pre1 + + dx] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx] + imgt[chunkidx, :, :] = imgtemp # [::-1, :] - imgtx1 = np.hstack(imgt[:nsecx:, :, :]) #hstack chunk(1,2)-[1,2,3,4,5,6,7,8] - imgtx2 = np.hstack(imgt[:(nsecx-1):-1, :, :]) #hstack chunk(4,3)-[16,15,14,13,12,11,,10,9] + # hstack chunk(1,2)-[1,2,3,4,5,6,7,8] + imgtx1 = np.hstack(imgt[:nsecx:, :, :]) + # hstack chunk(4,3)-[16,15,14,13,12,11,,10,9] + imgtx2 = np.hstack(imgt[:(nsecx-1):-1, :, :]) - newimg = galsim.Image(int(nx+(pre1+over1)*nsecx), int(ny+(pre2+over2)*nsecy), init_value=0) - newimg.array[:, :] = np.concatenate([imgtx1, imgtx2]) #vstack chunk(1,2) & chunk(4,3) + newimg = galsim.Image(int(nx+(pre1+over1)*nsecx), + int(ny+(pre2+over2)*nsecy), init_value=0) + newimg.array[:, :] = np.concatenate( + [imgtx1, imgtx2]) # vstack chunk(1,2) & chunk(4,3) newimg.wcs = GSImage.wcs return newimg -def AddPreScanFO(GSImage, pre1=27, pre2=4, over1=71, over2=80, nsecy = 1, nsecx=16): - img= GSImage.array + +def AddPreScanFO(GSImage, pre1=27, pre2=4, over1=71, over2=80, nsecy=1, nsecx=16): + img = GSImage.array ny, nx = img.shape dx = int(nx/nsecx) dy = int(ny/nsecy) - newimg = galsim.Image(int(nx+(pre1+over1)*nsecx), int(ny+(pre2+over2)*nsecy), init_value=0) + newimg = galsim.Image(int(nx+(pre1+over1)*nsecx), + int(ny+(pre2+over2)*nsecy), init_value=0) for ix in range(nsecx): - newimg.array[pre2:pre2+dy, pre1+ix*(dx+pre1+over1):pre1+dx+ix*(dx+pre1+over1)] = img[0:dy, 0+ix*dx:dx+ix*dx] + newimg.array[pre2:pre2+dy, pre1+ix * + (dx+pre1+over1):pre1+dx+ix*(dx+pre1+over1)] = img[0:dy, 0+ix*dx:dx+ix*dx] newimg.wcs = GSImage.wcs return newimg -def formatOutput(GSImage, nsecy = 2, nsecx=8): +def formatOutput(GSImage, nsecy=2, nsecx=8): img = GSImage.array ny, nx = img.shape dx = int(nx/nsecx) dy = int(ny/nsecy) - + imgt = np.zeros([int(nsecx*nsecy), dy, dx]) for iy in range(nsecy): for ix in range(nsecx): @@ -320,17 +377,18 @@ def formatOutput(GSImage, nsecy = 2, nsecx=8): imgt[chunkidx, :, :] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx] if int(chunkidx/4) == 3: imgt[chunkidx, :, :] = img[iy*dy:(iy+1)*dy, ix*dx:(ix+1)*dx] - - imgttx0 = np.hstack(imgt[ 0:4:, :, :]) - imgttx1 = np.hstack(imgt[ 4:8:, :, ::-1]) + + imgttx0 = np.hstack(imgt[0:4:, :, :]) + imgttx1 = np.hstack(imgt[4:8:, :, ::-1]) imgttx2 = np.hstack(imgt[8:12:, ::-1, ::-1]) - imgttx3 = np.hstack(imgt[12:16:,::-1, :]) - + imgttx3 = np.hstack(imgt[12:16:, ::-1, :]) + newimg = galsim.Image(int(dx*nsecx*nsecy), dy, init_value=0) newimg.array[:, :] = np.hstack([imgttx0, imgttx1, imgttx2, imgttx3]) return newimg -def formatRevert(GSImage, nsecy = 1, nsecx=16): + +def formatRevert(GSImage, nsecy=1, nsecx=16): img = GSImage.array ny, nx = img.shape dx = int(nx/nsecx) @@ -338,17 +396,20 @@ def formatRevert(GSImage, nsecy = 1, nsecx=16): newimg = galsim.Image(int(dx*8), int(dy*2), init_value=0) - for ix in range(0,4): + for ix in range(0, 4): tx = ix newimg.array[0:dy, 0+tx*dx:dx+tx*dx] = img[:, 0+ix*dx:dx+ix*dx] - for ix in range(4,8): + for ix in range(4, 8): tx = ix - newimg.array[0:dy, 0+tx*dx:dx+tx*dx] = img[:, 0+ix*dx:dx+ix*dx][:, ::-1] - for ix in range(8,12): + newimg.array[0:dy, 0+tx*dx:dx+tx * + dx] = img[:, 0+ix*dx:dx+ix*dx][:, ::-1] + for ix in range(8, 12): tx = 7-(ix-8) - newimg.array[0+dy:dy+dy, 0+tx*dx:dx+tx*dx] = img[:, 0+ix*dx:dx+ix*dx][::-1, ::-1] - for ix in range(12,16): + newimg.array[0+dy:dy+dy, 0+tx*dx:dx+tx * + dx] = img[:, 0+ix*dx:dx+ix*dx][::-1, ::-1] + for ix in range(12, 16): tx = 7-(ix-8) - newimg.array[0+dy:dy+dy, 0+tx*dx:dx+tx*dx] = img[:, 0+ix*dx:dx+ix*dx][::-1, :] + newimg.array[0+dy:dy+dy, 0+tx*dx:dx+tx * + dx] = img[:, 0+ix*dx:dx+ix*dx][::-1, :] return newimg diff --git a/ObservationSim/Instrument/Chip/Effects.py b/observation_sim/instruments/chip/effects.py similarity index 100% rename from ObservationSim/Instrument/Chip/Effects.py rename to observation_sim/instruments/chip/effects.py diff --git a/ObservationSim/Instrument/Chip/libCTI/__init__.py b/observation_sim/instruments/chip/libBF/__init__.py similarity index 100% rename from ObservationSim/Instrument/Chip/libCTI/__init__.py rename to observation_sim/instruments/chip/libBF/__init__.py diff --git a/ObservationSim/Instrument/Chip/libBF/diffusion_X1.c b/observation_sim/instruments/chip/libBF/diffusion_X1.c similarity index 100% rename from ObservationSim/Instrument/Chip/libBF/diffusion_X1.c rename to observation_sim/instruments/chip/libBF/diffusion_X1.c diff --git a/ObservationSim/Instrument/Chip/libBF/nrutil.c b/observation_sim/instruments/chip/libBF/nrutil.c similarity index 100% rename from ObservationSim/Instrument/Chip/libBF/nrutil.c rename to observation_sim/instruments/chip/libBF/nrutil.c diff --git a/ObservationSim/Instrument/Chip/libBF/nrutil.h b/observation_sim/instruments/chip/libBF/nrutil.h similarity index 100% rename from ObservationSim/Instrument/Chip/libBF/nrutil.h rename to observation_sim/instruments/chip/libBF/nrutil.h diff --git a/ObservationSim/Instrument/Chip/libCTI/CTI_modeling.py b/observation_sim/instruments/chip/libCTI/CTI_modeling.py similarity index 73% rename from ObservationSim/Instrument/Chip/libCTI/CTI_modeling.py rename to observation_sim/instruments/chip/libCTI/CTI_modeling.py index fcb72adc9921a0fc08f4392e346c13b7595d18e7..6c840599d15fc24a779f554b4abd05527017bc84 100644 --- a/ObservationSim/Instrument/Chip/libCTI/CTI_modeling.py +++ b/observation_sim/instruments/chip/libCTI/CTI_modeling.py @@ -1,4 +1,4 @@ -from ctypes import CDLL, POINTER, c_int, c_double,c_float,c_long,c_char_p +from ctypes import CDLL, POINTER, c_int, c_double, c_float, c_long, c_char_p from numpy.ctypeslib import ndpointer import numpy.ctypeslib as clb import numpy as np @@ -10,12 +10,12 @@ import os lib_path = os.path.dirname(os.path.realpath(__file__)) -#lib_path += "/add_CTI.so" +# lib_path += "/add_CTI.so" lib_path += "/libmoduleCTI.so" lib = CDLL(lib_path) CTI_simul = lib.__getattr__('CTI_simul') -CTI_simul.argtypes = [POINTER(POINTER(c_int)),c_int,c_int,c_int,c_int,POINTER(c_float),POINTER(c_float),\ - c_float,c_float,c_float,c_int,POINTER(c_int),c_int,POINTER(POINTER(c_int))] +CTI_simul.argtypes = [POINTER(POINTER(c_int)), c_int, c_int, c_int, c_int, POINTER(c_float), POINTER(c_float), + c_float, c_float, c_float, c_int, POINTER(c_int), c_int, POINTER(POINTER(c_int))] ''' get_trap_h = lib.__getattr__('save_trap_map') get_trap_h.argtypes = [POINTER(c_int), c_int, c_int, c_int, c_int, POINTER(c_float), c_float, c_float, c_char_p] @@ -45,42 +45,50 @@ def bin2fits(bin_file,fits_dir,nsp,nx,ny,nmax): datai[j+1,:,:] = h fits.writeto(fits_dir+"/trap_"+str(i+1)+".fits",datai,overwrite=True) ''' - + + def numpy_matrix_to_int_pointer(arr): int_pointer_array = (POINTER(c_int)*arr.shape[0])() for i in range(arr.shape[0]): - arr1 = np.array(arr[i].copy().tolist(),dtype=np.int32) + arr1 = np.array(arr[i].copy().tolist(), dtype=np.int32) int_pointer_array[i] = np.ctypeslib.as_ctypes(arr1) return int_pointer_array -def pointer_to_numpy_matrix(arr_pointer,row,col): - arr = np.zeros((row,col)) + + +def pointer_to_numpy_matrix(arr_pointer, row, col): + arr = np.zeros((row, col)) for i in range(row): for j in range(col): - arr[i,j] = arr_pointer[i][j] + arr[i, j] = arr_pointer[i][j] return arr -def CTI_sim(im,nx,ny,noverscan,nsp,nmax,beta,w,c,t,rho_trap,trap_seeds,release_seed=0): + + +def CTI_sim(im, nx, ny, noverscan, nsp, nmax, beta, w, c, t, rho_trap, trap_seeds, release_seed=0): image = im.T - nx_c,ny_c,noverscan_c,nsp_c,nmax_c = c_int(nx),c_int(ny),c_int(noverscan),c_int(nsp),c_int(nmax) + nx_c, ny_c, noverscan_c, nsp_c, nmax_c = c_int(nx), c_int( + ny), c_int(noverscan), c_int(nsp), c_int(nmax) ntotal = ny+noverscan - beta_c,w_c,c_c = c_float(beta),c_float(w),c_float(c) + beta_c, w_c, c_c = c_float(beta), c_float(w), c_float(c) t_p = np.ctypeslib.as_ctypes(t) rho_trap_p = np.ctypeslib.as_ctypes(rho_trap) image_p = numpy_matrix_to_int_pointer(image) trap_seeds1 = trap_seeds.astype(np.int32) trap_seeds_p = np.ctypeslib.as_ctypes(trap_seeds1) release_seed_c = c_int(release_seed) - image_cti = np.zeros((nx,ntotal)) + image_cti = np.zeros((nx, ntotal)) image_cti = image_cti.astype(np.int32) image_cti_p = numpy_matrix_to_int_pointer(image_cti) print(datetime.now()) - CTI_simul(image_p,nx,ny,noverscan,nsp,rho_trap_p,t_p,beta,w,c,nmax,trap_seeds_p,release_seed_c,image_cti_p) + CTI_simul(image_p, nx, ny, noverscan, nsp, rho_trap_p, t_p, beta, + w, c, nmax, trap_seeds_p, release_seed_c, image_cti_p) print(datetime.now()) - image_cti_result = np.zeros((nx,ntotal)) + image_cti_result = np.zeros((nx, ntotal)) for i in range(nx): for j in range(ntotal): - image_cti_result[i,j] = image_cti_p[i][j] + image_cti_result[i, j] = image_cti_p[i][j] return image_cti_result.T + """ if __name__ =='__main__': nx,ny,noverscan,nsp,nmax = 4608,4616,84,3,10 diff --git a/ObservationSim/Instrument/Chip/libCTI/Makefile b/observation_sim/instruments/chip/libCTI/Makefile similarity index 100% rename from ObservationSim/Instrument/Chip/libCTI/Makefile rename to observation_sim/instruments/chip/libCTI/Makefile diff --git a/ObservationSim/Instrument/data/__init__.py b/observation_sim/instruments/chip/libCTI/__init__.py similarity index 100% rename from ObservationSim/Instrument/data/__init__.py rename to observation_sim/instruments/chip/libCTI/__init__.py diff --git a/ObservationSim/Instrument/Chip/libCTI/readme b/observation_sim/instruments/chip/libCTI/readme similarity index 100% rename from ObservationSim/Instrument/Chip/libCTI/readme rename to observation_sim/instruments/chip/libCTI/readme diff --git a/ObservationSim/Instrument/Chip/libCTI/src/add_CTI.c b/observation_sim/instruments/chip/libCTI/src/add_CTI.c similarity index 100% rename from ObservationSim/Instrument/Chip/libCTI/src/add_CTI.c rename to observation_sim/instruments/chip/libCTI/src/add_CTI.c diff --git a/ObservationSim/Instrument/Chip/libCTI/src/creattraps.c b/observation_sim/instruments/chip/libCTI/src/creattraps.c similarity index 100% rename from ObservationSim/Instrument/Chip/libCTI/src/creattraps.c rename to observation_sim/instruments/chip/libCTI/src/creattraps.c diff --git a/ObservationSim/Instrument/Chip/libCTI/src/gammln.c b/observation_sim/instruments/chip/libCTI/src/gammln.c similarity index 100% rename from ObservationSim/Instrument/Chip/libCTI/src/gammln.c rename to observation_sim/instruments/chip/libCTI/src/gammln.c diff --git a/ObservationSim/Instrument/Chip/libCTI/src/gasdev.c b/observation_sim/instruments/chip/libCTI/src/gasdev.c similarity index 100% rename from ObservationSim/Instrument/Chip/libCTI/src/gasdev.c rename to observation_sim/instruments/chip/libCTI/src/gasdev.c diff --git a/ObservationSim/Instrument/Chip/libCTI/src/nrutil.c b/observation_sim/instruments/chip/libCTI/src/nrutil.c similarity index 100% rename from ObservationSim/Instrument/Chip/libCTI/src/nrutil.c rename to observation_sim/instruments/chip/libCTI/src/nrutil.c diff --git a/ObservationSim/Instrument/Chip/libCTI/src/nrutil.h b/observation_sim/instruments/chip/libCTI/src/nrutil.h similarity index 100% rename from ObservationSim/Instrument/Chip/libCTI/src/nrutil.h rename to observation_sim/instruments/chip/libCTI/src/nrutil.h diff --git a/ObservationSim/Instrument/Chip/libCTI/src/poidev.c b/observation_sim/instruments/chip/libCTI/src/poidev.c similarity index 100% rename from ObservationSim/Instrument/Chip/libCTI/src/poidev.c rename to observation_sim/instruments/chip/libCTI/src/poidev.c diff --git a/ObservationSim/Instrument/Chip/libCTI/src/ran1.c b/observation_sim/instruments/chip/libCTI/src/ran1.c similarity index 100% rename from ObservationSim/Instrument/Chip/libCTI/src/ran1.c rename to observation_sim/instruments/chip/libCTI/src/ran1.c diff --git a/ObservationSim/Instrument/Chip/libCTI/src/ran2.c b/observation_sim/instruments/chip/libCTI/src/ran2.c similarity index 100% rename from ObservationSim/Instrument/Chip/libCTI/src/ran2.c rename to observation_sim/instruments/chip/libCTI/src/ran2.c diff --git a/ObservationSim/Instrument/Chip/libCTI/src/sort.c b/observation_sim/instruments/chip/libCTI/src/sort.c similarity index 100% rename from ObservationSim/Instrument/Chip/libCTI/src/sort.c rename to observation_sim/instruments/chip/libCTI/src/sort.c diff --git a/ObservationSim/Instrument/data/ccd/__init__.py b/observation_sim/instruments/data/__init__.py similarity index 100% rename from ObservationSim/Instrument/data/ccd/__init__.py rename to observation_sim/instruments/data/__init__.py diff --git a/ObservationSim/Instrument/data/ccd/Astro_MB.txt b/observation_sim/instruments/data/ccd/Astro_MB.txt similarity index 100% rename from ObservationSim/Instrument/data/ccd/Astro_MB.txt rename to observation_sim/instruments/data/ccd/Astro_MB.txt diff --git a/ObservationSim/Instrument/data/ccd/Basic_NIR.txt b/observation_sim/instruments/data/ccd/Basic_NIR.txt similarity index 100% rename from ObservationSim/Instrument/data/ccd/Basic_NIR.txt rename to observation_sim/instruments/data/ccd/Basic_NIR.txt diff --git a/ObservationSim/Instrument/data/ccd/UV0.txt b/observation_sim/instruments/data/ccd/UV0.txt similarity index 100% rename from ObservationSim/Instrument/data/ccd/UV0.txt rename to observation_sim/instruments/data/ccd/UV0.txt diff --git a/ObservationSim/Instrument/data/field_distortion/__init__.py b/observation_sim/instruments/data/ccd/__init__.py similarity index 100% rename from ObservationSim/Instrument/data/field_distortion/__init__.py rename to observation_sim/instruments/data/ccd/__init__.py diff --git a/ObservationSim/Instrument/data/ccd/chip_definition.json b/observation_sim/instruments/data/ccd/chip_definition.json similarity index 100% rename from ObservationSim/Instrument/data/ccd/chip_definition.json rename to observation_sim/instruments/data/ccd/chip_definition.json diff --git a/ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_mainFP_v1.0.pickle b/observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_mainFP_v1.0.pickle similarity index 100% rename from ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_mainFP_v1.0.pickle rename to observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_mainFP_v1.0.pickle diff --git a/ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_pr4_fgs1.pickle b/observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_pr4_fgs1.pickle similarity index 100% rename from ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_pr4_fgs1.pickle rename to observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_pr4_fgs1.pickle diff --git a/ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_pr4_fgs2.pickle b/observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_pr4_fgs2.pickle similarity index 100% rename from ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_pr4_fgs2.pickle rename to observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_pr4_fgs2.pickle diff --git a/ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_pr4_fgs3.pickle b/observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_pr4_fgs3.pickle similarity index 100% rename from ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_pr4_fgs3.pickle rename to observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_pr4_fgs3.pickle diff --git a/ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_pr4_fgs4.pickle b/observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_pr4_fgs4.pickle similarity index 100% rename from ObservationSim/Instrument/data/field_distortion/FieldDistModelGlobal_pr4_fgs4.pickle rename to observation_sim/instruments/data/field_distortion/FieldDistModelGlobal_pr4_fgs4.pickle diff --git a/ObservationSim/Instrument/data/field_distortion/FieldDistModel_v2.0.pickle b/observation_sim/instruments/data/field_distortion/FieldDistModel_v2.0.pickle similarity index 100% rename from ObservationSim/Instrument/data/field_distortion/FieldDistModel_v2.0.pickle rename to observation_sim/instruments/data/field_distortion/FieldDistModel_v2.0.pickle diff --git a/ObservationSim/Instrument/data/filters/__init__.py b/observation_sim/instruments/data/field_distortion/__init__.py similarity index 100% rename from ObservationSim/Instrument/data/filters/__init__.py rename to observation_sim/instruments/data/field_distortion/__init__.py diff --git a/ObservationSim/Instrument/data/sls_conf/__init__.py b/observation_sim/instruments/data/filters/__init__.py similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/__init__.py rename to observation_sim/instruments/data/filters/__init__.py diff --git a/ObservationSim/Instrument/data/filters/fgs_sub.list b/observation_sim/instruments/data/filters/fgs_sub.list similarity index 100% rename from ObservationSim/Instrument/data/filters/fgs_sub.list rename to observation_sim/instruments/data/filters/fgs_sub.list diff --git a/ObservationSim/Instrument/data/filters/filter.list b/observation_sim/instruments/data/filters/filter.list similarity index 100% rename from ObservationSim/Instrument/data/filters/filter.list rename to observation_sim/instruments/data/filters/filter.list diff --git a/ObservationSim/Instrument/data/filters/g.txt b/observation_sim/instruments/data/filters/g.txt similarity index 100% rename from ObservationSim/Instrument/data/filters/g.txt rename to observation_sim/instruments/data/filters/g.txt diff --git a/ObservationSim/Instrument/data/filters/g_sub.list b/observation_sim/instruments/data/filters/g_sub.list similarity index 100% rename from ObservationSim/Instrument/data/filters/g_sub.list rename to observation_sim/instruments/data/filters/g_sub.list diff --git a/ObservationSim/Instrument/data/filters/gi_sub.list b/observation_sim/instruments/data/filters/gi_sub.list similarity index 100% rename from ObservationSim/Instrument/data/filters/gi_sub.list rename to observation_sim/instruments/data/filters/gi_sub.list diff --git a/ObservationSim/Instrument/data/filters/gu_sub.list b/observation_sim/instruments/data/filters/gu_sub.list similarity index 100% rename from ObservationSim/Instrument/data/filters/gu_sub.list rename to observation_sim/instruments/data/filters/gu_sub.list diff --git a/ObservationSim/Instrument/data/filters/gv_sub.list b/observation_sim/instruments/data/filters/gv_sub.list similarity index 100% rename from ObservationSim/Instrument/data/filters/gv_sub.list rename to observation_sim/instruments/data/filters/gv_sub.list diff --git a/ObservationSim/Instrument/data/filters/i.txt b/observation_sim/instruments/data/filters/i.txt similarity index 100% rename from ObservationSim/Instrument/data/filters/i.txt rename to observation_sim/instruments/data/filters/i.txt diff --git a/ObservationSim/Instrument/data/filters/i_sub.list b/observation_sim/instruments/data/filters/i_sub.list similarity index 100% rename from ObservationSim/Instrument/data/filters/i_sub.list rename to observation_sim/instruments/data/filters/i_sub.list diff --git a/ObservationSim/Instrument/data/filters/nuv.txt b/observation_sim/instruments/data/filters/nuv.txt similarity index 100% rename from ObservationSim/Instrument/data/filters/nuv.txt rename to observation_sim/instruments/data/filters/nuv.txt diff --git a/ObservationSim/Instrument/data/filters/nuv_sub.list b/observation_sim/instruments/data/filters/nuv_sub.list similarity index 100% rename from ObservationSim/Instrument/data/filters/nuv_sub.list rename to observation_sim/instruments/data/filters/nuv_sub.list diff --git a/ObservationSim/Instrument/data/filters/r.txt b/observation_sim/instruments/data/filters/r.txt similarity index 100% rename from ObservationSim/Instrument/data/filters/r.txt rename to observation_sim/instruments/data/filters/r.txt diff --git a/ObservationSim/Instrument/data/filters/r_sub.list b/observation_sim/instruments/data/filters/r_sub.list similarity index 100% rename from ObservationSim/Instrument/data/filters/r_sub.list rename to observation_sim/instruments/data/filters/r_sub.list diff --git a/ObservationSim/Instrument/data/filters/u.txt b/observation_sim/instruments/data/filters/u.txt similarity index 100% rename from ObservationSim/Instrument/data/filters/u.txt rename to observation_sim/instruments/data/filters/u.txt diff --git a/ObservationSim/Instrument/data/filters/u_sub.list b/observation_sim/instruments/data/filters/u_sub.list similarity index 100% rename from ObservationSim/Instrument/data/filters/u_sub.list rename to observation_sim/instruments/data/filters/u_sub.list diff --git a/ObservationSim/Instrument/data/filters/y.txt b/observation_sim/instruments/data/filters/y.txt similarity index 100% rename from ObservationSim/Instrument/data/filters/y.txt rename to observation_sim/instruments/data/filters/y.txt diff --git a/ObservationSim/Instrument/data/filters/y_sub.list b/observation_sim/instruments/data/filters/y_sub.list similarity index 100% rename from ObservationSim/Instrument/data/filters/y_sub.list rename to observation_sim/instruments/data/filters/y_sub.list diff --git a/ObservationSim/Instrument/data/filters/z.txt b/observation_sim/instruments/data/filters/z.txt similarity index 100% rename from ObservationSim/Instrument/data/filters/z.txt rename to observation_sim/instruments/data/filters/z.txt diff --git a/ObservationSim/Instrument/data/filters/z_sub.list b/observation_sim/instruments/data/filters/z_sub.list similarity index 100% rename from ObservationSim/Instrument/data/filters/z_sub.list rename to observation_sim/instruments/data/filters/z_sub.list diff --git a/ObservationSim/Instrument/data/mirror_ccdnote.txt b/observation_sim/instruments/data/mirror_ccdnote.txt similarity index 100% rename from ObservationSim/Instrument/data/mirror_ccdnote.txt rename to observation_sim/instruments/data/mirror_ccdnote.txt diff --git a/ObservationSim/Instrument/data/sls_conf/._CSST_GI1.conf b/observation_sim/instruments/data/sls_conf/._CSST_GI1.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/._CSST_GI1.conf rename to observation_sim/instruments/data/sls_conf/._CSST_GI1.conf diff --git a/ObservationSim/Instrument/data/sls_conf/._CSST_GV1.conf b/observation_sim/instruments/data/sls_conf/._CSST_GV1.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/._CSST_GV1.conf rename to observation_sim/instruments/data/sls_conf/._CSST_GV1.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GI1.conf b/observation_sim/instruments/data/sls_conf/CSST_GI1.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GI1.conf rename to observation_sim/instruments/data/sls_conf/CSST_GI1.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GI2.conf b/observation_sim/instruments/data/sls_conf/CSST_GI2.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GI2.conf rename to observation_sim/instruments/data/sls_conf/CSST_GI2.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GI3.conf b/observation_sim/instruments/data/sls_conf/CSST_GI3.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GI3.conf rename to observation_sim/instruments/data/sls_conf/CSST_GI3.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GI4.conf b/observation_sim/instruments/data/sls_conf/CSST_GI4.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GI4.conf rename to observation_sim/instruments/data/sls_conf/CSST_GI4.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GI5.conf b/observation_sim/instruments/data/sls_conf/CSST_GI5.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GI5.conf rename to observation_sim/instruments/data/sls_conf/CSST_GI5.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GI6.conf b/observation_sim/instruments/data/sls_conf/CSST_GI6.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GI6.conf rename to observation_sim/instruments/data/sls_conf/CSST_GI6.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GI7.conf b/observation_sim/instruments/data/sls_conf/CSST_GI7.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GI7.conf rename to observation_sim/instruments/data/sls_conf/CSST_GI7.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GI8.conf b/observation_sim/instruments/data/sls_conf/CSST_GI8.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GI8.conf rename to observation_sim/instruments/data/sls_conf/CSST_GI8.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GU1.conf b/observation_sim/instruments/data/sls_conf/CSST_GU1.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GU1.conf rename to observation_sim/instruments/data/sls_conf/CSST_GU1.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GU2.conf b/observation_sim/instruments/data/sls_conf/CSST_GU2.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GU2.conf rename to observation_sim/instruments/data/sls_conf/CSST_GU2.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GU3.conf b/observation_sim/instruments/data/sls_conf/CSST_GU3.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GU3.conf rename to observation_sim/instruments/data/sls_conf/CSST_GU3.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GU4.conf b/observation_sim/instruments/data/sls_conf/CSST_GU4.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GU4.conf rename to observation_sim/instruments/data/sls_conf/CSST_GU4.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GU5.conf b/observation_sim/instruments/data/sls_conf/CSST_GU5.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GU5.conf rename to observation_sim/instruments/data/sls_conf/CSST_GU5.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GU6.conf b/observation_sim/instruments/data/sls_conf/CSST_GU6.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GU6.conf rename to observation_sim/instruments/data/sls_conf/CSST_GU6.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GU7.conf b/observation_sim/instruments/data/sls_conf/CSST_GU7.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GU7.conf rename to observation_sim/instruments/data/sls_conf/CSST_GU7.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GU8.conf b/observation_sim/instruments/data/sls_conf/CSST_GU8.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GU8.conf rename to observation_sim/instruments/data/sls_conf/CSST_GU8.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GV1.conf b/observation_sim/instruments/data/sls_conf/CSST_GV1.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GV1.conf rename to observation_sim/instruments/data/sls_conf/CSST_GV1.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GV2.conf b/observation_sim/instruments/data/sls_conf/CSST_GV2.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GV2.conf rename to observation_sim/instruments/data/sls_conf/CSST_GV2.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GV3.conf b/observation_sim/instruments/data/sls_conf/CSST_GV3.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GV3.conf rename to observation_sim/instruments/data/sls_conf/CSST_GV3.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GV4.conf b/observation_sim/instruments/data/sls_conf/CSST_GV4.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GV4.conf rename to observation_sim/instruments/data/sls_conf/CSST_GV4.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GV5.conf b/observation_sim/instruments/data/sls_conf/CSST_GV5.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GV5.conf rename to observation_sim/instruments/data/sls_conf/CSST_GV5.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GV6.conf b/observation_sim/instruments/data/sls_conf/CSST_GV6.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GV6.conf rename to observation_sim/instruments/data/sls_conf/CSST_GV6.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GV7.conf b/observation_sim/instruments/data/sls_conf/CSST_GV7.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GV7.conf rename to observation_sim/instruments/data/sls_conf/CSST_GV7.conf diff --git a/ObservationSim/Instrument/data/sls_conf/CSST_GV8.conf b/observation_sim/instruments/data/sls_conf/CSST_GV8.conf similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/CSST_GV8.conf rename to observation_sim/instruments/data/sls_conf/CSST_GV8.conf diff --git a/ObservationSim/Instrument/data/sls_conf/GI.Throughput.-1st.fits b/observation_sim/instruments/data/sls_conf/GI.Throughput.-1st.fits similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/GI.Throughput.-1st.fits rename to observation_sim/instruments/data/sls_conf/GI.Throughput.-1st.fits diff --git a/ObservationSim/Instrument/data/sls_conf/GI.Throughput.-2st.fits b/observation_sim/instruments/data/sls_conf/GI.Throughput.-2st.fits similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/GI.Throughput.-2st.fits rename to observation_sim/instruments/data/sls_conf/GI.Throughput.-2st.fits diff --git a/ObservationSim/Instrument/data/sls_conf/GI.Throughput.0st.fits b/observation_sim/instruments/data/sls_conf/GI.Throughput.0st.fits similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/GI.Throughput.0st.fits rename to observation_sim/instruments/data/sls_conf/GI.Throughput.0st.fits diff --git a/ObservationSim/Instrument/data/sls_conf/GI.Throughput.1st.fits b/observation_sim/instruments/data/sls_conf/GI.Throughput.1st.fits similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/GI.Throughput.1st.fits rename to observation_sim/instruments/data/sls_conf/GI.Throughput.1st.fits diff --git a/ObservationSim/Instrument/data/sls_conf/GI.Throughput.2st.fits b/observation_sim/instruments/data/sls_conf/GI.Throughput.2st.fits similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/GI.Throughput.2st.fits rename to observation_sim/instruments/data/sls_conf/GI.Throughput.2st.fits diff --git a/ObservationSim/Instrument/data/sls_conf/GU.Throughput.-1st.fits b/observation_sim/instruments/data/sls_conf/GU.Throughput.-1st.fits similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/GU.Throughput.-1st.fits rename to observation_sim/instruments/data/sls_conf/GU.Throughput.-1st.fits diff --git a/ObservationSim/Instrument/data/sls_conf/GU.Throughput.-2st.fits b/observation_sim/instruments/data/sls_conf/GU.Throughput.-2st.fits similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/GU.Throughput.-2st.fits rename to observation_sim/instruments/data/sls_conf/GU.Throughput.-2st.fits diff --git a/ObservationSim/Instrument/data/sls_conf/GU.Throughput.0st.fits b/observation_sim/instruments/data/sls_conf/GU.Throughput.0st.fits similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/GU.Throughput.0st.fits rename to observation_sim/instruments/data/sls_conf/GU.Throughput.0st.fits diff --git a/ObservationSim/Instrument/data/sls_conf/GU.Throughput.1st.fits b/observation_sim/instruments/data/sls_conf/GU.Throughput.1st.fits similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/GU.Throughput.1st.fits rename to observation_sim/instruments/data/sls_conf/GU.Throughput.1st.fits diff --git a/ObservationSim/Instrument/data/sls_conf/GU.Throughput.2st.fits b/observation_sim/instruments/data/sls_conf/GU.Throughput.2st.fits similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/GU.Throughput.2st.fits rename to observation_sim/instruments/data/sls_conf/GU.Throughput.2st.fits diff --git a/ObservationSim/Instrument/data/sls_conf/GV.Throughput.-1st.fits b/observation_sim/instruments/data/sls_conf/GV.Throughput.-1st.fits similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/GV.Throughput.-1st.fits rename to observation_sim/instruments/data/sls_conf/GV.Throughput.-1st.fits diff --git a/ObservationSim/Instrument/data/sls_conf/GV.Throughput.-2st.fits b/observation_sim/instruments/data/sls_conf/GV.Throughput.-2st.fits similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/GV.Throughput.-2st.fits rename to observation_sim/instruments/data/sls_conf/GV.Throughput.-2st.fits diff --git a/ObservationSim/Instrument/data/sls_conf/GV.Throughput.0st.fits b/observation_sim/instruments/data/sls_conf/GV.Throughput.0st.fits similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/GV.Throughput.0st.fits rename to observation_sim/instruments/data/sls_conf/GV.Throughput.0st.fits diff --git a/ObservationSim/Instrument/data/sls_conf/GV.Throughput.1st.fits b/observation_sim/instruments/data/sls_conf/GV.Throughput.1st.fits similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/GV.Throughput.1st.fits rename to observation_sim/instruments/data/sls_conf/GV.Throughput.1st.fits diff --git a/ObservationSim/Instrument/data/sls_conf/GV.Throughput.2st.fits b/observation_sim/instruments/data/sls_conf/GV.Throughput.2st.fits similarity index 100% rename from ObservationSim/Instrument/data/sls_conf/GV.Throughput.2st.fits rename to observation_sim/instruments/data/sls_conf/GV.Throughput.2st.fits diff --git a/ObservationSim/Instrument/data/throughputs/__init__.py b/observation_sim/instruments/data/sls_conf/__init__.py similarity index 100% rename from ObservationSim/Instrument/data/throughputs/__init__.py rename to observation_sim/instruments/data/sls_conf/__init__.py diff --git a/ObservationSim/MockObject/data/__init__.py b/observation_sim/instruments/data/throughputs/__init__.py similarity index 100% rename from ObservationSim/MockObject/data/__init__.py rename to observation_sim/instruments/data/throughputs/__init__.py diff --git a/ObservationSim/Instrument/data/throughputs/fgs_throughput.txt b/observation_sim/instruments/data/throughputs/fgs_throughput.txt similarity index 100% rename from ObservationSim/Instrument/data/throughputs/fgs_throughput.txt rename to observation_sim/instruments/data/throughputs/fgs_throughput.txt diff --git a/ObservationSim/Instrument/data/throughputs/g_throughput.txt b/observation_sim/instruments/data/throughputs/g_throughput.txt similarity index 100% rename from ObservationSim/Instrument/data/throughputs/g_throughput.txt rename to observation_sim/instruments/data/throughputs/g_throughput.txt diff --git a/ObservationSim/Instrument/data/throughputs/i_throughput.txt b/observation_sim/instruments/data/throughputs/i_throughput.txt similarity index 100% rename from ObservationSim/Instrument/data/throughputs/i_throughput.txt rename to observation_sim/instruments/data/throughputs/i_throughput.txt diff --git a/ObservationSim/Instrument/data/throughputs/nuv_throughput.txt b/observation_sim/instruments/data/throughputs/nuv_throughput.txt similarity index 100% rename from ObservationSim/Instrument/data/throughputs/nuv_throughput.txt rename to observation_sim/instruments/data/throughputs/nuv_throughput.txt diff --git a/ObservationSim/Instrument/data/throughputs/r_throughput.txt b/observation_sim/instruments/data/throughputs/r_throughput.txt similarity index 100% rename from ObservationSim/Instrument/data/throughputs/r_throughput.txt rename to observation_sim/instruments/data/throughputs/r_throughput.txt diff --git a/ObservationSim/Instrument/data/throughputs/sky_emiss_hubble_50_50_A.dat b/observation_sim/instruments/data/throughputs/sky_emiss_hubble_50_50_A.dat similarity index 100% rename from ObservationSim/Instrument/data/throughputs/sky_emiss_hubble_50_50_A.dat rename to observation_sim/instruments/data/throughputs/sky_emiss_hubble_50_50_A.dat diff --git a/ObservationSim/Instrument/data/throughputs/u_throughput.txt b/observation_sim/instruments/data/throughputs/u_throughput.txt similarity index 100% rename from ObservationSim/Instrument/data/throughputs/u_throughput.txt rename to observation_sim/instruments/data/throughputs/u_throughput.txt diff --git a/ObservationSim/Instrument/data/throughputs/y_throughput.txt b/observation_sim/instruments/data/throughputs/y_throughput.txt similarity index 100% rename from ObservationSim/Instrument/data/throughputs/y_throughput.txt rename to observation_sim/instruments/data/throughputs/y_throughput.txt diff --git a/ObservationSim/Instrument/data/throughputs/z_throughput.txt b/observation_sim/instruments/data/throughputs/z_throughput.txt similarity index 100% rename from ObservationSim/Instrument/data/throughputs/z_throughput.txt rename to observation_sim/instruments/data/throughputs/z_throughput.txt diff --git a/ObservationSim/Instrument/data/wfc-cr-attachpixel.dat b/observation_sim/instruments/data/wfc-cr-attachpixel.dat similarity index 100% rename from ObservationSim/Instrument/data/wfc-cr-attachpixel.dat rename to observation_sim/instruments/data/wfc-cr-attachpixel.dat diff --git a/ObservationSim/MockObject/CatalogBase.py b/observation_sim/mock_objects/CatalogBase.py similarity index 97% rename from ObservationSim/MockObject/CatalogBase.py rename to observation_sim/mock_objects/CatalogBase.py index a0a2d16d18e2bacb81ce5f8c835a51cd4e77bcdf..cd1b669997ed0ac00b27c991885898e283c87714 100644 --- a/ObservationSim/MockObject/CatalogBase.py +++ b/observation_sim/mock_objects/CatalogBase.py @@ -5,7 +5,7 @@ import cmath from astropy.table import Table from abc import abstractmethod, ABCMeta -from ObservationSim.MockObject._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getABMAG +from observation_sim.mock_objects._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getABMAG class CatalogBase(metaclass=ABCMeta): diff --git a/ObservationSim/MockObject/FlatLED.py b/observation_sim/mock_objects/FlatLED.py similarity index 80% rename from ObservationSim/MockObject/FlatLED.py rename to observation_sim/mock_objects/FlatLED.py index 8cb835d2f78921084ec3376e20440969198ccf1f..a99e955c95401f8aafe52841cfe9d10633cb0125 100755 --- a/ObservationSim/MockObject/FlatLED.py +++ b/observation_sim/mock_objects/FlatLED.py @@ -1,7 +1,8 @@ import galsim -import os, sys +import os +import sys import numpy as np import time import math @@ -9,12 +10,11 @@ import astropy.constants as cons from astropy.io import fits from scipy.interpolate import griddata from astropy.table import Table -from ObservationSim.MockObject.SpecDisperser import SpecDisperser +from observation_sim.mock_objects.SpecDisperser import SpecDisperser from scipy import interpolate import gc -from ObservationSim.MockObject.MockObject import MockObject -# from ObservationSim.Straylight import calculateSkyMap_split_g +from observation_sim.mock_objects.MockObject import MockObject try: import importlib.resources as pkg_resources @@ -27,13 +27,13 @@ except ImportError: LED_name = ['LED1', 'LED2', 'LED3', 'LED4', 'LED5', 'LED6', 'LED7', 'LED8', 'LED9', 'LED10', 'LED11', 'LED12', 'LED13', 'LED14'] cwaves_name = {'LED1': '275', 'LED2': '310', 'LED3': '430', 'LED4': '505', 'LED5': '545', 'LED6': '590', 'LED7': '670', - 'LED8': '760', 'LED9': '940', 'LED10': '940', 'LED11': '1050', 'LED12': '1050', - 'LED13': '340', 'LED14': '365'} + 'LED8': '760', 'LED9': '940', 'LED10': '940', 'LED11': '1050', 'LED12': '1050', + 'LED13': '340', 'LED14': '365'} cwaves = {'LED1': 2750, 'LED2': 3100, 'LED3': 4300, 'LED4': 5050, 'LED5': 5250, 'LED6': 5900, 'LED7': 6700, 'LED8': 7600, 'LED9': 8800, 'LED10': 9400, 'LED11': 10500, 'LED12': 15500, 'LED13': 3400, 'LED14': 3650} cwaves_fwhm = {'LED1': 110, 'LED2': 120, 'LED3': 200, 'LED4': 300, 'LED5': 300, 'LED6': 130, 'LED7': 210, - 'LED8': 260, 'LED9': 400, 'LED10': 370, 'LED11': 500, 'LED12': 1400, 'LED13': 90, 'LED14': 100} + 'LED8': 260, 'LED9': 400, 'LED10': 370, 'LED11': 500, 'LED12': 1400, 'LED13': 90, 'LED14': 100} # LED_QE = {'LED1': 0.3, 'LED2': 0.4, 'LED13': 0.5, 'LED14': 0.5, 'LED10': 0.4} # e-/ms # fluxLED = {'LED1': 0.16478729, 'LED2': 0.084220931, 'LED3': 2.263360617, 'LED4': 2.190623489, 'LED5': 0.703504768, @@ -43,17 +43,18 @@ cwaves_fwhm = {'LED1': 110, 'LED2': 120, 'LED3': 200, 'LED4': 300, 'LED5': 300, # e-/ms fluxLED = {'LED1': 15, 'LED2': 15, 'LED3': 12.5, 'LED4': 9, 'LED5': 9, - 'LED6': 9, 'LED7': 9, 'LED8': 9, 'LED9': 9, 'LED10': 12.5, 'LED11': 15, 'LED12':15, 'LED13': 12.5, + 'LED6': 9, 'LED7': 9, 'LED8': 9, 'LED9': 9, 'LED10': 12.5, 'LED11': 15, 'LED12': 15, 'LED13': 12.5, 'LED14': 12.5} # fluxLEDL = {'LED1': 10, 'LED2': 10, 'LED3': 10, 'LED4': 10, 'LED5': 10, # 'LED6': 10, 'LED7': 10, 'LED8': 10, 'LED9': 10, 'LED10': 10, 'LED11': 10, 'LED12':10, 'LED13': 10, # 'LED14': 10} -mirro_eff = {'GU':0.61, 'GV':0.8, 'GI':0.8} +mirro_eff = {'GU': 0.61, 'GV': 0.8, 'GI': 0.8} # mirro_eff = {'GU':1, 'GV':1, 'GI':1} + class FlatLED(MockObject): - def __init__(self, chip,filt, flatDir = None, logger=None): + def __init__(self, chip, filt, flatDir=None, logger=None): # self.led_type_list = led_type_list self.filt = filt self.chip = chip @@ -62,18 +63,19 @@ class FlatLED(MockObject): self.flatDir = flatDir else: try: - with pkg_resources.files('ObservationSim.MockObject.data.led').joinpath("") as ledDir: + with pkg_resources.files('observation_sim.mock_objects.data.led').joinpath("") as ledDir: self.flatDir = ledDir.as_posix() except AttributeError: - with pkg_resources.path('ObservationSim.MockObject.data.led', "") as ledDir: + with pkg_resources.path('observation_sim.mock_objects.data.led', "") as ledDir: self.flatDir = ledDir.as_posix() ### - ### return LED flat, e/s + # return LED flat, e/s ### def getLEDImage(self, led_type='LED1'): # cwave = cwaves[led_type] - flat = fits.open(os.path.join(self.flatDir, 'model_' + cwaves_name[led_type] + 'nm.fits')) + flat = fits.open(os.path.join(self.flatDir, 'model_' + + cwaves_name[led_type] + 'nm.fits')) xlen = flat[0].header['NAXIS1'] ylen = 601 x = np.linspace(0, self.chip.npix_x * 6, xlen) @@ -95,21 +97,23 @@ class FlatLED(MockObject): i = self.chip.rowID - 1 j = self.chip.colID - 1 U = griddata(X_, Z_, ( - M[self.chip.npix_y * i:self.chip.npix_y * (i + 1), self.chip.npix_x * j:self.chip.npix_x * (j + 1)], + M[self.chip.npix_y * i:self.chip.npix_y * + (i + 1), self.chip.npix_x * j:self.chip.npix_x * (j + 1)], N[self.chip.npix_y * i:self.chip.npix_y * (i + 1), self.chip.npix_x * j:self.chip.npix_x * (j + 1)]), - method='linear') + method='linear') U = U/np.mean(U) flatImage = U*fluxLED[led_type]*1000 gc.collect() return flatImage - ### - ### return LED flat, e/s + # return LED flat, e/s ### + def getLEDImage1(self, led_type='LED1'): # cwave = cwaves[led_type] - flat = fits.open(os.path.join(self.flatDir, 'model_' + cwaves_name[led_type] + 'nm.fits')) + flat = fits.open(os.path.join(self.flatDir, 'model_' + + cwaves_name[led_type] + 'nm.fits')) xlen = flat[0].header['NAXIS1'] ylen = 601 @@ -120,22 +124,23 @@ class FlatLED(MockObject): y = np.linspace(0, self.chip.npix_y, int(ylen/5.)) xx, yy = np.meshgrid(x, y) - a1 = flat[0].data[int(ylen*i/5.):int(ylen*i/5.)+int(ylen/5.), int(xlen*j/6.):int(xlen*j/6.)+int(xlen/6.)] + a1 = flat[0].data[int(ylen*i/5.):int(ylen*i/5.)+int(ylen/5.), + int(xlen*j/6.):int(xlen*j/6.)+int(xlen/6.)] # z = np.sin((xx+yy+xx**2+yy**2)) # fInterp = interp2d(xx, yy, z, kind='linear') X_ = np.hstack((xx.flatten()[:, None], yy.flatten()[:, None])) Z_ = a1.flatten() - n_x = np.arange(0, self.chip.npix_x , 1) + n_x = np.arange(0, self.chip.npix_x, 1) n_y = np.arange(0, self.chip.npix_y, 1) M, N = np.meshgrid(n_x, n_y) U = griddata(X_, Z_, ( M[0:self.chip.npix_y, 0:self.chip.npix_x], - N[0:self.chip.npix_y, 0:self.chip.npix_x ]), - method='linear') + N[0:self.chip.npix_y, 0:self.chip.npix_x]), + method='linear') U = U/np.mean(U) flatImage = U*fluxLED[led_type]*1000 gc.collect() @@ -143,12 +148,13 @@ class FlatLED(MockObject): def drawObj_LEDFlat_img(self, led_type_list=['LED1'], exp_t_list=[0.1]): if len(led_type_list) > len(exp_t_list): - return np.ones([self.chip.npix_y,self.chip.npix_x]) + return np.ones([self.chip.npix_y, self.chip.npix_x]) - ledFlat = np.zeros([self.chip.npix_y,self.chip.npix_x]) + ledFlat = np.zeros([self.chip.npix_y, self.chip.npix_x]) ledStat = '00000000000000' - ledTimes = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] + ledTimes = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] nledStat = '2' for i in np.arange(len(led_type_list)): @@ -160,8 +166,10 @@ class FlatLED(MockObject): led_wave = cwaves[led_type] led_fwhm = cwaves_fwhm[led_type] led_spec = self.gaussian1d_profile_led(led_wave, led_fwhm) - speci = interpolate.interp1d(led_spec['WAVELENGTH'], led_spec['FLUX']) - w_list = np.arange(self.filt.blue_limit, self.filt.red_limit, 0.5) #A + speci = interpolate.interp1d( + led_spec['WAVELENGTH'], led_spec['FLUX']) + w_list = np.arange(self.filt.blue_limit, + self.filt.red_limit, 0.5) # A f_spec = speci(w_list) ccd_bp = self.chip._getChipEffCurve(self.chip.filter_type) @@ -174,19 +182,21 @@ class FlatLED(MockObject): # print("DEBUG1:---------------",np.mean(unitFlatImg)) ledFlat = ledFlat+unitFlatImg*exp_t - ledStat = ledStat[0:int(led_type[3:])-1]+nledStat+ledStat[int(led_type[3:]):] + ledStat = ledStat[0:int(led_type[3:])-1] + \ + nledStat+ledStat[int(led_type[3:]):] ledTimes[int(led_type[3:])-1] = exp_t * 1000 gc.collect() return ledFlat, ledStat, ledTimes def drawObj_LEDFlat_slitless(self, led_type_list=['LED1'], exp_t_list=[0.1]): if len(led_type_list) != len(exp_t_list): - return np.ones([self.chip.npix_y,self.chip.npix_x]) + return np.ones([self.chip.npix_y, self.chip.npix_x]) - ledFlat = np.zeros([self.chip.npix_y,self.chip.npix_x]) + ledFlat = np.zeros([self.chip.npix_y, self.chip.npix_x]) ledStat = '00000000000000' - ledTimes = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] + ledTimes = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] nledStat = '2' @@ -213,7 +223,8 @@ class FlatLED(MockObject): flat_cube=self.chip.flat_cube, led_spec=led_spec) ledFlat = ledFlat + ledspec_map - ledStat = ledStat[0:int(led_type[3:])-1]+nledStat+ledStat[int(led_type[3:]):] + ledStat = ledStat[0:int(led_type[3:])-1] + \ + nledStat+ledStat[int(led_type[3:]):] ledTimes[int(led_type[3:])-1] = exp_t * 1000 return ledFlat, ledStat, ledTimes @@ -223,7 +234,6 @@ class FlatLED(MockObject): elif self.chip.survey_type == "spectroscopic": return self.drawObj_LEDFlat_slitless(led_type_list=led_type_list, exp_t_list=exp_t_list) - def gaussian1d_profile_led(self, xc=5050, fwhm=300): sigma = fwhm/2.355 x_radii = int(5*sigma + 1) @@ -232,9 +242,10 @@ class FlatLED(MockObject): xlist_[1:-1] = xlist xlist_[0] = 2000 xlist_[-1] = 18000 - ids1 = xlist>xc-fwhm - ids2 = xlist[ids1] xc-fwhm + ids2 = xlist[ids1] < xc+fwhm + data = np.exp((-(xlist-xc)*(xlist-xc))/(2*sigma*sigma)) / \ + (np.sqrt(2*math.pi)*sigma) scale = 1/np.trapz(data[ids1][ids2], xlist[ids1][ids2]) data_ = np.zeros(len(xlist) + 2) data_[1:-1] = data*scale @@ -242,8 +253,8 @@ class FlatLED(MockObject): return Table(np.array([xlist_.astype(np.float32), data_.astype(np.float32)]).T, names=('WAVELENGTH', 'FLUX')) def calculateLEDSpec(self, skyMap=None, blueLimit=4200, redLimit=6500, - conf=[''], pixelSize=0.074, isAlongY=0, - split_pos=3685, flat_cube=None, led_spec=None): + conf=[''], pixelSize=0.074, isAlongY=0, + split_pos=3685, flat_cube=None, led_spec=None): conf1 = conf[0] conf2 = conf[0] @@ -297,7 +308,8 @@ class FlatLED(MockObject): sub_x_s = k2 sub_x_e = sub_x_end_arr[j] - skyImg_sub = galsim.Image(skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e]) + skyImg_sub = galsim.Image( + skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e]) origin_sub = [sub_y_s, sub_x_s] sub_x_center = (sub_x_s + sub_x_e) / 2. @@ -321,11 +333,8 @@ class FlatLED(MockObject): continue fImg[bounds] = fImg[bounds] + ssImg[bounds] - - else: - # sdp.compute_spec_orders() y_len = skyMap.shape[0] x_len = skyMap.shape[1] @@ -352,7 +361,8 @@ class FlatLED(MockObject): sub_x_e = sub_x_end_arr[j] # print(i,j,sub_y_s, sub_y_e,sub_x_s,sub_x_e) T1 = time.time() - skyImg_sub = galsim.Image(skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e]) + skyImg_sub = galsim.Image( + skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e]) origin_sub = [sub_y_s, sub_x_s] sub_x_center = (sub_x_s + sub_x_e) / 2. @@ -398,7 +408,8 @@ class FlatLED(MockObject): T1 = time.time() - skyImg_sub = galsim.Image(skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e]) + skyImg_sub = galsim.Image( + skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e]) origin_sub = [sub_y_s, sub_x_s] sub_x_center = (sub_x_s + sub_x_e) / 2. @@ -426,14 +437,11 @@ class FlatLED(MockObject): print('time: %s ms' % ((T2 - T1) * 1000)) if isAlongY == 1: - fimg, tmx, tmy = SpecDisperser.rotate90(array_orig=fImg.array, xc=0, yc=0, isClockwise=0) + fimg, tmx, tmy = SpecDisperser.rotate90( + array_orig=fImg.array, xc=0, yc=0, isClockwise=0) else: fimg = fImg.array # fimg = fimg * pixelSize * pixelSize return fimg - - - - diff --git a/ObservationSim/MockObject/Galaxy.py b/observation_sim/mock_objects/Galaxy.py similarity index 96% rename from ObservationSim/MockObject/Galaxy.py rename to observation_sim/mock_objects/Galaxy.py index 27d56380d98fb0b0872012396a7e1eaa1e94a2c2..c220621e35b1c6121edc2c22b83bb9410e02715e 100755 --- a/ObservationSim/MockObject/Galaxy.py +++ b/observation_sim/mock_objects/Galaxy.py @@ -2,9 +2,9 @@ import numpy as np import galsim from astropy.table import Table -from ObservationSim.MockObject._util import eObs, integrate_sed_bandpass, getNormFactorForSpecWithABMAG -from ObservationSim.MockObject.SpecDisperser import SpecDisperser -from ObservationSim.MockObject.MockObject import MockObject +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 diff --git a/ObservationSim/MockObject/MockObject.py b/observation_sim/mock_objects/MockObject.py similarity index 81% rename from ObservationSim/MockObject/MockObject.py rename to observation_sim/mock_objects/MockObject.py index 847e5b646ef50b088a9ae6674f477747800a0bbf..12e36124de22019c6382b3381fefdb8394eecc65 100755 --- a/ObservationSim/MockObject/MockObject.py +++ b/observation_sim/mock_objects/MockObject.py @@ -6,10 +6,10 @@ from astropy import wcs from astropy.table import Table import astropy.io.fits as fitsio -from ObservationSim.MockObject._util import magToFlux, VC_A, convolveGaussXorders, convolveImg -from ObservationSim.MockObject._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, \ +from observation_sim.mock_objects._util import magToFlux, VC_A, convolveGaussXorders, convolveImg +from observation_sim.mock_objects._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, \ getABMAG -from ObservationSim.MockObject.SpecDisperser import SpecDisperser +from observation_sim.mock_objects.SpecDisperser import SpecDisperser class MockObject(object): @@ -17,21 +17,21 @@ class MockObject(object): self.param = param for key in self.param: setattr(self, key, self.param[key]) - + if self.param["star"] == 0: self.type = "galaxy" elif self.param["star"] == 1: self.type = "star" elif self.param["star"] == 2: self.type = "quasar" - ###mock_stamp_START + # mock_stamp_START elif self.param["star"] == 3: self.type = "stamp" - ###mock_stamp_END - ###for calibration + # mock_stamp_END + # for calibration elif self.param["star"] == 4: self.type = "calib" - ###END + # END self.sed = None self.fd_shear = None @@ -72,19 +72,22 @@ class MockObject(object): if verbose: print("\n") print("Before field distortion:\n") - print("x = %.2f, y = %.2f\n" % (self.posImg.x, self.posImg.y), flush=True) - self.posImg, self.fd_shear = fdmodel.get_distorted(chip=chip, pos_img=self.posImg) + print("x = %.2f, y = %.2f\n" % + (self.posImg.x, self.posImg.y), flush=True) + self.posImg, self.fd_shear = fdmodel.get_distorted( + chip=chip, pos_img=self.posImg) if verbose: print("After field distortion:\n") - print("x = %.2f, y = %.2f\n" % (self.posImg.x, self.posImg.y), flush=True) - + print("x = %.2f, y = %.2f\n" % + (self.posImg.x, self.posImg.y), flush=True) + x, y = self.posImg.x + 0.5, self.posImg.y + 0.5 self.x_nominal = int(np.floor(x + 0.5)) self.y_nominal = int(np.floor(y + 0.5)) dx = x - self.x_nominal dy = y - self.y_nominal self.offset = galsim.PositionD(dx, dy) - + # Deal with chip rotation if chip_wcs is not None: self.chip_wcs = chip_wcs @@ -108,7 +111,8 @@ class MockObject(object): # print("nphotons_tot = ", nphotons_tot) try: - 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: print(e) if self.logger: @@ -121,7 +125,7 @@ class MockObject(object): else: folding_threshold = 5.e-3 gsp = galsim.GSParams(folding_threshold=folding_threshold) - + # Get real image position of object (deal with chip rotation w.r.t its center) self.real_pos = self.getRealPos(chip.img, global_x=self.posImg.x, global_y=self.posImg.y, img_real_wcs=self.chip_wcs) @@ -153,7 +157,7 @@ class MockObject(object): # nphotons_sum += nphotons # 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) @@ -166,21 +170,22 @@ class MockObject(object): if np.sum(np.isnan(stamp.array)) > 0: continue 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) 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 has 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 1, pos_shear # Return code 1: draw sucesss + return 1, pos_shear # Return code 1: draw sucesss def addSLStoChipImage(self, sdp=None, chip=None, xOrderSigPlus=None, local_wcs=None): spec_orders = sdp.compute_spec_orders() @@ -193,7 +198,8 @@ class MockObject(object): nan_ids = np.isnan(img_s) if img_s[nan_ids].shape[0] > 0: # img_s[nan_ids] = 0 - print("DEBUG: before convolveGaussXorders specImg nan num is", img_s[nan_ids].shape[0]) + print("DEBUG: before convolveGaussXorders specImg nan num is", + img_s[nan_ids].shape[0]) ######################################################### img_s, orig_off = convolveGaussXorders(img_s, xOrderSigPlus[k]) origin_order_x = v[1] - orig_off @@ -219,7 +225,8 @@ class MockObject(object): stamp.wcs = local_wcs stamp.setOrigin(origin_order_x, origin_order_y) - 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) if bounds.area() == 0: continue chip.img.setOrigin(0, 0) @@ -230,17 +237,18 @@ class MockObject(object): del stamp del spec_orders - def addSLStoChipImageWithPSF(self, sdp=None, chip=None, pos_img_local = [1,1], psf_model=None, bandNo = 1, grating_split_pos=3685, local_wcs=None, pos_img=None): + def addSLStoChipImageWithPSF(self, sdp=None, chip=None, pos_img_local=[1, 1], psf_model=None, bandNo=1, grating_split_pos=3685, local_wcs=None, pos_img=None): spec_orders = sdp.compute_spec_orders() for k, v in spec_orders.items(): img_s = v[0] # print(bandNo,k) try: - psf, pos_shear = psf_model.get_PSF(chip, pos_img_local = pos_img_local, bandNo = bandNo, galsimGSObject=True, g_order = k, grating_split_pos=grating_split_pos) + psf, pos_shear = psf_model.get_PSF( + chip, pos_img_local=pos_img_local, bandNo=bandNo, galsimGSObject=True, g_order=k, grating_split_pos=grating_split_pos) except: psf, pos_shear = psf_model.get_PSF(chip=chip, pos_img=pos_img) - psf_img = psf.drawImage(nx=100, ny=100, wcs = local_wcs) + psf_img = psf.drawImage(nx=100, ny=100, wcs=local_wcs) psf_img_m = psf_img.array @@ -263,7 +271,6 @@ class MockObject(object): origin_order_x = v[1] - orig_off[0] origin_order_y = v[2] - orig_off[1] - specImg = galsim.ImageF(img_s) # photons = galsim.PhotonArray.makeFromImage(specImg) # photons.x += origin_order_x @@ -278,7 +285,8 @@ class MockObject(object): specImg.wcs = local_wcs specImg.setOrigin(origin_order_x, origin_order_y) - bounds = specImg.bounds & galsim.BoundsI(0, chip.npix_x - 1, 0, chip.npix_y - 1) + bounds = specImg.bounds & galsim.BoundsI( + 0, chip.npix_x - 1, 0, chip.npix_y - 1) if bounds.area() == 0: continue chip.img.setOrigin(0, 0) @@ -297,7 +305,8 @@ class MockObject(object): 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]), + 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 @@ -331,9 +340,9 @@ class MockObject(object): 'D': 5.5684364343742825, 'E': 16.260021029735388} grating_split_pos_chip = 0 + grating_split_pos - branges = np.zeros([len(bandpass_list),2]) + branges = np.zeros([len(bandpass_list), 2]) - if 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): @@ -354,22 +363,24 @@ class MockObject(object): star = star.withFlux(tel.pupil_area * exptime) psf_tmp = galsim.Gaussian(sigma=0.002) star = galsim.Convolve(psf_tmp, star) - - starImg = star.drawImage(nx=60, ny=60, wcs=chip_wcs_local, offset=offset) + + starImg = star.drawImage( + nx=60, ny=60, wcs=chip_wcs_local, offset=offset) origin_star = [y_nominal - (starImg.center.y - starImg.ymin), x_nominal - (starImg.center.x - starImg.xmin)] - starImg.setOrigin(0,0) + starImg.setOrigin(0, 0) gal_origin = [origin_star[0], origin_star[1]] - gal_end = [origin_star[0] + starImg.array.shape[0] - 1, origin_star[1] + starImg.array.shape[1] - 1] + gal_end = [origin_star[0] + starImg.array.shape[0] - + 1, origin_star[1] + starImg.array.shape[1] - 1] if gal_origin[1] < grating_split_pos_chip < gal_end[1]: subSlitPos = int(grating_split_pos_chip - gal_origin[1] + 1) - ## part img disperse + # part img disperse subImg_p1 = starImg.array[:, 0:subSlitPos] star_p1 = galsim.Image(subImg_p1) origin_p1 = origin_star - star_p1.setOrigin(0,0) + star_p1.setOrigin(0, 0) xcenter_p1 = min(x_nominal, grating_split_pos_chip - 1) - 0 ycenter_p1 = y_nominal - 0 @@ -382,11 +393,12 @@ class MockObject(object): flat_cube=flat_cube) # self.addSLStoChipImage(sdp=sdp_p1, chip=chip, xOrderSigPlus=xOrderSigPlus, local_wcs=chip_wcs_local) - 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) + 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) - subImg_p2 = starImg.array[:, subSlitPos + 1:starImg.array.shape[1]] + subImg_p2 = starImg.array[:, + subSlitPos + 1:starImg.array.shape[1]] star_p2 = galsim.Image(subImg_p2) star_p2.setOrigin(0, 0) origin_p2 = [origin_star[0], grating_split_pos_chip] @@ -402,9 +414,9 @@ class MockObject(object): flat_cube=flat_cube) # self.addSLStoChipImage(sdp=sdp_p2, chip=chip, xOrderSigPlus=xOrderSigPlus, local_wcs=chip_wcs_local) - 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) + 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 @@ -417,9 +429,9 @@ class MockObject(object): isAlongY=0, flat_cube=flat_cube) # self.addSLStoChipImage(sdp=sdp, chip=chip, xOrderSigPlus=xOrderSigPlus, local_wcs=chip_wcs_local) - 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) + 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 elif grating_split_pos_chip >= gal_end[1]: sdp = SpecDisperser(orig_img=starImg, xcenter=x_nominal - 0, @@ -430,9 +442,9 @@ class MockObject(object): isAlongY=0, flat_cube=flat_cube) # self.addSLStoChipImage(sdp=sdp, chip=chip, xOrderSigPlus=xOrderSigPlus, local_wcs=chip_wcs_local) - 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) + 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 # del psf return 1, pos_shear @@ -447,16 +459,15 @@ class MockObject(object): snr_obj = img_flux / sig_obj return snr_obj - - def drawObj_PSF(self, tel, pos_img, psf_model, bandpass_list, filt, chip, nphotons_tot=None, g1=0, g2=0, - exptime=150., fd_shear=None, chip_output=None): + exptime=150., fd_shear=None, chip_output=None): if nphotons_tot == None: nphotons_tot = self.getElectronFluxFilt(filt, tel, exptime) # print("nphotons_tot = ", nphotons_tot) try: - 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: print(e) if self.logger: @@ -504,21 +515,21 @@ class MockObject(object): folding_threshold=folding_threshold) star_temp = psf.withFlux(nphotons) - if i==0: + if i == 0: star = star_temp else: star = star+star_temp pixelScale = 0.074 stamp = star.drawImage(wcs=chip_wcs_local, offset=offset) - #stamp = star.drawImage(nx=256, ny=256, scale=pixelScale) + # stamp = star.drawImage(nx=256, ny=256, scale=pixelScale) if np.sum(np.isnan(stamp.array)) > 0: return None - fn = chip_output.subdir + "/psfIDW" os.makedirs(fn, exist_ok=True) - fn = fn + "/ccd_{:}".format(chip.chipID)+"_psf_"+str(self.param['id'])+".fits" + fn = fn + "/ccd_{:}".format(chip.chipID) + \ + "_psf_"+str(self.param['id'])+".fits" if fn != None: if os.path.exists(fn): os.remove(fn) diff --git a/ObservationSim/MockObject/Quasar.py b/observation_sim/mock_objects/Quasar.py similarity index 94% rename from ObservationSim/MockObject/Quasar.py rename to observation_sim/mock_objects/Quasar.py index 1cfd99d1402cea6c9a8798644a78ad96abc958de..b27cb8ce97a6dff472cc08ab9752dc22f05424e4 100755 --- a/ObservationSim/MockObject/Quasar.py +++ b/observation_sim/mock_objects/Quasar.py @@ -6,8 +6,8 @@ import astropy.constants as cons from astropy.table import Table from scipy import interpolate -from ObservationSim.MockObject.MockObject import MockObject -from ObservationSim.MockObject._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, getABMAG +from observation_sim.mock_objects.MockObject import MockObject +from observation_sim.mock_objects._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, getABMAG class Quasar(MockObject): diff --git a/ObservationSim/MockObject/SpecDisperser/SpecDisperser.py b/observation_sim/mock_objects/SpecDisperser/SpecDisperser.py similarity index 87% rename from ObservationSim/MockObject/SpecDisperser/SpecDisperser.py rename to observation_sim/mock_objects/SpecDisperser/SpecDisperser.py index d4126f0c457dff809a06912c5c313c3dfda7adf8..6a1e3ef05c70fa418db91149eb1e60bf9dc8b81a 100644 --- a/ObservationSim/MockObject/SpecDisperser/SpecDisperser.py +++ b/observation_sim/mock_objects/SpecDisperser/SpecDisperser.py @@ -97,7 +97,6 @@ class SpecDisperser(object): self.grating_conf_file = conf self.ignoreBeam = ignoreBeam - def compute_spec_orders(self): all_orders = OrderedDict() @@ -121,16 +120,18 @@ class SpecDisperser(object): ytrace_beam, lam_beam = self.grating_conf.get_beam_trace(x=self.xcenter, y=self.ycenter, dx=(dx + xoff), beam=beam) - ### Account for pixel centering of the trace + # Account for pixel centering of the trace yfrac_beam = ytrace_beam - floor(ytrace_beam+0.5) ysens = lam_beam * 0 lam_index = argsort(lam_beam) conf_sens = self.grating_conf.sens[beam] - lam_intep = np.linspace(self.band_start, self.band_end, int((self.band_end - self.band_start) / 0.1)) + lam_intep = np.linspace(self.band_start, self.band_end, int( + (self.band_end - self.band_start) / 0.1)) - thri = interpolate.interp1d(conf_sens['WAVELENGTH'], conf_sens['SENSITIVITY']) + thri = interpolate.interp1d( + conf_sens['WAVELENGTH'], conf_sens['SENSITIVITY']) spci = interpolate.interp1d(self.spec['WAVELENGTH'], self.spec['FLUX']) beam_thr = thri(lam_intep) @@ -138,7 +139,7 @@ class SpecDisperser(object): bean_thr_spec = beam_thr * spec_sample - ###generate sensitivity file for aXe + # generate sensitivity file for aXe # ysensitivity = lam_beam * 0 # # ysensitivity[lam_index] = interp.interp_conserve_c(lam_beam[lam_index], lam_intep, @@ -155,7 +156,8 @@ class SpecDisperser(object): sensitivity_beam = ysens len_spec_x = len(dx) - len_spec_y = int(abs(ceil(ytrace_beam[-1]) - floor(ytrace_beam[0])) + 1) + len_spec_y = int( + abs(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) modelf = zeros(product(beam_sh), dtype=float) @@ -169,7 +171,7 @@ class SpecDisperser(object): dypix = cast[int](np.floor(ytrace_beam - dyc[0] + x0[0] + 0.5)) - frac_ids = yfrac_beam<0 + frac_ids = yfrac_beam < 0 dypix[frac_ids] = dypix[frac_ids] - 1 yfrac_beam[frac_ids] = 1+yfrac_beam[frac_ids] @@ -199,7 +201,8 @@ class SpecDisperser(object): else: beam_flat = zeros([len(modelf), len(self.flat_cube)]) - sub_flat_cube = zeros([len(self.flat_cube),beam_sh[0], beam_sh[1]]) + sub_flat_cube = zeros( + [len(self.flat_cube), beam_sh[0], beam_sh[1]]) sub_flat_cube[0] = sub_flat_cube[0] + 1. overlap_flag = 1 @@ -210,23 +213,28 @@ class SpecDisperser(object): sub_x_e = originOut_x + beam_sh[1] - 1 beam_x_s = max(sub_x_s, 0) - if beam_x_s > self.flat_cube[0].shape[1] - 1: overlap_flag = 0 + if beam_x_s > self.flat_cube[0].shape[1] - 1: + overlap_flag = 0 if overlap_flag == 1: beam_x_e = min(sub_x_e, self.flat_cube[0].shape[1] - 1) - if beam_x_e < 0: overlap_flag = 0 + if beam_x_e < 0: + overlap_flag = 0 if overlap_flag == 1: beam_y_s = max(sub_y_s, 0) - if beam_y_s > self.flat_cube[0].shape[0] - 1: overlap_flag = 0 + if beam_y_s > self.flat_cube[0].shape[0] - 1: + overlap_flag = 0 if overlap_flag == 1: beam_y_e = min(sub_y_e, self.flat_cube[0].shape[0] - 1) - if beam_y_e < 0: overlap_flag = 0 + if beam_y_e < 0: + overlap_flag = 0 if overlap_flag == 1: - sub_flat_cube[:,beam_y_s-originOut_y:beam_y_e-originOut_y+1,beam_x_s-originOut_x:beam_x_e-originOut_x+1] = self.flat_cube[:,beam_y_s:beam_y_e+1,beam_x_s:beam_x_e+1] + sub_flat_cube[:, beam_y_s-originOut_y:beam_y_e-originOut_y+1, beam_x_s-originOut_x:beam_x_e - + originOut_x+1] = self.flat_cube[:, beam_y_s:beam_y_e+1, beam_x_s:beam_x_e+1] for i in arange(0, len(self.flat_cube), 1): - beam_flat[:,i] = sub_flat_cube[i].flatten() + beam_flat[:, i] = sub_flat_cube[i].flatten() # beam_flat = zeros([len(modelf), len(self.flat_cube)]) # flat_sh = self.flat_cube[0].shape # for i in arange(0, beam_sh[0], 1): @@ -243,7 +251,8 @@ class SpecDisperser(object): flat_index[nonz], yfrac_beam[nonz], sensitivity_beam[nonz], modelf, x0, - array(self.img_sh, dtype=int64), + array(self.img_sh, + dtype=int64), array(beam_sh, dtype=int64), beam_flat, lam_beam[lam_index][nonz]) @@ -254,13 +263,15 @@ class SpecDisperser(object): if self.isAlongY == 1: model, _, _ = rotate90(array_orig=model, isClockwise=0) - return model, originOut_x, originOut_y, dxpix, dypix, lam_beam,ysens + return model, originOut_x, originOut_y, dxpix, dypix, lam_beam, ysens def writerSensitivityFile(self, conffile='', beam='', w=None, sens=None): orders = {'A': '1st', 'B': '0st', 'C': '2st', 'D': '-1st', 'E': '-2st'} - sens_file_name = conffile[0:-5] + '_sensitivity_' + orders[beam] + '.fits' + sens_file_name = conffile[0:-5] + \ + '_sensitivity_' + orders[beam] + '.fits' if not os.path.exists(sens_file_name) == True: - senstivity_out = Table(array([w, sens]).T, names=('WAVELENGTH', 'SENSITIVITY')) + senstivity_out = Table( + array([w, sens]).T, names=('WAVELENGTH', 'SENSITIVITY')) senstivity_out.write(sens_file_name, format='fits') @@ -284,7 +295,7 @@ class aXeConf(): self.conf_file = conf_file self.count_beam_orders() - ## Global XOFF/YOFF offsets + # Global XOFF/YOFF offsets if 'XOFF' in self.conf.keys(): self.xoff = np.float(self.conf['XOFF']) else: @@ -310,11 +321,11 @@ class aXeConf(): conf = OrderedDict() lines = open(conf_file).readlines() for line in lines: - ## empty / commented lines + # empty / commented lines if (line.startswith('#')) | (line.strip() == '') | ('"' in line): continue - ## split the line, taking out ; and # comments + # split the line, taking out ; and # comments spl = line.split(';')[0].split('#')[0].split() param = spl[0] if len(spl) > 2: @@ -360,13 +371,14 @@ class aXeConf(): self.beams.append(beam) self.dxlam[beam] = np.arange(self.conf['BEAM{0}'.format(beam)].min(), self.conf['BEAM{0}'.format(beam)].max(), dtype=int) - self.nx[beam] = int(self.dxlam[beam].max() - self.dxlam[beam].min()) + 1 + self.nx[beam] = int(self.dxlam[beam].max() - + self.dxlam[beam].min()) + 1 self.sens[beam] = Table.read( '{0}/{1}'.format(os.path.dirname(self.conf_file), self.conf['SENSITIVITY_{0}'.format(beam)])) # self.sens[beam].wave = np.cast[np.double](self.sens[beam]['WAVELENGTH']) # self.sens[beam].sens = np.cast[np.double](self.sens[beam]['SENSITIVITY']) - ### Need doubles for interpolating functions + # Need doubles for interpolating functions for col in self.sens[beam].colnames: data = np.cast[np.double](self.sens[beam][col]) self.sens[beam].remove_column(col) @@ -394,22 +406,22 @@ class aXeConf(): Evaluated field-dependent coefficients """ - ## number of coefficients for a given polynomial order - ## 1:1, 2:3, 3:6, 4:10, order:order*(order+1)/2 + # number of coefficients for a given polynomial order + # 1:1, 2:3, 3:6, 4:10, order:order*(order+1)/2 if isinstance(coeffs, float): order = 1 else: order = int(-1 + np.sqrt(1 + 8 * len(coeffs))) // 2 - ## Build polynomial terms array - ## $a = a_0+a_1x_i+a_2y_i+a_3x_i^2+a_4x_iy_i+a_5yi^2+$ ... + # Build polynomial terms array + # $a = a_0+a_1x_i+a_2y_i+a_3x_i^2+a_4x_iy_i+a_5yi^2+$ ... xy = [] for p in range(order): for px in range(p + 1): # print 'x**%d y**%d' %(p-px, px) xy.append(xi ** (p - px) * yi ** (px)) - ## Evaluate the polynomial, allowing for N-dimensional inputs + # Evaluate the polynomial, allowing for N-dimensional inputs a = np.sum((np.array(xy).T * coeffs).T, axis=0) return a @@ -445,26 +457,27 @@ class aXeConf(): .. math:: dp = (u \sqrt{1+u^2} + \mathrm{arcsinh}\ u) / (4\cdot \mathrm{DYDX}[2]) """ - ## dp is the arc length along the trace - ## $\lambda = dldp_0 + dldp_1 dp + dldp_2 dp^2$ ... + # dp is the arc length along the trace + # $\lambda = dldp_0 + dldp_1 dp + dldp_2 dp^2$ ... poly_order = len(dydx) - 1 if (poly_order == 2): if np.abs(np.unique(dydx[2])).max() == 0: poly_order = 1 - if poly_order == 0: ## dy=0 + if poly_order == 0: # dy=0 dp = dx - elif poly_order == 1: ## constant dy/dx + elif poly_order == 1: # constant dy/dx dp = np.sqrt(1 + dydx[1] ** 2) * (dx) - elif poly_order == 2: ## quadratic trace + elif poly_order == 2: # quadratic trace u0 = dydx[1] + 2 * dydx[2] * (0) dp0 = (u0 * np.sqrt(1 + u0 ** 2) + np.arcsinh(u0)) / (4 * dydx[2]) u = dydx[1] + 2 * dydx[2] * (dx) - dp = (u * np.sqrt(1 + u ** 2) + np.arcsinh(u)) / (4 * dydx[2]) - dp0 + dp = (u * np.sqrt(1 + u ** 2) + np.arcsinh(u)) / \ + (4 * dydx[2]) - dp0 else: - ## high order shape, numerical integration along trace - ## (this can be slow) + # high order shape, numerical integration along trace + # (this can be slow) xmin = np.minimum((dx).min(), 0) xmax = np.maximum((dx).max(), 0) xfull = np.arange(xmin, xmax) @@ -472,11 +485,12 @@ class aXeConf(): for i in range(1, poly_order): dyfull += i * dydx[i] * (xfull - 0.5) ** (i - 1) - ## Integrate from 0 to dx / -dx + # Integrate from 0 to dx / -dx dpfull = xfull * 0. lt0 = xfull < 0 if lt0.sum() > 1: - dpfull[lt0] = np.cumsum(np.sqrt(1 + dyfull[lt0][::-1] ** 2))[::-1] + dpfull[lt0] = np.cumsum( + np.sqrt(1 + dyfull[lt0][::-1] ** 2))[::-1] dpfull[lt0] *= -1 # @@ -520,10 +534,12 @@ class aXeConf(): NORDER = self.orders[beam] + 1 xi, yi = x - self.xoff, y - self.yoff - xoff_beam = self.field_dependent(xi, yi, self.conf['XOFF_{0}'.format(beam)]) - yoff_beam = self.field_dependent(xi, yi, self.conf['YOFF_{0}'.format(beam)]) + xoff_beam = self.field_dependent( + xi, yi, self.conf['XOFF_{0}'.format(beam)]) + yoff_beam = self.field_dependent( + xi, yi, self.conf['YOFF_{0}'.format(beam)]) - ## y offset of trace (DYDX) + # y offset of trace (DYDX) dydx = np.zeros(NORDER) # 0 #+1.e-80 dydx = [0] * NORDER @@ -538,7 +554,7 @@ class aXeConf(): for i in range(NORDER): dy += dydx[i] * (dx - xoff_beam) ** i - ## wavelength solution + # wavelength solution dldp = np.zeros(NORDER) dldp = [0] * NORDER @@ -556,7 +572,7 @@ class aXeConf(): # ## dp is the arc length along the trace # ## $\lambda = dldp_0 + dldp_1 dp + dldp_2 dp^2$ ... # if self.conf['DYDX_ORDER_%s' %(beam)] == 0: ## dy=0 - # dp = dx-xoff_beam + # dp = dx-xoff_beam # elif self.conf['DYDX_ORDER_%s' %(beam)] == 1: ## constant dy/dx # dp = np.sqrt(1+dydx[1]**2)*(dx-xoff_beam) # elif self.conf['DYDX_ORDER_%s' %(beam)] == 2: ## quadratic trace @@ -573,7 +589,7 @@ class aXeConf(): # dyfull = 0 # for i in range(1, NORDER): # dyfull += i*dydx[i]*(xfull-0.5)**(i-1) - # + # # ## Integrate from 0 to dx / -dx # dpfull = xfull*0. # lt0 = xfull <= 0 @@ -584,10 +600,10 @@ class aXeConf(): # gt0 = xfull >= 0 # if gt0.sum() > 0: # dpfull[gt0] = np.cumsum(np.sqrt(1+dyfull[gt0]**2)) - # + # # dp = np.interp(dx-xoff_beam, xfull, dpfull) - ## Evaluate dldp + # Evaluate dldp lam = dp * 0. for i in range(NORDER): lam += dldp[i] * dp ** i @@ -619,7 +635,8 @@ class aXeConf(): if 'XOFF_{0}'.format(beam) not in self.conf.keys(): continue - xoff = self.field_dependent(x0, x1, self.conf['XOFF_{0}'.format(beam)]) + xoff = self.field_dependent( + x0, x1, self.conf['XOFF_{0}'.format(beam)]) dy, lam = self.get_beam_trace(x0, x1, dx=dx, beam=beam) xlim = self.conf['BEAM{0}'.format(beam)] ok = (dx >= xlim[0]) & (dx <= xlim[1]) @@ -627,7 +644,8 @@ class aXeConf(): alpha=0.5, edgecolor='None') plt.text(np.median(dx[ok]), np.median(dy[ok]) + 1, beam, ha='center', va='center', fontsize=14) - print('Beam {0}, lambda=({1:.1f} - {2:.1f})'.format(beam, lam[ok].min(), lam[ok].max())) + print('Beam {0}, lambda=({1:.1f} - {2:.1f})'.format(beam, + lam[ok].min(), lam[ok].max())) plt.grid() plt.xlabel(r'$\Delta x$') @@ -650,7 +668,7 @@ class aXeConf(): # Returns # ------- # conf : `~grizli.grismconf.aXeConf` -# Configuration file object. Runs `conf.get_beams()` to read the +# Configuration file object. Runs `conf.get_beams()` to read the # sensitivity curves. # """ # conf = aXeConf(conf_file) diff --git a/ObservationSim/MockObject/SpecDisperser/__init__.py b/observation_sim/mock_objects/SpecDisperser/__init__.py similarity index 100% rename from ObservationSim/MockObject/SpecDisperser/__init__.py rename to observation_sim/mock_objects/SpecDisperser/__init__.py diff --git a/ObservationSim/MockObject/SpecDisperser/disperse_c/__init__.py b/observation_sim/mock_objects/SpecDisperser/disperse_c/__init__.py similarity index 100% rename from ObservationSim/MockObject/SpecDisperser/disperse_c/__init__.py rename to observation_sim/mock_objects/SpecDisperser/disperse_c/__init__.py diff --git a/ObservationSim/MockObject/SpecDisperser/disperse_c/disperse.pyx b/observation_sim/mock_objects/SpecDisperser/disperse_c/disperse.pyx similarity index 100% rename from ObservationSim/MockObject/SpecDisperser/disperse_c/disperse.pyx rename to observation_sim/mock_objects/SpecDisperser/disperse_c/disperse.pyx diff --git a/ObservationSim/MockObject/SpecDisperser/disperse_c/interp.pyx b/observation_sim/mock_objects/SpecDisperser/disperse_c/interp.pyx similarity index 100% rename from ObservationSim/MockObject/SpecDisperser/disperse_c/interp.pyx rename to observation_sim/mock_objects/SpecDisperser/disperse_c/interp.pyx diff --git a/ObservationSim/MockObject/SpecDisperser/setup_c.py b/observation_sim/mock_objects/SpecDisperser/setup_c.py similarity index 100% rename from ObservationSim/MockObject/SpecDisperser/setup_c.py rename to observation_sim/mock_objects/SpecDisperser/setup_c.py diff --git a/ObservationSim/MockObject/Stamp.py b/observation_sim/mock_objects/Stamp.py similarity index 77% rename from ObservationSim/MockObject/Stamp.py rename to observation_sim/mock_objects/Stamp.py index 1da5cd481478d3327291e57b0f5fdfc570c00cf0..51de71c9b42cbcbc54f5a02045c4901030597aa3 100644 --- a/ObservationSim/MockObject/Stamp.py +++ b/observation_sim/mock_objects/Stamp.py @@ -1,13 +1,15 @@ -import os, sys +import os +import sys import numpy as np import galsim import astropy.constants as cons from astropy.table import Table from scipy import interpolate -from ObservationSim.MockObject.MockObject import MockObject -from ObservationSim.MockObject.SpecDisperser import SpecDisperser -from ObservationSim.MockObject._util import eObs, integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, getABMAG,convolveGaussXorders +from observation_sim.mock_objects.MockObject import MockObject +from observation_sim.mock_objects.SpecDisperser import SpecDisperser +from observation_sim.mock_objects._util import eObs, integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, getABMAG, convolveGaussXorders + class Stamp(MockObject): def __init__(self, param, logger=None): @@ -22,17 +24,17 @@ class Stamp(MockObject): if nphotons_tot == None: nphotons_tot = self.getElectronFluxFilt(filt, tel, exptime) - try: - 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: print(e) self.logger.error(e) return False - #nphotons_sum = 0 - #photons_list = [] - #xmax, ymax = 0, 0 + # nphotons_sum = 0 + # photons_list = [] + # xmax, ymax = 0, 0 if self.getMagFilter(filt) <= 15: folding_threshold = 5.e-4 @@ -72,17 +74,18 @@ class Stamp(MockObject): nphotons = ratio * nphotons_tot else: continue - #nphotons_sum += nphotons + # nphotons_sum += 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) - _gal = self.param['image'] - galImg= galsim.ImageF(_gal, scale=self.param['pixScale']) - gal_temp= galsim.InterpolatedImage(galImg) - gal_temp= gal_temp.shear(gal_shear) - gal_temp= gal_temp.withFlux(nphotons) + _gal = self.param['image'] + galImg = galsim.ImageF(_gal, scale=self.param['pixScale']) + gal_temp = galsim.InterpolatedImage(galImg) + gal_temp = gal_temp.shear(gal_shear) + gal_temp = gal_temp.withFlux(nphotons) - gal_temp= galsim.Convolve(psf, gal_temp) + gal_temp = galsim.Convolve(psf, gal_temp) if i == 0: gal = gal_temp @@ -95,7 +98,8 @@ class Stamp(MockObject): 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) + bounds = stamp.bounds & galsim.BoundsI( + 0, chip.npix_x - 1, 0, chip.npix_y - 1) if bounds.area() > 0: chip.img.setOrigin(0, 0) @@ -105,22 +109,22 @@ class Stamp(MockObject): del stamp if is_updated == 0: - print("fits obj %s missed"%(self.id)) + print("fits obj %s missed" % (self.id)) if self.logger: - self.logger.info("fits obj %s missed"%(self.id)) + self.logger.info("fits obj %s missed" % (self.id)) return 0, pos_shear 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])) + 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: @@ -140,7 +144,6 @@ class Stamp(MockObject): chip_wcs_local = self.chip_wcs.local(self.real_pos) - if self.getMagFilter(filt) <= 15: folding_threshold = 5.e-4 else: @@ -150,7 +153,8 @@ class Stamp(MockObject): flat_cube = chip.flat_cube - xOrderSigPlus = {'A':1.3909419820029296,'B':1.4760376591236062,'C':4.035447379743442,'D':5.5684364343742825,'E':16.260021029735388} + 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]) @@ -174,9 +178,9 @@ class Stamp(MockObject): # psf, pos_shear = psf_model.get_PSF(chip=chip, pos_img=pos_img, bandpass=bandpass, folding_threshold=folding_threshold) - _gal = self.param['image'] - galImg= galsim.ImageF(_gal, scale=self.param['pixScale']) - gal = galsim.InterpolatedImage(galImg) + _gal = self.param['image'] + galImg = galsim.ImageF(_gal, scale=self.param['pixScale']) + gal = galsim.InterpolatedImage(galImg) # (TEST) Random knots # knots = galsim.RandomKnots(npoints=100, profile=disk) @@ -196,40 +200,43 @@ class Stamp(MockObject): # # if fd_shear is not None: # # gal = gal.shear(fd_shear) - starImg = gal.drawImage(wcs=chip_wcs_local, offset=offset,method = 'real_space') + starImg = gal.drawImage( + wcs=chip_wcs_local, offset=offset, method='real_space') origin_star = [y_nominal - (starImg.center.y - starImg.ymin), x_nominal - (starImg.center.x - starImg.xmin)] starImg.setOrigin(0, 0) gal_origin = [origin_star[0], origin_star[1]] - gal_end = [origin_star[0] + starImg.array.shape[0] - 1, origin_star[1] + starImg.array.shape[1] - 1] + gal_end = [origin_star[0] + starImg.array.shape[0] - + 1, origin_star[1] + starImg.array.shape[1] - 1] if gal_origin[1] < grating_split_pos_chip < gal_end[1]: subSlitPos = int(grating_split_pos_chip - gal_origin[1] + 1) - ## part img disperse + # part img disperse subImg_p1 = starImg.array[:, 0:subSlitPos] star_p1 = galsim.Image(subImg_p1) star_p1.setOrigin(0, 0) origin_p1 = origin_star - xcenter_p1 = min(x_nominal,grating_split_pos_chip-1) - 0 + xcenter_p1 = min(x_nominal, grating_split_pos_chip-1) - 0 ycenter_p1 = y_nominal-0 sdp_p1 = SpecDisperser(orig_img=star_p1, 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) + 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) 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) + local_wcs=chip_wcs_local, pos_img=pos_img) - subImg_p2 = starImg.array[:, subSlitPos+1:starImg.array.shape[1]] + subImg_p2 = starImg.array[:, + subSlitPos+1:starImg.array.shape[1]] star_p2 = galsim.Image(subImg_p2) star_p2.setOrigin(0, 0) origin_p2 = [origin_star[0], grating_split_pos_chip] @@ -248,11 +255,11 @@ class Stamp(MockObject): 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) + local_wcs=chip_wcs_local, pos_img=pos_img) del sdp_p1 del sdp_p2 - elif grating_split_pos_chip<=gal_origin[1]: + elif grating_split_pos_chip <= gal_origin[1]: sdp = SpecDisperser(orig_img=starImg, xcenter=x_nominal - 0, ycenter=y_nominal - 0, origin=origin_star, tar_spec=normalSED, @@ -264,9 +271,9 @@ class Stamp(MockObject): 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) + local_wcs=chip_wcs_local, pos_img=pos_img) del sdp - elif grating_split_pos_chip>=gal_end[1]: + elif grating_split_pos_chip >= gal_end[1]: sdp = SpecDisperser(orig_img=starImg, xcenter=x_nominal - 0, ycenter=y_nominal - 0, origin=origin_star, tar_spec=normalSED, @@ -278,7 +285,7 @@ class Stamp(MockObject): 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) + local_wcs=chip_wcs_local, pos_img=pos_img) del sdp # print(self.y_nominal, starImg.center.y, starImg.ymin) diff --git a/ObservationSim/MockObject/Star.py b/observation_sim/mock_objects/Star.py similarity index 88% rename from ObservationSim/MockObject/Star.py rename to observation_sim/mock_objects/Star.py index 04fc88ea7a3e7369b4d98f74fdb5531616e6d5ec..c27b4bab7036874913088a156f07b137dd340f13 100755 --- a/ObservationSim/MockObject/Star.py +++ b/observation_sim/mock_objects/Star.py @@ -6,8 +6,8 @@ import astropy.constants as cons from astropy.table import Table from scipy import interpolate -from ObservationSim.MockObject._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, getABMAG, tag_sed -from ObservationSim.MockObject.MockObject import MockObject +from observation_sim.mock_objects._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, getABMAG, tag_sed +from observation_sim.mock_objects.MockObject import MockObject class Star(MockObject): diff --git a/ObservationSim/MockObject/__init__.py b/observation_sim/mock_objects/__init__.py similarity index 72% rename from ObservationSim/MockObject/__init__.py rename to observation_sim/mock_objects/__init__.py index 261107321d91c55eb6424d4dcdbceddfc4957ea3..0a655e14de1cc73602fcf8b3f38b57d038e92902 100755 --- a/ObservationSim/MockObject/__init__.py +++ b/observation_sim/mock_objects/__init__.py @@ -5,5 +5,3 @@ from .Quasar import Quasar from .Star import Star from .Stamp import Stamp from .FlatLED import FlatLED -# from .SkybackgroundMap import * -# from .CosmicRay import CosmicRay diff --git a/ObservationSim/MockObject/_util.py b/observation_sim/mock_objects/_util.py similarity index 62% rename from ObservationSim/MockObject/_util.py rename to observation_sim/mock_objects/_util.py index 02aee7700f411d53bf05850bfee514d3f4898f45..f5b0c06db23e4f4a1bd85e0dae3f3b413bbf79c4 100755 --- a/ObservationSim/MockObject/_util.py +++ b/observation_sim/mock_objects/_util.py @@ -7,16 +7,19 @@ import galsim VC_A = 2.99792458e+18 # speed of light: A/s VC_M = 2.99792458e+8 # speed of light: m/s -H_PLANK = 6.626196e-27 # Plank constant: erg s +H_PLANK = 6.626196e-27 # Plank constant: erg s -def comoving_dist(z, om_m=0.3111, om_L=0.6889, h=0.6766): + +def comoving_dist(z, om_m=0.3111, om_L=0.6889, h=0.6766): # Return comving distance in pc - H0 = h*100. # km / (s Mpc) + H0 = h*100. # km / (s Mpc) + def dist_int(z): return 1./np.sqrt(om_m*(1.+z)**3 + om_L) res, err = integrate.quad(dist_int, 0., z) return [res * (VC_M/1e3/H0) * 1e6, err * (VC_M/1e3/H0) * 1e6] + def magToFlux(mag): """ flux of a given AB magnitude @@ -30,6 +33,7 @@ def magToFlux(mag): flux = 10**(-0.4*(mag+48.6)) return flux + def extAv(nav, seed=1212123): """ Generate random intrinsic extinction Av @@ -39,7 +43,7 @@ def extAv(nav, seed=1212123): tau = 0.4 peak, a = 0.1, 0.5 b = a*(tau-peak) - pav = lambda av: (a*av+b)*np.exp(-av/tau) + def pav(av): return (a*av+b)*np.exp(-av/tau) avmin, avmax = 0., 3. avs = np.linspace(avmin, avmax, int((avmax-avmin)/0.001)+1) norm = np.trapz(pav(avs), avs) @@ -66,18 +70,20 @@ def seds(sedlistn, seddir="./", unit="A"): reds = {} sedlist = seddir + sedlistn sedn = open(sedlist).read().splitlines() - sedtype = range(1,len(sedn)+1) + sedtype = range(1, len(sedn)+1) for i in range(len(sedn)): xxx = sedn[i].split() isedn = seddir+xxx[0] itype = sedtype[i] ised = np.loadtxt(isedn) - if unit=="nm": ised[:,0] *= 10.0 + if unit == "nm": + ised[:, 0] *= 10.0 seds[itype] = ised reds[itype] = int(xxx[1]) return seds, reds + def sed_assign(phz, btt, rng): """ assign SED template to a galaxy. @@ -106,6 +112,8 @@ def sed_assign(phz, btt, rng): return sedtype ########################################### + + def tflux(filt, sed, redshift=0.0, av=0.0, redden=0): """ calculate the theoretical SED for given filter set and template @@ -130,44 +138,47 @@ def tflux(filt, sed, redshift=0.0, av=0.0, redden=0): SED in observed frame """ z = redshift + 1.0 - sw, sf = sed[:,0], sed[:,1] + sw, sf = sed[:, 0], sed[:, 1] # reddening sf = reddening(sw, sf, av=av, model=redden) sw, sf = sw*z, sf*(z**3) # lyman forest correction sf = lyman_forest(sw, sf, redshift) - + sedxx = (sw.copy(), sf.copy()) - + sw = VC_A/sw - sf = sf*(VC_A/sw**2) # convert flux unit to erg/s/cm^s/Hz + sf = sf*(VC_A/sw**2) # convert flux unit to erg/s/cm^s/Hz sw, sf = sw[::-1], sf[::-1] sfun = interp1d(sw, sf, kind='linear') - fwave, fresp = filt[:,0], filt[:,1] + fwave, fresp = filt[:, 0], filt[:, 1] fwave = VC_A/fwave fwave, fresp = fwave[::-1], fresp[::-1] tflux = sfun(fwave) zpflux = 3.631*1.0e-20 - tflux = np.trapz(tflux*fresp/fwave,fwave)/np.trapz(zpflux*fresp/fwave,fwave) - #tflux = np.trapz(tflux*fresp,fwave)/np.trapz(zpflux*fresp,fwave) + tflux = np.trapz(tflux*fresp/fwave, fwave) / \ + np.trapz(zpflux*fresp/fwave, fwave) + # tflux = np.trapz(tflux*fresp,fwave)/np.trapz(zpflux*fresp,fwave) return tflux, sedxx ########################################### + + def lyman_forest(wavelen, flux, z): """ Compute the Lyman forest mean absorption of an input spectrum, according to D_A and D_B evolution from Madau (1995). The waveeln and flux are in observed frame """ - if z<=0: + if z <= 0: flux0 = flux else: nw = 200 - istep = np.linspace(0,nw-1,nw) + istep = np.linspace(0, nw-1, nw) w1a, w2a = 1050.0*(1.0+z), 1170.0*(1.0+z) w1b, w2b = 920.0*(1.0+z), 1015.0*(1.0+z) wstepa = (w2a-w1a)/float(nw) @@ -177,20 +188,25 @@ def lyman_forest(wavelen, flux, z): ptaua = np.exp(-3.6e-03*(wtempa/1216.0)**3.46) wtempb = w1b + istep*wstepb - ptaub = np.exp(-1.7e-3*(wtempb/1026.0)**3.46\ - -1.2e-3*(wtempb/972.50)**3.46\ - -9.3e-4*(wtempb/950.00)**3.46) + ptaub = np.exp(-1.7e-3*(wtempb/1026.0)**3.46 + - 1.2e-3*(wtempb/972.50)**3.46 + - 9.3e-4*(wtempb/950.00)**3.46) da = (1.0/(120.0*(1.0+z)))*np.trapz(ptaua, wtempa) db = (1.0/(95.0*(1.0+z)))*np.trapz(ptaub, wtempb) - if da>1.0: da=1.0 - if db>1.0: db=1.0 - if da<0.0: da=0.0 - if db<0.0: db=0.0 + if da > 1.0: + da = 1.0 + if db > 1.0: + db = 1.0 + if da < 0.0: + da = 0.0 + if db < 0.0: + db = 0.0 flux0 = flux.copy() - id0 = wavelen<=1026.0*(1.0+z) - id1 = np.logical_and(wavelen<1216.0*(1.0+z),wavelen>=1026.0*(1.0+z)) + id0 = wavelen <= 1026.0*(1.0+z) + id1 = np.logical_and(wavelen < 1216.0*(1.0+z), + wavelen >= 1026.0*(1.0+z)) flux0[id0] = db*flux[id0] flux0[id1] = da*flux[id1] @@ -220,128 +236,131 @@ def reddening(sw, sf, av=0.0, model=0): Return: reddening-corrected flux or observed flux """ - if model==0 or av==0.0: - flux=sf - elif model==1: # Allen (1976) for the Milky Way - lambda0 = np.array([1000, 1110, 1250, 1430, 1670, \ - 2000, 2220, 2500, 2850, 3330, \ - 3650, 4000, 4400, 5000, 5530, \ + if model == 0 or av == 0.0: + flux = sf + elif model == 1: # Allen (1976) for the Milky Way + lambda0 = np.array([1000, 1110, 1250, 1430, 1670, + 2000, 2220, 2500, 2850, 3330, + 3650, 4000, 4400, 5000, 5530, 6700, 9000, 10000, 20000, 100000], dtype=float) - kR = np.array([4.20, 3.70, 3.30, 3.00, 2.70, \ - 2.80, 2.90, 2.30, 1.97, 1.69, \ - 1.58, 1.45, 1.32, 1.13, 1.00, \ - 0.74, 0.46, 0.38, 0.11, 0.00],dtype=float) + kR = np.array([4.20, 3.70, 3.30, 3.00, 2.70, + 2.80, 2.90, 2.30, 1.97, 1.69, + 1.58, 1.45, 1.32, 1.13, 1.00, + 0.74, 0.46, 0.38, 0.11, 0.00], dtype=float) ext0 = InterpolatedUnivariateSpline(lambda0, kR, k=1) A_lambda = av*ext0(sw) - A_lambda[A_lambda<0.0] = 0.0 + A_lambda[A_lambda < 0.0] = 0.0 flux = sf*10**(-0.4*A_lambda) - elif model==2: # Seaton (1979) fit by Fitzpatrick (1986) for the Milky Way - Rv=3.1 + elif model == 2: # Seaton (1979) fit by Fitzpatrick (1986) for the Milky Way + Rv = 3.1 al0, ga, c1, c2, c3, c4 = 4.595, 1.051, -0.38, 0.74, 3.96, 0.26 - ff11 = __red(1100.0,al0,ga,c1,c2,c3,c4) - ff12 = __red(1200.0,al0,ga,c1,c2,c3,c4) - slope=(ff12-ff11)/100.0 - lambda0 = np.array([3650, 4000, 4400, 5000, 5530, \ + ff11 = __red(1100.0, al0, ga, c1, c2, c3, c4) + ff12 = __red(1200.0, al0, ga, c1, c2, c3, c4) + slope = (ff12-ff11)/100.0 + lambda0 = np.array([3650, 4000, 4400, 5000, 5530, 6700, 9000, 10000, 20000, 100000], dtype=float) - kR = np.array([1.58, 1.45, 1.32, 1.13, 1.00, \ - 0.74, 0.46, 0.38, 0.11, 0.00],dtype=float) + kR = np.array([1.58, 1.45, 1.32, 1.13, 1.00, + 0.74, 0.46, 0.38, 0.11, 0.00], dtype=float) fun = interp1d(lambda0, kR, kind='linear') - sw0 = sw[sw<1200.0] + sw0 = sw[sw < 1200.0] A_lambda0 = (ff11+(sw0-1100.0)*slope)/Rv+1.0 - sw1 = sw[np.logical_and(sw>=1200.0, sw<=3650.0)] - ff = __red(sw1,al0,ga,c1,c2,c3,c4) + sw1 = sw[np.logical_and(sw >= 1200.0, sw <= 3650.0)] + ff = __red(sw1, al0, ga, c1, c2, c3, c4) A_lambda1 = ff/Rv+1.0 - sw2 = sw[np.logical_and(sw>3650.0, sw<=100000.0)] + sw2 = sw[np.logical_and(sw > 3650.0, sw <= 100000.0)] A_lambda2 = fun(sw2) - A_lambda3 = sw[sw>100000.0]*0.0 - A_lambda = av*np.hstack([A_lambda0,A_lambda1,A_lambda2,A_lambda3]) - A_lambda[A_lambda<0.0] = 0.0 + A_lambda3 = sw[sw > 100000.0]*0.0 + A_lambda = av*np.hstack([A_lambda0, A_lambda1, A_lambda2, A_lambda3]) + A_lambda[A_lambda < 0.0] = 0.0 flux = sf*10**(-0.4*A_lambda) - elif model==3: # Fitzpatrick (1986) for the Large Magellanic Cloud (LMC) - Rv=3.1 + elif model == 3: # Fitzpatrick (1986) for the Large Magellanic Cloud (LMC) + Rv = 3.1 al0, ga, c1, c2, c3, c4 = 4.608, 0.994, -0.69, 0.89, 2.55, 0.50 - ff11 = __red(1100.0,al0,ga,c1,c2,c3,c4) - ff12 = __red(1200.0,al0,ga,c1,c2,c3,c4) - slope=(ff12-ff11)/100.0 - lambda0 = np.array([3330, 3650, 4000, 4400, 5000, 5530, \ + ff11 = __red(1100.0, al0, ga, c1, c2, c3, c4) + ff12 = __red(1200.0, al0, ga, c1, c2, c3, c4) + slope = (ff12-ff11)/100.0 + lambda0 = np.array([3330, 3650, 4000, 4400, 5000, 5530, 6700, 9000, 10000, 20000, 100000], dtype=float) - kR = np.array([1.682, 1.58, 1.45, 1.32, 1.13, 1.00, \ - 0.74, 0.46, 0.38, 0.11, 0.00],dtype=float) + kR = np.array([1.682, 1.58, 1.45, 1.32, 1.13, 1.00, + 0.74, 0.46, 0.38, 0.11, 0.00], dtype=float) fun = interp1d(lambda0, kR, kind='linear') - sw0 = sw[sw<1200.0] + sw0 = sw[sw < 1200.0] A_lambda0 = (ff11+(sw0-1100.0)*slope)/Rv+1.0 - sw1 = sw[np.logical_and(sw>=1200.0, sw<=3330.0)] - ff = __red(sw1,al0,ga,c1,c2,c3,c4) + sw1 = sw[np.logical_and(sw >= 1200.0, sw <= 3330.0)] + ff = __red(sw1, al0, ga, c1, c2, c3, c4) A_lambda1 = ff/Rv+1.0 - sw2 = sw[np.logical_and(sw>3330.0, sw<=100000.0)] + sw2 = sw[np.logical_and(sw > 3330.0, sw <= 100000.0)] A_lambda2 = fun(sw2) - A_lambda3 = sw[sw>100000.0]*0.0 - A_lambda = av*np.hstack([A_lambda0,A_lambda1,A_lambda2,A_lambda3]) - A_lambda[A_lambda<0.0] = 0.0 + A_lambda3 = sw[sw > 100000.0]*0.0 + A_lambda = av*np.hstack([A_lambda0, A_lambda1, A_lambda2, A_lambda3]) + A_lambda[A_lambda < 0.0] = 0.0 flux = sf*10**(-0.4*A_lambda) - elif model==4: # Prevot et al (1984) and Bouchet (1985) for the Small Magellanic Cloud (SMC) + # Prevot et al (1984) and Bouchet (1985) for the Small Magellanic Cloud (SMC) + elif model == 4: Rv = 2.72 - lambda0 = np.array([1275, 1330, 1385, 1435, 1490, 1545, \ - 1595, 1647, 1700, 1755, 1810, 1860, \ - 1910, 2000, 2115, 2220, 2335, 2445, \ - 2550, 2665, 2778, 2890, 2995, 3105, \ + lambda0 = np.array([1275, 1330, 1385, 1435, 1490, 1545, + 1595, 1647, 1700, 1755, 1810, 1860, + 1910, 2000, 2115, 2220, 2335, 2445, + 2550, 2665, 2778, 2890, 2995, 3105, 3704, 4255, 5291, 12500, 16500, 22000], dtype=float) - kR = np.array([13.54, 12.52, 11.51, 10.80, 9.84, 9.28, \ - 9.06, 8.49, 8.01, 7.71, 7.17, 6.90, 6.76, \ - 6.38, 5.85, 5.30, 4.53, 4.24, 3.91, 3.49, \ - 3.15, 3.00, 2.65, 2.29, 1.81, 1.00, 0.00, \ - -2.02, -2.36, -2.47],dtype=float) + kR = np.array([13.54, 12.52, 11.51, 10.80, 9.84, 9.28, + 9.06, 8.49, 8.01, 7.71, 7.17, 6.90, 6.76, + 6.38, 5.85, 5.30, 4.53, 4.24, 3.91, 3.49, + 3.15, 3.00, 2.65, 2.29, 1.81, 1.00, 0.00, + -2.02, -2.36, -2.47], dtype=float) kR = kR/Rv+1.0 ext0 = InterpolatedUnivariateSpline(lambda0, kR, k=1) A_lambda = av*ext0(sw) - A_lambda[A_lambda<0.0] = 0.0 + A_lambda[A_lambda < 0.0] = 0.0 flux = sf*10**(-0.4*A_lambda) - elif model==5: # Calzetti et al (2000) for starburst galaxies + elif model == 5: # Calzetti et al (2000) for starburst galaxies Rv = 4.05 - sw = sw*1.0e-04 #wavelength in microns + sw = sw*1.0e-04 # wavelength in microns - fun1 = lambda x: 2.659*(-2.156+1.509/x-0.198/x**2+0.011/x**3)+Rv - fun2 = lambda x: 2.659*(-1.857+1.040/x)+Rv + def fun1(x): return 2.659*(-2.156+1.509/x-0.198/x**2+0.011/x**3)+Rv + def fun2(x): return 2.659*(-1.857+1.040/x)+Rv ff11, ff12 = fun1(0.11), fun1(0.12) - slope1=(ff12-ff11)/0.01 + slope1 = (ff12-ff11)/0.01 ff99, ff100 = fun2(2.19), fun2(2.2) - slope2=(ff100-ff99)/0.01 + slope2 = (ff100-ff99)/0.01 - sw0 = sw[sw<0.12] - sw1 = sw[np.logical_and(sw>=0.12, sw<=0.63)] - sw2 = sw[np.logical_and(sw>0.63, sw<=2.2)] - sw3 = sw[sw>2.2] + sw0 = sw[sw < 0.12] + sw1 = sw[np.logical_and(sw >= 0.12, sw <= 0.63)] + sw2 = sw[np.logical_and(sw > 0.63, sw <= 2.2)] + sw3 = sw[sw > 2.2] k_lambda0 = ff11+(sw0-0.11)*slope1 k_lambda1, k_lambda2 = fun1(sw1), fun2(sw2) k_lambda3 = ff99+(sw3-2.19)*slope2 - A_lambda = av*np.hstack([k_lambda0,k_lambda1,k_lambda2,k_lambda3])/Rv - A_lambda[A_lambda<0.0] = 0.0 + A_lambda = av*np.hstack([k_lambda0, k_lambda1, + k_lambda2, k_lambda3])/Rv + A_lambda[A_lambda < 0.0] = 0.0 flux = sf*10**(-0.4*A_lambda) - elif model==6: # Reddy et al (2015) for satr forming galaxies + elif model == 6: # Reddy et al (2015) for satr forming galaxies Rv = 2.505 sw = sw*1.0e-04 - fun1 = lambda x: -5.726+4.004/x-0.525/x**2+0.029/x**3+Rv - fun2 = lambda x: -2.672-0.010/x+1.532/x**2-0.412/x**3+Rv + def fun1(x): return -5.726+4.004/x-0.525/x**2+0.029/x**3+Rv + def fun2(x): return -2.672-0.010/x+1.532/x**2-0.412/x**3+Rv ff11, ff12 = fun1(0.14), fun1(0.15) - slope1=(ff12-ff11)/0.01 + slope1 = (ff12-ff11)/0.01 ff99, ff100 = fun2(2.84), fun2(2.85) - slope2=(ff100-ff99)/0.01 + slope2 = (ff100-ff99)/0.01 - sw0 = sw[sw<0.15] - sw1 = sw[np.logical_and(sw>=0.15, sw<0.60)] - sw2 = sw[np.logical_and(sw>=0.60, sw<2.85)] - sw3 = sw[sw>=2.85] + sw0 = sw[sw < 0.15] + sw1 = sw[np.logical_and(sw >= 0.15, sw < 0.60)] + sw2 = sw[np.logical_and(sw >= 0.60, sw < 2.85)] + sw3 = sw[sw >= 2.85] k_lambda0 = ff11+(sw0-0.14)*slope1 k_lambda1, k_lambda2 = fun1(sw1), fun2(sw2) k_lambda3 = ff99+(sw3-2.84)*slope2 - A_lambda = av*np.hstack([k_lambda0,k_lambda1,k_lambda2,k_lambda3])/Rv - A_lambda[A_lambda<0.0] = 0.0 - flux = sf*10**(-0.4*A_lambda) + A_lambda = av*np.hstack([k_lambda0, k_lambda1, + k_lambda2, k_lambda3])/Rv + A_lambda[A_lambda < 0.0] = 0.0 + flux = sf*10**(-0.4*A_lambda) else: raise ValueError("!!! Please select a proper reddening model") @@ -349,25 +368,30 @@ def reddening(sw, sf, av=0.0, model=0): return flux ########################################### -def __red(alan,al0,ga,c1,c2,c3,c4): - fun1 = lambda x: c3/(((x-(al0**2/x))**2)+ga*ga) - fun2 = lambda x,cc: cc*(0.539*((x-5.9)**2)+0.0564*((x-5.9)**3)) - fun = lambda x,cc: c1+c2*x+fun1(x)+fun2(x,cc) - ala = alan*1.0e-04 #wavelength in microns +def __red(alan, al0, ga, c1, c2, c3, c4): + + def fun1(x): return c3/(((x-(al0**2/x))**2)+ga*ga) + def fun2(x, cc): return cc*(0.539*((x-5.9)**2)+0.0564*((x-5.9)**3)) + def fun(x, cc): return c1+c2*x+fun1(x)+fun2(x, cc) + + ala = alan*1.0e-04 # wavelength in microns p = 1.0/ala - if np.size(p)>1: - p1, p2 = p[p>=5.9], p[p<5.9] - ff = np.append(fun(p1,c4), fun(p2,0.0)) - elif np.size(p)==1: - if p<5.9: c4 = 0.0 + if np.size(p) > 1: + p1, p2 = p[p >= 5.9], p[p < 5.9] + ff = np.append(fun(p1, c4), fun(p2, 0.0)) + elif np.size(p) == 1: + if p < 5.9: + c4 = 0.0 ff = fun(p, c4) else: return return ff ########################################### + + def sed2mag(mag_i, sedCat, filter_list, redshift=0.0, av=0.0, redden=0): # load the filters @@ -378,19 +402,23 @@ def sed2mag(mag_i, sedCat, filter_list, redshift=0.0, av=0.0, redden=0): if filter_list[k].filter_type == 'i': nid = k bandpass = filter_list[k].bandpass_full - ktrans = np.transpose(np.array([bandpass.wave_list*10.0, bandpass.func(bandpass.wave_list)])) - aflux[k], isedObs = tflux(ktrans, sedCat, redshift=redshift, av=av, redden=redden) + ktrans = np.transpose( + np.array([bandpass.wave_list*10.0, bandpass.func(bandpass.wave_list)])) + aflux[k], isedObs = tflux( + ktrans, sedCat, redshift=redshift, av=av, redden=redden) # normalize to i-band aflux = aflux / aflux[nid] # magnitudes in all filters amag = -2.5*np.log10(aflux) + mag_i - spec = galsim.LookupTable(x=np.array(isedObs[0]), f=np.array(isedObs[1]), interpolant='nearest') + spec = galsim.LookupTable(x=np.array(isedObs[0]), f=np.array( + isedObs[1]), interpolant='nearest') isedObs = galsim.SED(spec, wave_type='A', flux_type='1', fast=False) return amag, isedObs -def eObs(e1,e2,g1,g2): + +def eObs(e1, e2, g1, g2): """ Calculate the sheared (observed) ellipticity using the intrinsic ellipticity and cosmic shear components. @@ -424,7 +452,7 @@ def eObs(e1,e2,g1,g2): e = complex(e1[i], e2[i]) g = complex(g1[i], g2[i]) e, gg = abs(e), abs(g) - if gg<=1.0: + if gg <= 1.0: tt = e + g bb = 1.0 + e*g.conjugate() eobs = tt/bb @@ -432,27 +460,34 @@ def eObs(e1,e2,g1,g2): tt = 1.0 + g*e.conjugate() bb = e.conjugate() + g.conjugate() eobs = tt/bb - + # derive the orientation dd = 0.5*np.arctan(abs(eobs.imag/eobs.real))*180.0/np.pi - if eobs.imag>0 and eobs.real>0: dd = dd - if eobs.imag>0 and eobs.real<0: dd = 90.0 - dd - if eobs.imag<0 and eobs.real>0: dd = 0.0 - dd - if eobs.imag<0 and eobs.real<0: dd = dd - 90.0 + if eobs.imag > 0 and eobs.real > 0: + dd = dd + if eobs.imag > 0 and eobs.real < 0: + dd = 90.0 - dd + if eobs.imag < 0 and eobs.real > 0: + dd = 0.0 - dd + if eobs.imag < 0 and eobs.real < 0: + dd = dd - 90.0 e1obs += [eobs.real] e2obs += [eobs.imag] eeobs += [abs(eobs)] theta += [dd] - e1obs,e2obs,eeobs,theta = np.array(e1obs),np.array(e2obs),np.array(eeobs),np.array(theta) - if nobj == 1: e1obs,e2obs,eeobs,theta = e1obs[0],e2obs[0],eeobs[0],theta[0] - + e1obs, e2obs, eeobs, theta = np.array(e1obs), np.array( + e2obs), np.array(eeobs), np.array(theta) + if nobj == 1: + e1obs, e2obs, eeobs, theta = e1obs[0], e2obs[0], eeobs[0], theta[0] + return e1obs, e2obs, eeobs, theta + def getObservedSED(sedCat, redshift=0.0, av=0.0, redden=0): z = redshift + 1.0 - sw, sf = sedCat[:,0], sedCat[:,1] + sw, sf = sedCat[:, 0], sedCat[:, 1] # reddening sf = reddening(sw, sf, av=av, model=redden) # sw, sf = sw*z, sf*(z**3) @@ -464,28 +499,33 @@ def getObservedSED(sedCat, redshift=0.0, av=0.0, redden=0): isedObs = (sw.copy(), sf.copy()) return isedObs + def integrate_sed_bandpass(sed, bandpass): - wave = np.linspace(bandpass.blue_limit, bandpass.red_limit, 1000) # in nm + wave = np.linspace(bandpass.blue_limit, bandpass.red_limit, 1000) # in nm flux_normalized = sed(wave)*bandpass(wave) # print('in integrate_sed_bandpass', bandpass.blue_limit, bandpass.red_limit) - int_flux = np.trapz(y=flux_normalized, x=wave) * 10. # convert to photons s-1 m-2 A-1 + int_flux = np.trapz(y=flux_normalized, x=wave) * \ + 10. # convert to photons s-1 m-2 A-1 return int_flux + def getABMAG(interFlux, bandpass): - throughtput = Table(np.array(np.array([bandpass.wave_list*10.0, bandpass.func(bandpass.wave_list)])).T, names=(['WAVELENGTH', 'SENSITIVITY'])) + throughtput = Table(np.array(np.array([bandpass.wave_list*10.0, bandpass.func( + bandpass.wave_list)])).T, names=(['WAVELENGTH', 'SENSITIVITY'])) sWave = bandpass.blue_limit*10.0 eWave = bandpass.red_limit*10.0 # print('in getABMAG', sWave, eWave) ABMAG_zero = getABMagAverageVal( - ABmag=0, - norm_thr=throughtput, - sWave=sWave, + ABmag=0, + norm_thr=throughtput, + sWave=sWave, eWave=eWave) flux_ave = interFlux / (eWave-sWave) ABMAG_spec = -2.5 * np.log10(flux_ave/ABMAG_zero) return ABMAG_spec -def getABMagAverageVal(ABmag=20.,norm_thr=None, sWave=6840, eWave=8250): + +def getABMagAverageVal(ABmag=20., norm_thr=None, sWave=6840, eWave=8250): """ norm_thr: astropy.table, 2 colum, 'WAVELENGTH', 'SENSITIVITY' @@ -496,15 +536,16 @@ def getABMagAverageVal(ABmag=20.,norm_thr=None, sWave=6840, eWave=8250): inverseLambda = norm_thr['SENSITIVITY']/norm_thr['WAVELENGTH'] norm_thr_i = interpolate.interp1d(norm_thr['WAVELENGTH'], inverseLambda) - x = np.linspace(sWave,eWave, int(eWave)-int(sWave)+1) + x = np.linspace(sWave, eWave, int(eWave)-int(sWave)+1) y = norm_thr_i(x) - AverageLamdaInverse = np.trapz(y,x)/(eWave-sWave) + AverageLamdaInverse = np.trapz(y, x)/(eWave-sWave) norm = 54798696332.52474 * pow(10.0, -0.4 * ABmag) * AverageLamdaInverse # print('AverageLamdaInverse = ', AverageLamdaInverse) # print('norm = ', norm) return norm + def getNormFactorForSpecWithABMAG(ABMag=20., spectrum=None, norm_thr=None, sWave=6840, eWave=8250): """ Use AB magnitude system (zero point, fv = 3631 janskys) in the normal band(norm_thr) normalize the spectrum by inpute ABMag @@ -520,17 +561,19 @@ def getNormFactorForSpecWithABMAG(ABMag=20., spectrum=None, norm_thr=None, sWave the normalization factor flux of AB system(fix a band and magnitude ) /the flux of inpute spectrum(fix a band) """ spectrumi = interpolate.interp1d(spectrum['WAVELENGTH'], spectrum['FLUX']) - norm_thri = interpolate.interp1d(norm_thr['WAVELENGTH'], norm_thr['SENSITIVITY']) + norm_thri = interpolate.interp1d( + norm_thr['WAVELENGTH'], norm_thr['SENSITIVITY']) - x = np.linspace(sWave,eWave, int(eWave)-int(sWave)+1) + x = np.linspace(sWave, eWave, int(eWave)-int(sWave)+1) y_spec = spectrumi(x) y_thr = norm_thri(x) y = y_spec*y_thr - specAve = np.trapz(y,x)/(eWave-sWave) - norm = getABMagAverageVal(ABmag=ABMag, norm_thr=norm_thr, sWave=sWave, eWave=eWave) + specAve = np.trapz(y, x)/(eWave-sWave) + norm = getABMagAverageVal( + ABmag=ABMag, norm_thr=norm_thr, sWave=sWave, eWave=eWave) if specAve == 0: return 0 @@ -551,12 +594,14 @@ def tag_sed(h5file, model_tag, teff=5000, logg=2, feh=0): close_feh = 99 else: close_feh = feh_grid[np.argmin(np.abs(feh_grid - feh))] - path = model_tag_str + f"_teff_{close_teff:.1f}_logg_{close_logg:.2f}_feh_{close_feh:.1f}" + path = model_tag_str + \ + f"_teff_{close_teff:.1f}_logg_{close_logg:.2f}_feh_{close_feh:.1f}" wave = np.array(h5file["wave"][model_tag_str][()]).ravel() flux = np.array(h5file["sed"][path][()]).ravel() return path, wave, flux -def convolveGaussXorders(img=None, sigma = 1): + +def convolveGaussXorders(img=None, sigma=1): from astropy.modeling.models import Gaussian2D from scipy import signal offset = int(np.ceil(sigma*10)) @@ -571,14 +616,13 @@ def convolveGaussXorders(img=None, sigma = 1): convImg = signal.fftconvolve(img, psf, mode='full', axes=None) return convImg, offset -def convolveImg(img=None, psf = None): + +def convolveImg(img=None, psf=None): from astropy.modeling.models import Gaussian2D from scipy import signal convImg = signal.fftconvolve(img, psf, mode='full', axes=None) offset_x = int(psf.shape[1]/2. + 0.5) - 1 offset_y = int(psf.shape[0]/2. + 0.5) - 1 - offset = [offset_x,offset_y] + offset = [offset_x, offset_y] return convImg, offset - - diff --git a/ObservationSim/MockObject/data/led/__init__.py b/observation_sim/mock_objects/data/__init__.py similarity index 100% rename from ObservationSim/MockObject/data/led/__init__.py rename to observation_sim/mock_objects/data/__init__.py diff --git a/ObservationSim/Straylight/data/__init__.py b/observation_sim/mock_objects/data/led/__init__.py old mode 100755 new mode 100644 similarity index 100% rename from ObservationSim/Straylight/data/__init__.py rename to observation_sim/mock_objects/data/led/__init__.py diff --git a/ObservationSim/MockObject/data/led/model_1050nm.fits b/observation_sim/mock_objects/data/led/model_1050nm.fits similarity index 100% rename from ObservationSim/MockObject/data/led/model_1050nm.fits rename to observation_sim/mock_objects/data/led/model_1050nm.fits diff --git a/ObservationSim/MockObject/data/led/model_275nm.fits b/observation_sim/mock_objects/data/led/model_275nm.fits similarity index 100% rename from ObservationSim/MockObject/data/led/model_275nm.fits rename to observation_sim/mock_objects/data/led/model_275nm.fits diff --git a/ObservationSim/MockObject/data/led/model_310nm.fits b/observation_sim/mock_objects/data/led/model_310nm.fits similarity index 100% rename from ObservationSim/MockObject/data/led/model_310nm.fits rename to observation_sim/mock_objects/data/led/model_310nm.fits diff --git a/ObservationSim/MockObject/data/led/model_340nm.fits b/observation_sim/mock_objects/data/led/model_340nm.fits similarity index 100% rename from ObservationSim/MockObject/data/led/model_340nm.fits rename to observation_sim/mock_objects/data/led/model_340nm.fits diff --git a/ObservationSim/MockObject/data/led/model_365nm.fits b/observation_sim/mock_objects/data/led/model_365nm.fits similarity index 100% rename from ObservationSim/MockObject/data/led/model_365nm.fits rename to observation_sim/mock_objects/data/led/model_365nm.fits diff --git a/ObservationSim/MockObject/data/led/model_430nm.fits b/observation_sim/mock_objects/data/led/model_430nm.fits similarity index 100% rename from ObservationSim/MockObject/data/led/model_430nm.fits rename to observation_sim/mock_objects/data/led/model_430nm.fits diff --git a/ObservationSim/MockObject/data/led/model_505nm.fits b/observation_sim/mock_objects/data/led/model_505nm.fits similarity index 100% rename from ObservationSim/MockObject/data/led/model_505nm.fits rename to observation_sim/mock_objects/data/led/model_505nm.fits diff --git a/ObservationSim/MockObject/data/led/model_545nm.fits b/observation_sim/mock_objects/data/led/model_545nm.fits similarity index 100% rename from ObservationSim/MockObject/data/led/model_545nm.fits rename to observation_sim/mock_objects/data/led/model_545nm.fits diff --git a/ObservationSim/MockObject/data/led/model_590nm.fits b/observation_sim/mock_objects/data/led/model_590nm.fits similarity index 100% rename from ObservationSim/MockObject/data/led/model_590nm.fits rename to observation_sim/mock_objects/data/led/model_590nm.fits diff --git a/ObservationSim/MockObject/data/led/model_670nm.fits b/observation_sim/mock_objects/data/led/model_670nm.fits similarity index 100% rename from ObservationSim/MockObject/data/led/model_670nm.fits rename to observation_sim/mock_objects/data/led/model_670nm.fits diff --git a/ObservationSim/MockObject/data/led/model_760nm.fits b/observation_sim/mock_objects/data/led/model_760nm.fits similarity index 100% rename from ObservationSim/MockObject/data/led/model_760nm.fits rename to observation_sim/mock_objects/data/led/model_760nm.fits diff --git a/ObservationSim/MockObject/data/led/model_940nm.fits b/observation_sim/mock_objects/data/led/model_940nm.fits similarity index 100% rename from ObservationSim/MockObject/data/led/model_940nm.fits rename to observation_sim/mock_objects/data/led/model_940nm.fits diff --git a/ObservationSim/PSF/FieldDistortion.py b/observation_sim/psf/FieldDistortion.py similarity index 82% rename from ObservationSim/PSF/FieldDistortion.py rename to observation_sim/psf/FieldDistortion.py index 7c95fd6b7b3369cb2ae5792569dc293989d02a6c..506bbba487cc91b1c7a97418eb648c2a53491d9a 100644 --- a/ObservationSim/PSF/FieldDistortion.py +++ b/observation_sim/psf/FieldDistortion.py @@ -2,6 +2,7 @@ import galsim import numpy as np import cmath + class FieldDistortion(object): def __init__(self, chip, fdModel=None, fdModel_path=None, img_rot=0.): @@ -13,7 +14,8 @@ class FieldDistortion(object): with open(fdModel_path, "rb") as f: self.fdModel = pickle.load(f) else: - raise ValueError("Error: no field distortion model has been specified!") + raise ValueError( + "Error: no field distortion model has been specified!") else: self.fdModel = fdModel self.img_rot = img_rot @@ -21,19 +23,20 @@ class FieldDistortion(object): self.ixfdModel = self.ifdModel["xImagePos"] self.iyfdModel = self.ifdModel["yImagePos"] # first-order derivatives of the global field distortion model - self.ifx_dx = self.ixfdModel.partial_derivative(1,0) - self.ifx_dy = self.ixfdModel.partial_derivative(0,1) - self.ify_dx = self.iyfdModel.partial_derivative(1,0) - self.ify_dy = self.iyfdModel.partial_derivative(0,1) + self.ifx_dx = self.ixfdModel.partial_derivative(1, 0) + self.ifx_dy = self.ixfdModel.partial_derivative(0, 1) + self.ify_dx = self.iyfdModel.partial_derivative(1, 0) + self.ify_dy = self.iyfdModel.partial_derivative(0, 1) if "residual" in self.fdModel["wave1"]: - self.irsModel = self.fdModel["wave1"]["residual"]["ccd" + chip.getChipLabel(chipID=chip.chipID)] + self.irsModel = self.fdModel["wave1"]["residual"]["ccd" + + chip.getChipLabel(chipID=chip.chipID)] self.ixrsModel = self.irsModel["xResidual"] self.iyrsModel = self.irsModel["yResidual"] # first-order derivatives of the residual field distortion model - self.irx_dx = self.ixrsModel.partial_derivative(1,0) - self.irx_dy = self.ixrsModel.partial_derivative(0,1) - self.iry_dx = self.iyrsModel.partial_derivative(1,0) - self.iry_dy = self.iyrsModel.partial_derivative(0,1) + self.irx_dx = self.ixrsModel.partial_derivative(1, 0) + self.irx_dy = self.ixrsModel.partial_derivative(0, 1) + self.iry_dx = self.iyrsModel.partial_derivative(1, 0) + self.iry_dy = self.iyrsModel.partial_derivative(0, 1) else: self.irsModel = None @@ -95,8 +98,8 @@ class FieldDistortion(object): ix_dy = self.ifx_dy(x, y) iy_dx = self.ify_dx(x, y) iy_dy = self.ify_dy(x, y) - g1k_fd = 0.0 + (iy_dy - ix_dx) / (iy_dy + ix_dx) - g2k_fd = 0.0 - (iy_dx + ix_dy) / (iy_dy + ix_dx) + g1k_fd = 0.0 + (iy_dy - ix_dx) / (iy_dy + ix_dx) + g2k_fd = 0.0 - (iy_dx + ix_dy) / (iy_dy + ix_dx) # [TODO] [TESTING] Rotate the shear: g_abs = np.sqrt(g1k_fd**2 + g2k_fd**2) @@ -107,4 +110,3 @@ class FieldDistortion(object): fd_shear = galsim.Shear(g1=g1k_fd, g2=g2k_fd) return galsim.PositionD(x, y), fd_shear - diff --git a/observation_sim/psf/PSFGauss.py b/observation_sim/psf/PSFGauss.py new file mode 100644 index 0000000000000000000000000000000000000000..a21b0c8963da1aa7b4e22701d06b234b8402a69c --- /dev/null +++ b/observation_sim/psf/PSFGauss.py @@ -0,0 +1,125 @@ +import galsim +import sep +import numpy as np +from scipy.interpolate import interp1d + +from observation_sim.psf.PSFModel import PSFModel + + +class PSFGauss(PSFModel): + def __init__(self, chip, fwhm=0.187, sigSpin=0., psfRa=None): + self.pix_size = chip.pix_scale + self.chip = chip + if psfRa is None: + self.fwhm = fwhm + self.sigGauss = 0.15 + else: + self.fwhm = self.fwhmGauss(r=psfRa) + self.sigGauss = psfRa # 80% light radius + self.sigSpin = sigSpin + self.psf = galsim.Gaussian(flux=1.0, fwhm=fwhm) + + def perfGauss(self, r, sig): + """ + pseudo-error function, i.e. Cumulative distribution function of Gaussian distribution + + Parameter: + r: radius + sig: sigma of the Gaussian distribution + + Return: + the value of the pseudo CDF + """ + def gaussFun(sigma, r): return 1.0/(np.sqrt(2.0*np.pi) + * sigma) * np.exp(-r**2/(2.0*sigma**2)) + nxx = 1000 + rArr = np.linspace(0.0, r, nxx) + gauss = gaussFun(sig, rArr) + erf = 2.0*np.trapz(gauss, rArr) + return erf + + def fracGauss(self, sig, r=0.15, pscale=None): + """ + For a given Gaussian PSF with sigma=sig, + derive the flux ratio ar the given radius r + + Parameters: + sig: sigma of the Gauss PSF Function in arcsec + r: radius in arcsec + pscale: pixel scale + + Return: the flux ratio + """ + if pscale == None: + pscale = self.pix_size + gaussx = galsim.Gaussian(flux=1.0, sigma=sig) + gaussImg = gaussx.drawImage(scale=pscale, method='no_pixel') + gaussImg = gaussImg.array + size = np.size(gaussImg, axis=0) + cxy = 0.5*(size-1) + flux, ferr, flag = sep.sum_circle( + gaussImg, [cxy], [cxy], [r/pscale], subpix=0) + return flux + + def fwhmGauss(self, r=0.15, fr=0.8, pscale=None): + """ + Given a total flux ratio 'fr' within a fixed radius 'r', + estimate the fwhm of the Gaussian function + + return the fwhm in arcsec + """ + if pscale == None: + pscale = self.pix_size + err = 1.0e-3 + nxx = 100 + sig = np.linspace(0.5*pscale, 1.0, nxx) + frA = np.zeros(nxx) + for i in range(nxx): + frA[i] = self.fracGauss(sig[i], r=r, pscale=pscale) + index = [i for i in range(nxx-1) if (fr-frA[i]) + * (fr-frA[i+1]) <= 0.0][0] + + while abs(frA[index]-fr) > 1.0e-3: + sig = np.linspace(sig[index], sig[index+1], nxx) + for i in range(nxx): + frA[i] = self.fracGauss(sig[i], r=r, pscale=pscale) + index = [i for i in range( + nxx-1) if (fr-frA[i])*(fr-frA[i+1]) <= 0.0][0] + + fwhm = 2.35482*sig[index] + return fwhm + + def get_PSF(self, pos_img, chip=None, bandpass=None, folding_threshold=5.e-3): + dx = pos_img.x - self.chip.cen_pix_x + dy = pos_img.y - self.chip.cen_pix_y + return self.PSFspin(dx, dy) + + def PSFspin(self, x, y): + """ + The PSF profile at a given image position relative to the axis center + + Parameters: + theta : spin angles in a given exposure in unit of [arcsecond] + dx, dy: relative position to the axis center in unit of [pixels] + + Return: + Spinned PSF: g1, g2 and axis ratio 'a/b' + """ + a2Rad = np.pi/(60.0*60.0*180.0) + + ff = self.sigGauss * 0.107 * (1000.0/10.0) # in unit of [pixels] + rc = np.sqrt(x*x + y*y) + cpix = rc*(self.sigSpin*a2Rad) + + beta = (np.arctan2(y, x) + np.pi/2) + ell = cpix**2/(2.0*ff**2+cpix**2) + # ell *= 10.0 + qr = np.sqrt((1.0+ell)/(1.0-ell)) + + # psfShape = galsim.Shear(e=ell, beta=beta) + # g1, g2 = psfShape.g1, psfShape.g2 + # qr = np.sqrt((1.0+ell)/(1.0-ell)) + + # return ell, beta, qr + PSFshear = galsim.Shear(e=ell, beta=beta*galsim.radians) + return self.psf.shear(PSFshear), PSFshear diff --git a/ObservationSim/PSF/PSFInterp.py b/observation_sim/psf/PSFInterp.py similarity index 70% rename from ObservationSim/PSF/PSFInterp.py rename to observation_sim/psf/PSFInterp.py index 9e9b65c0773d1d47452d9875a8389cec7c34e37e..97435ad048225969fd5287e1dd01a26ef2eb639f 100644 --- a/ObservationSim/PSF/PSFInterp.py +++ b/observation_sim/psf/PSFInterp.py @@ -12,14 +12,14 @@ import scipy.spatial as spatial import galsim import h5py -from ObservationSim.PSF.PSFModel import PSFModel +from observation_sim.psf.PSFModel import PSFModel -NPSF = 900 #***# 30*30 -PixSizeInMicrons = 5. #***# in microns +NPSF = 900 # ***# 30*30 +PixSizeInMicrons = 5. # ***# in microns -###find neighbors-KDtree### +### find neighbors-KDtree### def findNeighbors(tx, ty, px, py, dr=0.1, dn=1, OnlyDistance=True): """ find nearest neighbors by 2D-KDTree @@ -38,7 +38,7 @@ def findNeighbors(tx, ty, px, py, dr=0.1, dn=1, OnlyDistance=True): datay = py tree = spatial.KDTree(list(zip(datax.ravel(), datay.ravel()))) - dataq=[] + dataq = [] rr = dr if OnlyDistance == True: dataq = tree.query_ball_point([tx, ty], rr) @@ -51,7 +51,9 @@ def findNeighbors(tx, ty, px, py, dr=0.1, dn=1, OnlyDistance=True): dataq = np.array(dataq)[ddSortindx[0:dn]] return dataq -###find neighbors-hoclist### +### find neighbors-hoclist### + + def hocBuild(partx, party, nhocx, nhocy, dhocx, dhocy): if np.max(partx) > nhocx*dhocx: print('ERROR') @@ -60,8 +62,8 @@ def hocBuild(partx, party, nhocx, nhocy, dhocx, dhocy): print('ERROR') sys.exit() - npart = partx.size - hoclist= np.zeros(npart, dtype=np.int32)-1 + npart = partx.size + hoclist = np.zeros(npart, dtype=np.int32)-1 hoc = np.zeros([nhocy, nhocx], dtype=np.int32)-1 for ipart in range(npart): ix = int(partx[ipart]/dhocx) @@ -70,18 +72,20 @@ def hocBuild(partx, party, nhocx, nhocy, dhocx, dhocy): hoc[iy, ix] = ipart return hoc, hoclist + def hocFind(px, py, dhocx, dhocy, hoc, hoclist): ix = int(px/dhocx) iy = int(py/dhocy) - neigh=[] + neigh = [] it = hoc[iy, ix] while it != -1: neigh.append(it) it = hoclist[it] return neigh -def findNeighbors_hoclist(px, py, tx=None,ty=None, dn=4, hoc=None, hoclist=None): + +def findNeighbors_hoclist(px, py, tx=None, ty=None, dn=4, hoc=None, hoclist=None): nhocy = nhocx = 20 pxMin = np.min(px) @@ -91,21 +95,21 @@ def findNeighbors_hoclist(px, py, tx=None,ty=None, dn=4, hoc=None, hoclist=None) dhocx = (pxMax - pxMin)/(nhocx-1) dhocy = (pyMax - pyMin)/(nhocy-1) - partx = px - pxMin +dhocx/2 - party = py - pyMin +dhocy/2 + partx = px - pxMin + dhocx/2 + party = py - pyMin + dhocy/2 if hoc is None: hoc, hoclist = hocBuild(partx, party, nhocx, nhocy, dhocx, dhocy) return hoc, hoclist if hoc is not None: - tx = tx - pxMin +dhocx/2 - ty = ty - pyMin +dhocy/2 + tx = tx - pxMin + dhocx/2 + ty = ty - pyMin + dhocy/2 itx = int(tx/dhocx) ity = int(ty/dhocy) ps = [-1, 0, 1] - neigh=[] + neigh = [] for ii in range(3): for jj in range(3): ix = itx + ps[ii] @@ -119,23 +123,23 @@ def findNeighbors_hoclist(px, py, tx=None,ty=None, dn=4, hoc=None, hoclist=None) if iy > nhocy-1: continue - #neightt = myUtil.hocFind(ppx, ppy, dhocx, dhocy, hoc, hoclist) + # neightt = myUtil.hocFind(ppx, ppy, dhocx, dhocy, hoc, hoclist) it = hoc[iy, ix] while it != -1: neigh.append(it) it = hoclist[it] - #neigh.append(neightt) - #ll = [i for k in neigh for i in k] + # neigh.append(neightt) + # ll = [i for k in neigh for i in k] if dn != -1: ptx = np.array(partx[neigh]) pty = np.array(party[neigh]) - dd = np.hypot(ptx-tx, pty-ty) + dd = np.hypot(ptx-tx, pty-ty) idx = np.argsort(dd) - neigh= np.array(neigh)[idx[0:dn]] + neigh = np.array(neigh)[idx[0:dn]] return neigh -###PSF-IDW### +### PSF-IDW### def psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, IDWindex=2, OnlyNeighbors=True, hoc=None, hoclist=None, PSFCentroidWgt=False): """ psf interpolation by IDW @@ -161,9 +165,11 @@ def psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, IDWindex=2, OnlyNeighbors=Tru if OnlyNeighbors == True: if hoc is None: - neigh = findNeighbors(px, py, cen_col, cen_row, dr=5., dn=4, OnlyDistance=False) + neigh = findNeighbors(px, py, cen_col, cen_row, + dr=5., dn=4, OnlyDistance=False) if hoc is not None: - neigh = findNeighbors_hoclist(cen_col, cen_row, tx=px,ty=py, dn=4, hoc=hoc, hoclist=hoclist) + neigh = findNeighbors_hoclist( + cen_col, cen_row, tx=px, ty=py, dn=4, hoc=hoc, hoclist=hoclist) neighFlag = np.zeros(npsf) neighFlag[neigh] = 1 @@ -173,7 +179,8 @@ def psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, IDWindex=2, OnlyNeighbors=Tru if neighFlag[ipsf] != 1: continue - dist = np.sqrt((ref_col - cen_col[ipsf])**2 + (ref_row - cen_row[ipsf])**2) + dist = np.sqrt((ref_col - cen_col[ipsf]) + ** 2 + (ref_row - cen_row[ipsf])**2) if IDWindex == 1: psfWeight[ipsf] = dist if IDWindex == 2: @@ -186,7 +193,7 @@ def psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, IDWindex=2, OnlyNeighbors=Tru psfWeight[ipsf] = 1./psfWeight[ipsf] psfWeight /= np.sum(psfWeight) - psfMaker = np.zeros([ngy, ngx], dtype=np.float32) + psfMaker = np.zeros([ngy, ngx], dtype=np.float32) for ipsf in range(npsf): if OnlyNeighbors == True: if neighFlag[ipsf] != 1: @@ -201,15 +208,14 @@ def psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, IDWindex=2, OnlyNeighbors=Tru return psfMaker - -###define PSFInterp### +### define PSFInterp### class PSFInterp(PSFModel): def __init__(self, chip, npsf=NPSF, PSF_data=None, PSF_data_file=None, PSF_data_prefix="", sigSpin=0, psfRa=0.15, HocBuild=False, LOG_DEBUG=False): self.LOG_DEBUG = LOG_DEBUG if self.LOG_DEBUG: print('===================================================') - print('DEBUG: psf module for csstSim ' \ - +time.strftime("(%Y-%m-%d %H:%M:%S)", time.localtime()), flush=True) + print('DEBUG: psf module for csstSim ' + + time.strftime("(%Y-%m-%d %H:%M:%S)", time.localtime()), flush=True) print('===================================================') self.sigSpin = sigSpin @@ -221,53 +227,62 @@ class PSFInterp(PSFModel): print('Error - PSF_data_file is None') sys.exit() - self.nwave= self._getPSFwave(self.iccd, PSF_data_file, PSF_data_prefix) + self.nwave = self._getPSFwave( + self.iccd, PSF_data_file, PSF_data_prefix) self.npsf = npsf - self.PSF_data = self._loadPSF(self.iccd, PSF_data_file, PSF_data_prefix) + self.PSF_data = self._loadPSF( + self.iccd, PSF_data_file, PSF_data_prefix) if self.LOG_DEBUG: - print('nwave-{:} on ccd-{:}::'.format(self.nwave, self.iccd), flush=True) + print('nwave-{:} on ccd-{:}::'.format(self.nwave, + self.iccd), flush=True) print('self.PSF_data ... ok', flush=True) - print('Preparing self.[psfMat,cen_col,cen_row] for psfMaker ... ', end='', flush=True) - - ngy, ngx = self.PSF_data[0][0]['psfMat'].shape - self.psfMat = np.zeros([self.nwave, self.npsf, ngy, ngx], dtype=np.float32) - self.cen_col= np.zeros([self.nwave, self.npsf], dtype=np.float32) - self.cen_row= np.zeros([self.nwave, self.npsf], dtype=np.float32) - self.hoc =[] - self.hoclist=[] - + print( + 'Preparing self.[psfMat,cen_col,cen_row] for psfMaker ... ', end='', flush=True) + + ngy, ngx = self.PSF_data[0][0]['psfMat'].shape + self.psfMat = np.zeros( + [self.nwave, self.npsf, ngy, ngx], dtype=np.float32) + self.cen_col = np.zeros([self.nwave, self.npsf], dtype=np.float32) + self.cen_row = np.zeros([self.nwave, self.npsf], dtype=np.float32) + self.hoc = [] + self.hoclist = [] + for twave in range(self.nwave): for tpsf in range(self.npsf): - self.psfMat[twave, tpsf, :, :] = self.PSF_data[twave][tpsf]['psfMat'] - self.PSF_data[twave][tpsf]['psfMat'] = 0 ###free psfMat + self.psfMat[twave, tpsf, :, + :] = self.PSF_data[twave][tpsf]['psfMat'] + self.PSF_data[twave][tpsf]['psfMat'] = 0 # free psfMat - self.pixsize = self.PSF_data[twave][tpsf]['pixsize']*1e-3 ##mm - self.cen_col[twave, tpsf] = self.PSF_data[twave][tpsf]['image_x'] + self.PSF_data[twave][tpsf]['centroid_x'] - self.cen_row[twave, tpsf] = self.PSF_data[twave][tpsf]['image_y'] + self.PSF_data[twave][tpsf]['centroid_y'] + self.pixsize = self.PSF_data[twave][tpsf]['pixsize']*1e-3 # mm + self.cen_col[twave, tpsf] = self.PSF_data[twave][tpsf]['image_x'] + \ + self.PSF_data[twave][tpsf]['centroid_x'] + self.cen_row[twave, tpsf] = self.PSF_data[twave][tpsf]['image_y'] + \ + self.PSF_data[twave][tpsf]['centroid_y'] if HocBuild: - #hoclist on twave for neighborsFinding - hoc,hoclist = findNeighbors_hoclist(self.cen_col[twave], self.cen_row[twave]) + # hoclist on twave for neighborsFinding + hoc, hoclist = findNeighbors_hoclist( + self.cen_col[twave], self.cen_row[twave]) self.hoc.append(hoc) self.hoclist.append(hoclist) if self.LOG_DEBUG: print('ok', flush=True) - def _getPSFwave(self, iccd, PSF_data_file, PSF_data_prefix): # fq = h5py.File(PSF_data_file+'/' +PSF_data_prefix +'psfCube_ccd{:}.h5'.format(iccd), 'r') - fq = h5py.File(PSF_data_file+'/' +PSF_data_prefix +'psfCube_{:}.h5'.format(iccd), 'r') + fq = h5py.File(PSF_data_file+'/' + PSF_data_prefix + + 'psfCube_{:}.h5'.format(iccd), 'r') nwave = len(fq.keys()) fq.close() return nwave - def _loadPSF(self, iccd, PSF_data_file, PSF_data_prefix): psfSet = [] # fq = h5py.File(PSF_data_file+'/' +PSF_data_prefix +'psfCube_ccd{:}.h5'.format(iccd), 'r') - fq = h5py.File(PSF_data_file+'/' +PSF_data_prefix +'psfCube_{:}.h5'.format(iccd), 'r') + fq = h5py.File(PSF_data_file+'/' + PSF_data_prefix + + 'psfCube_{:}.h5'.format(iccd), 'r') for ii in range(self.nwave): iwave = ii+1 psfWave = [] @@ -276,30 +291,30 @@ class PSFInterp(PSFModel): for jj in range(self.npsf): ipsf = jj+1 psfInfo = {} - psfInfo['wavelength']= fq_iwave['wavelength'][()] + psfInfo['wavelength'] = fq_iwave['wavelength'][()] fq_iwave_ipsf = fq_iwave['psf_{:}'.format(ipsf)] - psfInfo['pixsize'] = PixSizeInMicrons - psfInfo['field_x'] = fq_iwave_ipsf['field_x'][()] - psfInfo['field_y'] = fq_iwave_ipsf['field_y'][()] - psfInfo['image_x'] = fq_iwave_ipsf['image_x'][()] - psfInfo['image_y'] = fq_iwave_ipsf['image_y'][()] - psfInfo['centroid_x']= fq_iwave_ipsf['cx'][()] - psfInfo['centroid_y']= fq_iwave_ipsf['cy'][()] - psfInfo['psfMat'] = fq_iwave_ipsf['psfMat'][()] - + psfInfo['pixsize'] = PixSizeInMicrons + psfInfo['field_x'] = fq_iwave_ipsf['field_x'][()] + psfInfo['field_y'] = fq_iwave_ipsf['field_y'][()] + psfInfo['image_x'] = fq_iwave_ipsf['image_x'][()] + psfInfo['image_y'] = fq_iwave_ipsf['image_y'][()] + psfInfo['centroid_x'] = fq_iwave_ipsf['cx'][()] + psfInfo['centroid_y'] = fq_iwave_ipsf['cy'][()] + psfInfo['psfMat'] = fq_iwave_ipsf['psfMat'][()] + psfWave.append(psfInfo) psfSet.append(psfWave) fq.close() if self.LOG_DEBUG: print('psfSet has been loaded:', flush=True) - print('psfSet[iwave][ipsf][keys]:', psfSet[0][0].keys(), flush=True) + print('psfSet[iwave][ipsf][keys]:', + psfSet[0][0].keys(), flush=True) return psfSet - def _findWave(self, bandpass): - if isinstance(bandpass,int): + if isinstance(bandpass, int): twave = bandpass return twave @@ -308,7 +323,6 @@ class PSFInterp(PSFModel): if bandpass.blue_limit < bandwave and bandwave < bandpass.red_limit: return twave return -1 - def get_PSF(self, chip, pos_img, bandpass, galsimGSObject=True, findNeighMode='treeFind', folding_threshold=5.e-3, pointing_pa=0.0): """ @@ -323,7 +337,7 @@ class PSFInterp(PSFModel): Returns: PSF: A 'galsim.GSObject'. """ - pixSize = np.rad2deg(self.pixsize*1e-3/28)*3600 #set psf pixsize + pixSize = np.rad2deg(self.pixsize*1e-3/28)*3600 # set psf pixsize # assert self.iccd == int(chip.getChipLabel(chipID=chip.chipID)), 'ERROR: self.iccd != chip.chipID' twave = self._findWave(bandpass) @@ -331,16 +345,18 @@ class PSFInterp(PSFModel): print("!!!PSF bandpass does not match.") exit() PSFMat = self.psfMat[twave] - cen_col= self.cen_col[twave] - cen_row= self.cen_row[twave] + cen_col = self.cen_col[twave] + cen_row = self.cen_row[twave] px = (pos_img.x - chip.cen_pix_x)*0.01 py = (pos_img.y - chip.cen_pix_y)*0.01 if findNeighMode == 'treeFind': - imPSF = psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, IDWindex=2, OnlyNeighbors=True, PSFCentroidWgt=True) + imPSF = psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, + IDWindex=2, OnlyNeighbors=True, PSFCentroidWgt=True) if findNeighMode == 'hoclistFind': - assert(self.hoc != 0), 'hoclist should be built correctly!' - imPSF = psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, IDWindex=2, OnlyNeighbors=True, hoc=self.hoc[twave], hoclist=self.hoclist[twave], PSFCentroidWgt=True) + assert (self.hoc != 0), 'hoclist should be built correctly!' + imPSF = psfMaker_IDW(px, py, PSFMat, cen_col, cen_row, IDWindex=2, OnlyNeighbors=True, + hoc=self.hoc[twave], hoclist=self.hoclist[twave], PSFCentroidWgt=True) ''' ############TEST: START @@ -353,20 +369,21 @@ class PSFInterp(PSFModel): ''' if galsimGSObject: - imPSFt = np.zeros([257,257]) + imPSFt = np.zeros([257, 257]) imPSFt[0:256, 0:256] = imPSF # imPSFt[120:130, 0:256] = 1. img = galsim.ImageF(imPSFt, scale=pixSize) gsp = galsim.GSParams(folding_threshold=folding_threshold) - ############TEST: START + # TEST: START # Use sheared PSF to test the PSF orientation # self.psf = galsim.InterpolatedImage(img, gsparams=gsp).shear(g1=0.8, g2=0.) - ############TEST: END + # TEST: END self.psf = galsim.InterpolatedImage(img, gsparams=gsp) wcs = chip.img.wcs.local(pos_img) scale = galsim.PixelScale(0.074) - self.psf = wcs.toWorld(scale.toImage(self.psf), image_pos=(pos_img)) + self.psf = wcs.toWorld(scale.toImage( + self.psf), image_pos=(pos_img)) # return self.PSFspin(x=px/0.01, y=py/0.01) return self.psf, galsim.Shear(e=0., beta=(np.pi/2)*galsim.radians) diff --git a/ObservationSim/PSF/PSFInterpSLS.py b/observation_sim/psf/PSFInterpSLS.py similarity index 88% rename from ObservationSim/PSF/PSFInterpSLS.py rename to observation_sim/psf/PSFInterpSLS.py index 7dc1624c2ae4305cac78650044e46c95e6de57a2..7adfedc5b953339492940d41b08e0f31c062213c 100644 --- a/ObservationSim/PSF/PSFInterpSLS.py +++ b/observation_sim/psf/PSFInterpSLS.py @@ -4,6 +4,7 @@ PSF interpolation for CSST-Sim NOTE: [iccd, iwave, ipsf] are counted from 1 to n, but [tccd, twave, tpsf] are counted from 0 to n-1 ''' +import yaml import sys import time import copy @@ -12,8 +13,9 @@ import scipy.spatial as spatial import galsim import h5py -from ObservationSim.PSF.PSFModel import PSFModel -from ObservationSim.Instrument.Chip import ChipUtils as chip_utils +from observation_sim.instruments import Filter, FilterParam, Chip +from observation_sim.psf.PSFModel import PSFModel +from observation_sim.instruments.chip import chip_utils import os from astropy.io import fits @@ -21,12 +23,12 @@ from astropy.modeling.models import Gaussian2D from scipy import signal -LOG_DEBUG = False #***# -NPSF = 900 #***# 30*30 -PixSizeInMicrons = 5. #***# in microns +LOG_DEBUG = False # ***# +NPSF = 900 # ***# 30*30 +PIX_SIZE_MICRON = 5. # ***# in microns -###find neighbors-KDtree### +### find neighbors-KDtree### # def findNeighbors(tx, ty, px, py, dr=0.1, dn=1, OnlyDistance=True): # """ # find nearest neighbors by 2D-KDTree @@ -208,36 +210,35 @@ PixSizeInMicrons = 5. #***# in microns # return psfMaker - -###define PSFInterp### +### define PSFInterp### class PSFInterpSLS(PSFModel): - def __init__(self, chip, filt,PSF_data_prefix="", sigSpin=0, psfRa=0.15, pix_size = 0.005): + def __init__(self, chip, filt, PSF_data_prefix="", sigSpin=0, psfRa=0.15, pix_size=0.005): if LOG_DEBUG: print('===================================================') - print('DEBUG: psf module for csstSim ' \ - +time.strftime("(%Y-%m-%d %H:%M:%S)", time.localtime()), flush=True) + print('DEBUG: psf module for csstSim ' + + time.strftime("(%Y-%m-%d %H:%M:%S)", time.localtime()), flush=True) print('===================================================') self.sigSpin = sigSpin self.sigGauss = psfRa self.grating_ids = chip_utils.getChipSLSGratingID(chip.chipID) - _,self.grating_type = chip.getChipFilter(chipID=chip.chipID) + _, self.grating_type = chip.getChipFilter(chipID=chip.chipID) self.data_folder = PSF_data_prefix self.getPSFDataFromFile(filt) - self.pixsize = pix_size # um + self.pixsize = pix_size # um def getPSFDataFromFile(self, filt): - gratingInwavelist = {'GU':0,'GV':1,'GI':2} - grating_orders = ['0','1'] + gratingInwavelist = {'GU': 0, 'GV': 1, 'GI': 2} + grating_orders = ['0', '1'] waveListFn = self.data_folder + '/wavelist.dat' wavelists = np.loadtxt(waveListFn) - self.waveList = wavelists[:,gratingInwavelist[self.grating_type]] - bandranges = np.zeros([4,2]) + self.waveList = wavelists[:, gratingInwavelist[self.grating_type]] + bandranges = np.zeros([4, 2]) midBand = (self.waveList[0:3] + self.waveList[1:4])/2.*10000. - bandranges[0,0] = filt.blue_limit - bandranges[1:4,0] = midBand + bandranges[0, 0] = filt.blue_limit + bandranges[1:4, 0] = midBand bandranges[0:3, 1] = midBand - bandranges[3,1] = filt.red_limit + bandranges[3, 1] = filt.red_limit self.bandranges = bandranges @@ -246,7 +247,7 @@ class PSFInterpSLS(PSFModel): for g_order in grating_orders: g_folder_order = g_folder + 'PSF_Order_' + g_order + '/' grating_order_data = {} - for bandi in [1,2,3,4]: + for bandi in [1, 2, 3, 4]: subBand_data = {} subBand_data['bandrange'] = bandranges[bandi-1] final_folder = g_folder_order + str(bandi) + '/' @@ -305,7 +306,7 @@ class PSFInterpSLS(PSFModel): # psfInfo['wavelength']= fq_iwave['wavelength'][()] # # fq_iwave_ipsf = fq_iwave['psf_{:}'.format(ipsf)] - # psfInfo['pixsize'] = PixSizeInMicrons + # psfInfo['pixsize'] = PIX_SIZE_MICRON # psfInfo['field_x'] = fq_iwave_ipsf['field_x'][()] # psfInfo['field_y'] = fq_iwave_ipsf['field_y'][()] # psfInfo['image_x'] = fq_iwave_ipsf['image_x'][()] @@ -342,7 +343,7 @@ class PSFInterpSLS(PSFModel): offset = int(np.ceil(sigma * 3)) g_size = 2 * offset + 1 m_cen = int(g_size / 2) - print('-----',g_size) + print('-----', g_size) g_PSF_ = Gaussian2D(1, m_cen, m_cen, sigma, sigma) yp, xp = np.mgrid[0:g_size, 0:g_size] g_PSF = g_PSF_(xp, yp) @@ -351,8 +352,7 @@ class PSFInterpSLS(PSFModel): convImg = convImg/np.sum(convImg) return convImg - - def get_PSF(self, chip, pos_img_local = [1000,1000], bandNo = 1, galsimGSObject=True, folding_threshold=5.e-3, g_order = 'A', grating_split_pos=3685): + def get_PSF(self, chip, pos_img_local=[1000, 1000], bandNo=1, galsimGSObject=True, folding_threshold=5.e-3, g_order='A', grating_split_pos=3685): """ Get the PSF at a given image position @@ -365,8 +365,9 @@ class PSFInterpSLS(PSFModel): Returns: PSF: A 'galsim.GSObject'. """ - order_IDs = {'A': '1', 'B': '0' ,'C': '0', 'D': '0', 'E': '0'} - contam_order_sigma = {'C':0.28032344707964174,'D':0.39900182912061344,'E':1.1988309797685412} #arcsec + order_IDs = {'A': '1', 'B': '0', 'C': '0', 'D': '0', 'E': '0'} + contam_order_sigma = {'C': 0.28032344707964174, + 'D': 0.39900182912061344, 'E': 1.1988309797685412} # arcsec x_start = chip.x_cen/chip.pix_size - chip.npix_x / 2. y_start = chip.y_cen/chip.pix_size - chip.npix_y / 2. # print(pos_img.x - x_start) @@ -382,7 +383,6 @@ class PSFInterpSLS(PSFModel): # if grating_order in ['-2','-1','2']: # grating_order = '1' - # if grating_order in ['0', '1']: psf_order = psf_data['order'+grating_order] psf_order_b = psf_order['band'+str(bandNo)] @@ -396,31 +396,34 @@ class PSFInterpSLS(PSFModel): px = pos_img.x*chip.pix_size py = pos_img.y*chip.pix_size - dist2=(pos_p[:,1] - px)*(pos_p[:,1] - px) + (pos_p[:,0] - py)*(pos_p[:,0] - py) - temp_sort_dist = np.zeros([dist2.shape[0],2]) - temp_sort_dist[:, 0] = np.arange(0, dist2.shape[0],1) + dist2 = (pos_p[:, 1] - px)*(pos_p[:, 1] - px) + \ + (pos_p[:, 0] - py)*(pos_p[:, 0] - py) + temp_sort_dist = np.zeros([dist2.shape[0], 2]) + temp_sort_dist[:, 0] = np.arange(0, dist2.shape[0], 1) temp_sort_dist[:, 1] = dist2 # print(temp_sort_dist) - dits2_sortlist = sorted(temp_sort_dist, key=lambda x:x[1]) + dits2_sortlist = sorted(temp_sort_dist, key=lambda x: x[1]) # print(dits2_sortlist) - nearest4p = np.zeros([4,2]) - pc_coeff_4p = np.zeros([pc_coeff.data.shape[0],4]) + nearest4p = np.zeros([4, 2]) + pc_coeff_4p = np.zeros([pc_coeff.data.shape[0], 4]) for i in np.arange(4): smaller_ids = int(dits2_sortlist[i][0]) nearest4p[i, 0] = pos_p[smaller_ids, 1] nearest4p[i, 1] = pos_p[smaller_ids, 0] - pc_coeff_4p[:,i] = pc_coeff[:,smaller_ids] - idw_dist = 1/(np.sqrt((px-nearest4p[:,0]) * (px-nearest4p[:,0]) + (py-nearest4p[:,1]) * (py-nearest4p[:,1]))) + pc_coeff_4p[:, i] = pc_coeff[:, smaller_ids] + idw_dist = 1/(np.sqrt((px-nearest4p[:, 0]) * (px-nearest4p[:, 0]) + ( + py-nearest4p[:, 1]) * (py-nearest4p[:, 1]))) coeff_int = np.zeros(pc_coeff.data.shape[0]) for i in np.arange(4): - coeff_int = coeff_int + pc_coeff_4p[:,i]*idw_dist[i] + coeff_int = coeff_int + pc_coeff_4p[:, i]*idw_dist[i] coeff_int = coeff_int / np.sum(coeff_int) npc = 10 m_size = int(pcs.shape[0]**0.5) - PSF_int = np.dot(pcs[:,0:npc],coeff_int[0:npc]).reshape(m_size,m_size) + PSF_int = np.dot(pcs[:, 0:npc], coeff_int[0:npc] + ).reshape(m_size, m_size) # PSF_int = PSF_int/np.sum(PSF_int) PSF_int_trans = np.flipud(np.fliplr(PSF_int)) @@ -434,7 +437,6 @@ class PSFInterpSLS(PSFModel): # from astropy.io import fits # fits.writeto(str(bandNo) + '_' + g_order+ '_psf_o.fits', PSF_int_trans) - # if g_order in ['C','D','E']: # g_simgma = contam_order_sigma[g_order]/pixel_size_arc # PSF_int_trans = self.convolveWithGauss(PSF_int_trans,g_simgma) @@ -459,24 +461,24 @@ class PSFInterpSLS(PSFModel): pixel_size_arc = np.rad2deg(self.pixsize * 1e-3 / 28) * 3600 img = galsim.ImageF(PSF_int_trans, scale=pixel_size_arc) gsp = galsim.GSParams(folding_threshold=folding_threshold) - ############TEST: START + # TEST: START # Use sheared PSF to test the PSF orientation # self.psf = galsim.InterpolatedImage(img, gsparams=gsp).shear(g1=0.8, g2=0.) - ############TEST: END + # TEST: END self.psf = galsim.InterpolatedImage(img, gsparams=gsp) # if g_order in ['C','D','E']: # add_psf = galsim.Gaussian(sigma=contam_order_sigma[g_order], flux=1.0) # self.psf = galsim.Convolve(self.psf, add_psf) wcs = chip.img.wcs.local(pos_img) scale = galsim.PixelScale(0.074) - self.psf = wcs.toWorld(scale.toImage(self.psf), image_pos=(pos_img)) + self.psf = wcs.toWorld(scale.toImage( + self.psf), image_pos=(pos_img)) # return self.PSFspin(x=px/0.01, y=py/0.01) return self.psf, galsim.Shear(e=0., beta=(np.pi/2)*galsim.radians) return PSF_int_trans, PSF_int - # pixSize = np.rad2deg(self.pixsize*1e-3/28)*3600 #set psf pixsize # # # assert self.iccd == int(chip.getChipLabel(chipID=chip.chipID)), 'ERROR: self.iccd != chip.chipID' @@ -547,24 +549,23 @@ class PSFInterpSLS(PSFModel): # PSFshear = galsim.Shear(e=ell, beta=beta*galsim.radians) # return self.psf.shear(PSFshear), PSFshear -from ObservationSim.Instrument import Filter, FilterParam, Chip -import yaml + if __name__ == '__main__': configfn = '/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_new_sim/csst-simulation/config/config_C6_dev.yaml' with open(configfn, "r") as stream: try: config = yaml.safe_load(stream) for key, value in config.items(): - print (key + " : " + str(value)) + print(key + " : " + str(value)) except yaml.YAMLError as exc: print(exc) - chip = Chip(chipID=1,config=config) + chip = Chip(chipID=1, config=config) filter_id, filter_type = chip.getChipFilter() filt = Filter(filter_id=filter_id, filter_type=filter_type, filter_param=FilterParam()) - psf_i = PSFInterpSLS(chip, filt,PSF_data_prefix="/Volumes/EAGET/CSST_PSF_data/SLS_PSF_PCA_fp/") + psf_i = PSFInterpSLS( + chip, filt, PSF_data_prefix="/Volumes/EAGET/CSST_PSF_data/SLS_PSF_PCA_fp/") pos_img = galsim.PositionD(x=25155, y=-22060) - psf_im = psf_i.get_PSF(chip, pos_img = pos_img, g_order = '1') - + psf_im = psf_i.get_PSF(chip, pos_img=pos_img, g_order='1') diff --git a/observation_sim/psf/PSFModel.py b/observation_sim/psf/PSFModel.py new file mode 100755 index 0000000000000000000000000000000000000000..604ff8b20130ea43ef26e096936b879e842da1f1 --- /dev/null +++ b/observation_sim/psf/PSFModel.py @@ -0,0 +1,43 @@ +import galsim +import sep +import numpy as np +from scipy.interpolate import interp1d +import pylab as pl +import os +import sys + + +class PSFModel(object): + def __init__(self, sigSpin=0., psfRa=0.15): + # TODO: what are the nesseary fields in PSFModel class? + pass + + def PSFspin(self, psf, sigSpin, sigGauss, dx, dy): + """ + The PSF profile at a given image position relative to the axis center + + Parameters: + theta : spin angles in a given exposure in unit of [arcsecond] + dx, dy: relative position to the axis center in unit of [pixels] + + Return: + Spinned PSF: g1, g2 and axis ratio 'a/b' + """ + a2Rad = np.pi/(60.0*60.0*180.0) + + ff = sigGauss * 0.107 * (1000.0/10.0) # in unit of [pixels] + rc = np.sqrt(dx*dx + dy*dy) + cpix = rc*(sigSpin*a2Rad) + + beta = (np.arctan2(dy, dx) + np.pi/2) + ell = cpix**2/(2.0*ff**2+cpix**2) + # ell *= 10.0 + qr = np.sqrt((1.0+ell)/(1.0-ell)) + + # psfShape = galsim.Shear(e=ell, beta=beta) + # g1, g2 = psfShape.g1, psfShape.g2 + # qr = np.sqrt((1.0+ell)/(1.0-ell)) + + # return ell, beta, qr + PSFshear = galsim.Shear(e=ell, beta=beta*galsim.radians) + return psf.shear(PSFshear), PSFshear diff --git a/ObservationSim/PSF/__init__.py b/observation_sim/psf/__init__.py similarity index 100% rename from ObservationSim/PSF/__init__.py rename to observation_sim/psf/__init__.py diff --git a/ObservationSim/sim_steps/__init__.py b/observation_sim/sim_steps/__init__.py similarity index 100% rename from ObservationSim/sim_steps/__init__.py rename to observation_sim/sim_steps/__init__.py diff --git a/observation_sim/sim_steps/add_LED_flat.py b/observation_sim/sim_steps/add_LED_flat.py new file mode 100644 index 0000000000000000000000000000000000000000..76bcdbd5459fdf0eb7e41bc652acc36e48f2fcb5 --- /dev/null +++ b/observation_sim/sim_steps/add_LED_flat.py @@ -0,0 +1,59 @@ +import numpy as np +from observation_sim.mock_objects import FlatLED +import galsim + +from astropy.time import Time +from datetime import datetime, timezone + +import gc + + +def add_LED_Flat(self, chip, filt, tel, pointing, catalog, obs_param): + + if not hasattr(self, 'h_ext'): + _, _ = self.prepare_headers(chip=chip, pointing=pointing) + chip_wcs = galsim.FitsWCS(header=self.h_ext) + pf_map = np.zeros_like(chip.img.array) + if obs_param["LED_TYPE"] is not None: + if len(obs_param["LED_TYPE"]) != 0: + print("LED OPEN--------") + + led_obj = FlatLED(chip, filt) + led_flat, ledstat, letts = led_obj.drawObj_LEDFlat( + led_type_list=obs_param["LED_TYPE"], exp_t_list=obs_param["LED_TIME"]) + pf_map = led_flat + self.updateHeaderInfo(header_flag='ext', keys=[ + 'LEDSTAT'], values=[ledstat]) + self.updateHeaderInfo(header_flag='ext', keys=['LEDT01', 'LEDT02', 'LEDT03', 'LEDT04', 'LEDT05', 'LEDT06', + 'LEDT07', 'LEDT08', 'LEDT09', 'LEDT10', 'LEDT11', 'LEDT12', 'LEDT13', 'LEDT14'], values=letts) + + if obs_param["shutter_effect"] == True: + pf_map = pf_map * chip.shutter_img + pf_map = np.array(pf_map, dtype='float32') + self.updateHeaderInfo(header_flag='ext', keys=[ + 'SHTSTAT'], values=[True]) + else: + self.updateHeaderInfo(header_flag='ext', keys=['SHTSTAT', 'SHTOPEN1', 'SHTCLOS0'], values=[ + True, self.h_ext['SHTCLOS1'], self.h_ext['SHTOPEN0']]) + + chip.img = chip.img + pf_map + + # renew header info + datetime_obs = datetime.utcfromtimestamp(pointing.timestamp) + datetime_obs = datetime_obs.replace(tzinfo=timezone.utc) + t_obs = Time(datetime_obs) + + # ccd刷新2s,等待0.5s,开灯后等待0.5s,开始曝光 + t_obs_renew = Time(t_obs.mjd - (2.) / 86400., format="mjd") + + t_obs_utc = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp( + t_obs_renew.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) + self.updateHeaderInfo(header_flag='prim', keys=[ + 'DATE-OBS'], values=[t_obs_utc.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]]) + + # dark time : + self.updateHeaderInfo(header_flag='ext', keys=[ + 'DARKTIME'], values=[pointing.exp_time]) + + gc.collect() + return chip, filt, tel, pointing diff --git a/ObservationSim/sim_steps/add_brighter_fatter_CTE.py b/observation_sim/sim_steps/add_brighter_fatter_CTE.py similarity index 59% rename from ObservationSim/sim_steps/add_brighter_fatter_CTE.py rename to observation_sim/sim_steps/add_brighter_fatter_CTE.py index ec8a31ad37f0b81199e58ddd81c3e7183bb36f1e..d235b4161f16c5da15d7e4c22f629f86fc00b5e5 100644 --- a/ObservationSim/sim_steps/add_brighter_fatter_CTE.py +++ b/observation_sim/sim_steps/add_brighter_fatter_CTE.py @@ -1,15 +1,17 @@ import numpy as np import galsim -from ObservationSim.Instrument.Chip import ChipUtils as chip_utils -from ObservationSim.Instrument.Chip.libCTI.CTI_modeling import CTI_sim +from observation_sim.instruments.chip import chip_utils +from observation_sim.instruments.chip.libCTI.CTI_modeling import CTI_sim + def add_brighter_fatter(self, chip, filt, tel, pointing, catalog, obs_param): chip.img = chip_utils.add_brighter_fatter(img=chip.img) return chip, filt, tel, pointing + def apply_CTE(self, chip, filt, tel, pointing, catalog, obs_param): self.chip_output.Log_info(" Apply CTE Effect") - ### 2*8 -> 1*16 img-layout + # 2*8 -> 1*16 img-layout img = chip_utils.formatOutput(GSImage=chip.img) chip.nsecy = 1 chip.nsecx = 16 @@ -20,23 +22,26 @@ def apply_CTE(self, chip, filt, tel, pointing, catalog, obs_param): dy = int(ny/chip.nsecy) newimg = galsim.Image(nx, int(ny+chip.overscan_y), init_value=0) for ichannel in range(16): - print('\n***add CTI effects: pointing-{:} chip-{:} channel-{:}***'.format(pointing.id, chip.chipID, ichannel+1)) + print('\n***add CTI effects: pointing-{:} chip-{:} channel-{:}***'.format( + pointing.id, chip.chipID, ichannel+1)) noverscan, nsp, nmax = chip.overscan_y, 3, 10 beta, w, c = 0.478, 84700, 0 - t = np.array([0.74, 7.7, 37],dtype=np.float32) - rho_trap = np.array([0.6, 1.6, 1.4],dtype=np.float32) - trap_seeds = np.array([0, 1000, 10000],dtype=np.int32) + ichannel + chip.chipID*16 - release_seed = 50 + ichannel + pointing.id*30 + chip.chipID*16 - newimg.array[:, 0+ichannel*dx:dx+ichannel*dx] = CTI_sim(img_arr[:, 0+ichannel*dx:dx+ichannel*dx],dx,dy,noverscan,nsp,nmax,beta,w,c,t,rho_trap,trap_seeds,release_seed) + t = np.array([0.74, 7.7, 37], dtype=np.float32) + rho_trap = np.array([0.6, 1.6, 1.4], dtype=np.float32) + trap_seeds = np.array( + [0, 1000, 10000], dtype=np.int32) + ichannel + chip.chipID*16 + release_seed = 50 + ichannel + pointing.id*30 + chip.chipID*16 + newimg.array[:, 0+ichannel*dx:dx+ichannel*dx] = CTI_sim( + img_arr[:, 0+ichannel*dx:dx+ichannel*dx], dx, dy, noverscan, nsp, nmax, beta, w, c, t, rho_trap, trap_seeds, release_seed) newimg.wcs = img.wcs del img img = newimg - ### 1*16 -> 2*8 img-layout + # 1*16 -> 2*8 img-layout chip.img = chip_utils.formatRevert(GSImage=img) chip.nsecy = 2 chip.nsecx = 8 - + # [TODO] make overscan_y == 0 chip.overscan_y = 0 - return chip, filt, tel, pointing \ No newline at end of file + return chip, filt, tel, pointing diff --git a/ObservationSim/sim_steps/add_cosmic_rays.py b/observation_sim/sim_steps/add_cosmic_rays.py similarity index 85% rename from ObservationSim/sim_steps/add_cosmic_rays.py rename to observation_sim/sim_steps/add_cosmic_rays.py index 147fa064b2b2be157aae77848a971ba83d57dbfb..77a470a3a4630175087ad8b2871df717ac36ab1b 100644 --- a/ObservationSim/sim_steps/add_cosmic_rays.py +++ b/observation_sim/sim_steps/add_cosmic_rays.py @@ -1,8 +1,9 @@ -from ObservationSim.Instrument.Chip import ChipUtils as chip_utils +from observation_sim.instruments.chip import chip_utils + def add_cosmic_rays(self, chip, filt, tel, pointing, catalog, obs_param): self.chip_output.Log_info(" Adding Cosmic-Ray") - + # Get exposure time if (obs_param) and ("exptime" in obs_param) and (obs_param["exptime"] is not None): exptime = obs_param["exptime"] @@ -10,9 +11,9 @@ def add_cosmic_rays(self, chip, filt, tel, pointing, catalog, obs_param): exptime = pointing.exp_time chip.img, crmap_gsimg, cr_event_num = chip_utils.add_cosmic_rays( - img=chip.img, - chip=chip, - exptime=exptime, + img=chip.img, + chip=chip, + exptime=exptime, seed=self.overall_config["random_seeds"]["seed_CR"]+pointing.id*30+chip.chipID) # Save cosmic ray image if (obs_param) and ("save_cosmic_img" in obs_param) and (obs_param["save_cosmic_img"] is not None): @@ -27,4 +28,4 @@ def add_cosmic_rays(self, chip, filt, tel, pointing, catalog, obs_param): project_cycle=self.overall_config["project_cycle"], run_counter=self.overall_config["run_counter"] ) - return chip, filt, tel, pointing \ No newline at end of file + return chip, filt, tel, pointing diff --git a/ObservationSim/sim_steps/add_objects.py b/observation_sim/sim_steps/add_objects.py similarity index 98% rename from ObservationSim/sim_steps/add_objects.py rename to observation_sim/sim_steps/add_objects.py index 1ec800106b20d2036d5e34ac41965b0d0ad830b0..9f41d3621c8457adbd66db88bac38f2ccd64d505 100644 --- a/ObservationSim/sim_steps/add_objects.py +++ b/observation_sim/sim_steps/add_objects.py @@ -4,8 +4,8 @@ import psutil import traceback import numpy as np import galsim -from ObservationSim._util import get_shear_field -from ObservationSim.PSF import PSFGauss, FieldDistortion, PSFInterp, PSFInterpSLS +from observation_sim._util import get_shear_field +from observation_sim.psf import PSFGauss, FieldDistortion, PSFInterp, PSFInterpSLS from astropy.time import Time from datetime import datetime, timezone diff --git a/observation_sim/sim_steps/add_pattern_noise.py b/observation_sim/sim_steps/add_pattern_noise.py new file mode 100644 index 0000000000000000000000000000000000000000..fc091c5c09b033583509bbec70d942ba39cd5cd3 --- /dev/null +++ b/observation_sim/sim_steps/add_pattern_noise.py @@ -0,0 +1,85 @@ +from numpy.random import Generator, PCG64 +from observation_sim.instruments.chip import chip_utils +from observation_sim.instruments.chip import effects + + +def apply_PRNU(self, chip, filt, tel, pointing, catalog, obs_param): + chip.img *= chip.prnu_img + if self.overall_config["output_setting"]["prnu_output"] == True: + chip.prnu_img.write("%s/FlatImg_PRNU_%s.fits" % + (self.chip_output.subdir, str(chip.chipID).rjust(2, '0'))) + return chip, filt, tel, pointing + + +def add_poisson_and_dark(self, chip, filt, tel, pointing, catalog, obs_param): + # Add dark current & Poisson noise + # Get exposure time + if (obs_param) and ("exptime" in obs_param) and (obs_param["exptime"] is not None): + exptime = obs_param["exptime"] + else: + exptime = pointing.exp_time + + if obs_param["add_dark"] == True: + chip.img, _ = chip_utils.add_poisson(img=chip.img, + chip=chip, + exptime=pointing.exp_time, + poisson_noise=chip.poisson_noise, + InputDark=None) + else: + chip.img, _ = chip_utils.add_poisson(img=chip.img, + chip=self, + exptime=exptime, + poisson_noise=chip.poisson_noise, + dark_noise=0.) + return chip, filt, tel, pointing + + +def add_detector_defects(self, chip, filt, tel, pointing, catalog, obs_param): + # Add Hot Pixels or/and Dead Pixels + rgbadpix = Generator( + PCG64(int(self.overall_config["random_seeds"]["seed_defective"]+chip.chipID))) + badfraction = 5E-5*(rgbadpix.random()*0.5+0.7) + chip.img = effects.DefectivePixels( + chip.img, + IfHotPix=obs_param["hot_pixels"], + IfDeadPix=obs_param["dead_pixels"], + fraction=badfraction, + seed=self.overall_config["random_seeds"]["seed_defective"]+chip.chipID, biaslevel=0) + # Apply Bad columns + if obs_param["bad_columns"] == True: + chip.img = effects.BadColumns(chip.img, + seed=self.overall_config["random_seeds"]["seed_badcolumns"], + chipid=chip.chipID) + return chip, filt, tel, pointing + + +def add_nonlinearity(self, chip, filt, tel, pointing, catalog, obs_param): + self.chip_output.Log_info(" Applying Non-Linearity on the chip image") + chip.img = effects.NonLinearity(GSImage=chip.img, + beta1=5.e-7, + beta2=0) + return chip, filt, tel, pointing + + +def add_blooming(self, chip, filt, tel, pointing, catalog, obs_param): + self.chip_output.Log_info(" Applying CCD Saturation & Blooming") + chip.img = effects.SaturBloom(GSImage=chip.img, + nsect_x=1, + nsect_y=1, + fullwell=int(chip.full_well)) + return chip, filt, tel, pointing + + +def add_bias(self, chip, filt, tel, pointing, catalog, obs_param): + self.chip_output.Log_info( + " Adding Bias level and 16-channel non-uniformity") + if obs_param["bias_16channel"] == True: + chip.img = effects.AddBiasNonUniform16(chip.img, + bias_level=float( + chip.bias_level), + nsecy=chip.nsecy, + nsecx=chip.nsecx, + seed=self.overall_config["random_seeds"]["seed_biasNonUniform"]+chip.chipID) + elif obs_param["bias_16channel"] == False: + chip.img += self.bias_level + return chip, filt, tel, pointing diff --git a/ObservationSim/sim_steps/add_sky_background.py b/observation_sim/sim_steps/add_sky_background.py similarity index 55% rename from ObservationSim/sim_steps/add_sky_background.py rename to observation_sim/sim_steps/add_sky_background.py index 563fad892d9d5b46f86cd5a12ab2b64dfca0308b..ab013f34b12bca3c8b88144d96bc56c548a372b4 100644 --- a/ObservationSim/sim_steps/add_sky_background.py +++ b/observation_sim/sim_steps/add_sky_background.py @@ -1,72 +1,79 @@ import numpy as np import galsim -from ObservationSim.Straylight import calculateSkyMap_split_g -from ObservationSim.Instrument import FilterParam +from observation_sim.sky_background import calculateSkyMap_split_g +from observation_sim.instruments import FilterParam from astropy.time import Time from datetime import datetime, timezone + def add_sky_background_sci(self, chip, filt, tel, pointing, catalog, obs_param): - + # Get exposure time if (obs_param) and ("exptime" in obs_param) and (obs_param["exptime"] is not None): exptime = obs_param["exptime"] else: exptime = pointing.exp_time - + flat_normal = np.ones_like(chip.img.array) if obs_param["flat_fielding"] == True: - flat_normal = flat_normal * chip.flat_img.array / np.mean(chip.flat_img.array) + flat_normal = flat_normal * chip.flat_img.array / \ + np.mean(chip.flat_img.array) if obs_param["shutter_effect"] == True: flat_normal = flat_normal * chip.shutter_img flat_normal = np.array(flat_normal, dtype='float32') - self.updateHeaderInfo(header_flag='ext', keys = ['SHTSTAT'], values = [True]) + self.updateHeaderInfo(header_flag='ext', keys=[ + 'SHTSTAT'], values=[True]) else: - self.updateHeaderInfo(header_flag='ext', keys = ['SHTSTAT','SHTOPEN1','SHTCLOS0'], values = [True,self.h_ext['SHTCLOS1'],self.h_ext['SHTOPEN0']]) - + self.updateHeaderInfo(header_flag='ext', keys=['SHTSTAT', 'SHTOPEN1', 'SHTCLOS0'], values=[ + True, self.h_ext['SHTCLOS1'], self.h_ext['SHTOPEN0']]) + if obs_param["enable_straylight_model"]: # Filter.sky_background, Filter.zodical_spec will be updated filt.setFilterStrayLightPixel( - jtime = pointing.jdt, - sat_pos = np.array([pointing.sat_x, pointing.sat_y, pointing.sat_z]), - pointing_radec = np.array([pointing.ra,pointing.dec]), - sun_pos = np.array([pointing.sun_x, pointing.sun_y, pointing.sun_z])) - self.chip_output.Log_info("================================================") - self.chip_output.Log_info("sky background + stray light pixel flux value: %.5f"%(filt.sky_background)) - + jtime=pointing.jdt, + sat_pos=np.array([pointing.sat_x, pointing.sat_y, pointing.sat_z]), + pointing_radec=np.array([pointing.ra, pointing.dec]), + sun_pos=np.array([pointing.sun_x, pointing.sun_y, pointing.sun_z])) + self.chip_output.Log_info( + "================================================") + self.chip_output.Log_info( + "sky background + stray light pixel flux value: %.5f" % (filt.sky_background)) + if chip.survey_type == "photometric": - sky_map = filt.getSkyNoise(exptime = exptime) + sky_map = filt.getSkyNoise(exptime=exptime) sky_map = sky_map * np.ones_like(chip.img.array) * flat_normal sky_map = galsim.Image(array=sky_map) else: # chip.loadSLSFLATCUBE(flat_fn='flat_cube.fits') sky_map = calculateSkyMap_split_g( - skyMap=flat_normal, - blueLimit=filt.blue_limit, - redLimit=filt.red_limit, - conf=chip.sls_conf, - pixelSize=chip.pix_scale, - isAlongY=0, - flat_cube=chip.flat_cube, - zoldial_spec = filt.zodical_spec) + skyMap=flat_normal, + blueLimit=filt.blue_limit, + redLimit=filt.red_limit, + conf=chip.sls_conf, + pixelSize=chip.pix_scale, + isAlongY=0, + flat_cube=chip.flat_cube, + zoldial_spec=filt.zodical_spec) sky_map = (sky_map + filt.sky_background)*exptime - + # sky_map = sky_map * tel.pupil_area * obs_param["exptime"] chip.img += sky_map return chip, filt, tel, pointing + def add_sky_flat_calibration(self, chip, filt, tel, pointing, catalog, obs_param): if not hasattr(self, 'h_ext'): _, _ = self.prepare_headers(chip=chip, pointing=pointing) - chip_wcs = galsim.FitsWCS(header = self.h_ext) + chip_wcs = galsim.FitsWCS(header=self.h_ext) # Get exposure time if (obs_param) and ("exptime" in obs_param) and (obs_param["exptime"] is not None): exptime = obs_param["exptime"] else: exptime = pointing.exp_time - + skyback_level = obs_param["flat_level"] filter_param = FilterParam() @@ -75,27 +82,33 @@ def add_sky_flat_calibration(self, chip, filt, tel, pointing, catalog, obs_param flat_normal = np.ones_like(chip.img.array) if obs_param["flat_fielding"] == True: - flat_normal = flat_normal * chip.flat_img.array / np.mean(chip.flat_img.array) + flat_normal = flat_normal * chip.flat_img.array / \ + np.mean(chip.flat_img.array) if obs_param["shutter_effect"] == True: flat_normal = flat_normal * chip.shutter_img flat_normal = np.array(flat_normal, dtype='float32') - if self.overall_config["output_setting"]["shutter_output"] == True: # output 16-bit shutter effect image with pixel value <=65535 + # output 16-bit shutter effect image with pixel value <=65535 + if self.overall_config["output_setting"]["shutter_output"] == True: shutt_gsimg = galsim.ImageUS(chip.shutter_img*6E4) - shutt_gsimg.write("%s/ShutterEffect_%s_1.fits" % (self.chip_output.subdir, str(chip.chipID).rjust(2, '0'))) - self.updateHeaderInfo(header_flag='ext', keys = ['SHTSTAT'], values = [True]) + shutt_gsimg.write("%s/ShutterEffect_%s_1.fits" % + (self.chip_output.subdir, str(chip.chipID).rjust(2, '0'))) + self.updateHeaderInfo(header_flag='ext', keys=[ + 'SHTSTAT'], values=[True]) else: - self.updateHeaderInfo(header_flag='ext', keys = ['SHTSTAT','SHTOPEN1','SHTCLOS0'], values = [True,self.h_ext['SHTCLOS1'],self.h_ext['SHTOPEN0']]) - + self.updateHeaderInfo(header_flag='ext', keys=['SHTSTAT', 'SHTOPEN1', 'SHTCLOS0'], values=[ + True, self.h_ext['SHTCLOS1'], self.h_ext['SHTOPEN0']]) if chip.survey_type == "photometric": - sky_map = flat_normal * np.ones_like(chip.img.array) * norm_scaler * filter_param.param[chip.filter_type][5] / tel.pupil_area * exptime + sky_map = flat_normal * np.ones_like(chip.img.array) * norm_scaler * \ + filter_param.param[chip.filter_type][5] / tel.pupil_area * exptime elif chip.survey_type == "spectroscopic": # flat_normal = np.ones_like(chip.img.array) if obs_param["flat_fielding"] == True: - - flat_normal = flat_normal * chip.flat_img.array / np.mean(chip.flat_img.array) + + flat_normal = flat_normal * chip.flat_img.array / \ + np.mean(chip.flat_img.array) if obs_param["shutter_effect"] == True: - + flat_normal = flat_normal * chip.shutter_img flat_normal = np.array(flat_normal, dtype='float32') sky_map = calculateSkyMap_split_g( @@ -107,36 +120,42 @@ def add_sky_flat_calibration(self, chip, filt, tel, pointing, catalog, obs_param isAlongY=0, flat_cube=chip.flat_cube) sky_map = sky_map * norm_scaler * exptime - + chip.img += sky_map return chip, filt, tel, pointing + def add_sky_background(self, chip, filt, tel, pointing, catalog, obs_param): if not hasattr(self, 'h_ext'): _, _ = self.prepare_headers(chip=chip, pointing=pointing) - chip_wcs = galsim.FitsWCS(header = self.h_ext) + chip_wcs = galsim.FitsWCS(header=self.h_ext) if "flat_level" not in obs_param or "flat_level_filt" not in obs_param: - chip, filt, tel, pointing = self.add_sky_background_sci(chip, filt, tel, pointing, catalog, obs_param) + chip, filt, tel, pointing = self.add_sky_background_sci( + chip, filt, tel, pointing, catalog, obs_param) else: - if obs_param.get('flat_level') is None or obs_param.get('flat_level_filt')is None: - chip, filt, tel, pointing = self.add_sky_background_sci(chip, filt, tel, pointing, catalog, obs_param) + if obs_param.get('flat_level') is None or obs_param.get('flat_level_filt') is None: + chip, filt, tel, pointing = self.add_sky_background_sci( + chip, filt, tel, pointing, catalog, obs_param) else: - chip, filt, tel, pointing = self.add_sky_flat_calibration(chip, filt, tel, pointing, catalog, obs_param) + chip, filt, tel, pointing = self.add_sky_flat_calibration( + chip, filt, tel, pointing, catalog, obs_param) # renew header info datetime_obs = datetime.utcfromtimestamp(pointing.timestamp) datetime_obs = datetime_obs.replace(tzinfo=timezone.utc) t_obs = Time(datetime_obs) - - ##ccd刷新2s,等待0.5s,开始曝光 - t_obs_renew = Time(t_obs.mjd - (2.+0.5) / 86400., format="mjd") - t_obs_utc = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(t_obs_renew.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) - self.updateHeaderInfo(header_flag='prim', keys = ['DATE-OBS'], values = [t_obs_utc.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]]) + # ccd刷新2s,等待0.5s,开始曝光 + t_obs_renew = Time(t_obs.mjd - (2.+0.5) / 86400., format="mjd") - #dark time : 曝光时间+刷新后等带时间0.5s+关闭快门时间1.5s+管快门后读出前等待0.5s - self.updateHeaderInfo(header_flag='ext', keys = ['DARKTIME'], values = [0.+0.0+0.0+pointing.exp_time]) + t_obs_utc = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp( + t_obs_renew.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) + self.updateHeaderInfo(header_flag='prim', keys=[ + 'DATE-OBS'], values=[t_obs_utc.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]]) + # dark time : 曝光时间+刷新后等带时间0.5s+关闭快门时间1.5s+管快门后读出前等待0.5s + self.updateHeaderInfo(header_flag='ext', keys=['DARKTIME'], values=[ + 0.+0.0+0.0+pointing.exp_time]) - return chip, filt, tel, pointing \ No newline at end of file + return chip, filt, tel, pointing diff --git a/observation_sim/sim_steps/prepare_headers.py b/observation_sim/sim_steps/prepare_headers.py new file mode 100644 index 0000000000000000000000000000000000000000..e8c41741710bd2c24512aa3e73a0ff7c1edf24d5 --- /dev/null +++ b/observation_sim/sim_steps/prepare_headers.py @@ -0,0 +1,52 @@ +from observation_sim.config.header import generatePrimaryHeader, generateExtensionHeader + + +def prepare_headers(self, chip, pointing): + self.h_prim = generatePrimaryHeader( + xlen=chip.npix_x, + ylen=chip.npix_y, + pointing_id=pointing.obs_id, + pointing_type_code=pointing.pointing_type_code, + ra=pointing.ra, + dec=pointing.dec, + pixel_scale=chip.pix_scale, + time_pt=pointing.timestamp, + exptime=pointing.exp_time, + im_type=pointing.pointing_type, + sat_pos=[pointing.sat_x, pointing.sat_y, pointing.sat_z], + sat_vel=[pointing.sat_vx, pointing.sat_vy, pointing.sat_vz], + project_cycle=self.overall_config["project_cycle"], + run_counter=self.overall_config["run_counter"], + chip_name=str(chip.chipID).rjust(2, '0')) + self.h_ext = generateExtensionHeader( + chip=chip, + xlen=chip.npix_x, + ylen=chip.npix_y, + ra=pointing.ra, + dec=pointing.dec, + pa=pointing.img_pa.deg, + gain=chip.gain, + readout=chip.read_noise, + dark=chip.dark_noise, + saturation=90000, + pixel_scale=chip.pix_scale, + pixel_size=chip.pix_size, + xcen=chip.x_cen, + ycen=chip.y_cen, + extName=pointing.pointing_type, + timestamp=pointing.timestamp, + exptime=pointing.exp_time, + readoutTime=chip.readout_time, + t_shutter_open=pointing.t_shutter_open, + t_shutter_close=pointing.t_shutter_close) + + return self.h_prim, self.h_ext + + +def updateHeaderInfo(self, header_flag='prim', keys=['key'], values=[0]): + if header_flag == 'prim': + for key, value in zip(keys, values): + self.h_prim[key] = value + if header_flag == 'ext': + for key, value in zip(keys, values): + self.h_ext[key] = value diff --git a/ObservationSim/sim_steps/readout_output.py b/observation_sim/sim_steps/readout_output.py similarity index 57% rename from ObservationSim/sim_steps/readout_output.py rename to observation_sim/sim_steps/readout_output.py index 080baeda5b20298a31bdbe0931e7f5a63d2b8161..8ef872fd6d9348f3f46491486010fa41af935c6f 100644 --- a/ObservationSim/sim_steps/readout_output.py +++ b/observation_sim/sim_steps/readout_output.py @@ -2,66 +2,76 @@ import os import galsim import numpy as np from astropy.io import fits -from ObservationSim.Instrument.Chip import ChipUtils as chip_utils -from ObservationSim.Instrument.Chip import Effects +from observation_sim.instruments.chip import chip_utils +from observation_sim.instruments.chip import effects from astropy.time import Time from datetime import datetime, timezone + def add_prescan_overscan(self, chip, filt, tel, pointing, catalog, obs_param): self.chip_output.Log_info("Apply pre/over-scan") chip.img = chip_utils.AddPreScan(GSImage=chip.img, - pre1=chip.prescan_x, - pre2=chip.prescan_y, - over1=chip.overscan_x, - over2=chip.overscan_y) + pre1=chip.prescan_x, + pre2=chip.prescan_y, + over1=chip.overscan_x, + over2=chip.overscan_y) if obs_param["add_dark"] == True: ny = int(chip.npix_y/2) base_dark = (ny-1)*(chip.readout_time/ny)*chip.dark_noise - chip.img.array[(chip.prescan_y+ny):-(chip.prescan_y+ny),:] = base_dark + chip.img.array[(chip.prescan_y+ny):-(chip.prescan_y+ny), :] = base_dark return chip, filt, tel, pointing + def add_readout_noise(self, chip, filt, tel, pointing, catalog, obs_param): - seed = int(self.overall_config["random_seeds"]["seed_readout"]) + pointing.id*30 + chip.chipID + seed = int(self.overall_config["random_seeds"] + ["seed_readout"]) + pointing.id*30 + chip.chipID rng_readout = galsim.BaseDeviate(seed) - readout_noise = galsim.GaussianNoise(rng=rng_readout, sigma=chip.read_noise) + readout_noise = galsim.GaussianNoise( + rng=rng_readout, sigma=chip.read_noise) chip.img.addNoise(readout_noise) return chip, filt, tel, pointing + def apply_gain(self, chip, filt, tel, pointing, catalog, obs_param): self.chip_output.Log_info(" Applying Gain") if obs_param["gain_16channel"] == True: - chip.img, chip.gain_channel = Effects.ApplyGainNonUniform16(chip.img, - gain=chip.gain, - nsecy = chip.nsecy, - nsecx=chip.nsecx, - seed=self.overall_config["random_seeds"]["seed_gainNonUniform"]+chip.chipID) + chip.img, chip.gain_channel = effects.ApplyGainNonUniform16(chip.img, + gain=chip.gain, + nsecy=chip.nsecy, + nsecx=chip.nsecx, + seed=self.overall_config["random_seeds"]["seed_gainNonUniform"]+chip.chipID) elif obs_param["gain_16channel"] == False: chip.img /= chip.gain return chip, filt, tel, pointing + def quantization_and_output(self, chip, filt, tel, pointing, catalog, obs_param): if not hasattr(self, 'h_ext'): _, _ = self.prepare_headers(chip=chip, pointing=pointing) - self.updateHeaderInfo(header_flag='ext', keys = ['SHTSTAT','SHTOPEN1','SHTCLOS0','SHTCLOS1','EXPTIME'], values = [False,self.h_ext['SHTOPEN0'],self.h_ext['SHTOPEN0'],self.h_ext['SHTOPEN0'],0.0]) + self.updateHeaderInfo(header_flag='ext', keys=['SHTSTAT', 'SHTOPEN1', 'SHTCLOS0', 'SHTCLOS1', 'EXPTIME'], values=[ + False, self.h_ext['SHTOPEN0'], self.h_ext['SHTOPEN0'], self.h_ext['SHTOPEN0'], 0.0]) # renew header info datetime_obs = datetime.utcfromtimestamp(pointing.timestamp) datetime_obs = datetime_obs.replace(tzinfo=timezone.utc) t_obs = Time(datetime_obs) - - ##ccd刷新2s,等待0.5s,开灯后等待0.5s,开始曝光 + + # ccd刷新2s,等待0.5s,开灯后等待0.5s,开始曝光 t_obs_renew = Time(t_obs.mjd - 2. / 86400., format="mjd") - t_obs_utc = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp(t_obs_renew.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) - self.updateHeaderInfo(header_flag='prim', keys = ['DATE-OBS'], values = [t_obs_utc.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]]) - + t_obs_utc = datetime.utcfromtimestamp(np.round(datetime.utcfromtimestamp( + t_obs_renew.unix).replace(tzinfo=timezone.utc).timestamp(), 1)) + self.updateHeaderInfo(header_flag='prim', keys=[ + 'DATE-OBS'], values=[t_obs_utc.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5]]) + gains1 = list(chip.gain_channel[0:8]) gains2 = list(chip.gain_channel[8:]) gains2.reverse() - gains = np.append(gains1,gains2) - self.updateHeaderInfo(header_flag='ext', keys = ['GAIN01','GAIN02','GAIN03','GAIN04','GAIN05','GAIN06','GAIN07','GAIN08','GAIN09','GAIN10','GAIN11','GAIN12','GAIN13','GAIN14','GAIN15','GAIN16'], values = gains) + gains = np.append(gains1, gains2) + self.updateHeaderInfo(header_flag='ext', keys=['GAIN01', 'GAIN02', 'GAIN03', 'GAIN04', 'GAIN05', 'GAIN06', 'GAIN07', + 'GAIN08', 'GAIN09', 'GAIN10', 'GAIN11', 'GAIN12', 'GAIN13', 'GAIN14', 'GAIN15', 'GAIN16'], values=gains) if obs_param["format_output"] == True: self.chip_output.Log_info(" Apply 1*16 format") @@ -73,20 +83,21 @@ def quantization_and_output(self, chip, filt, tel, pointing, catalog, obs_param) chip.img.replaceNegative(replace_value=0) chip.img.quantize() chip.img = galsim.Image(chip.img.array, dtype=np.uint16) - fname = os.path.join(self.chip_output.subdir, self.h_prim['FILENAME'] + '.fits') + fname = os.path.join(self.chip_output.subdir, + self.h_prim['FILENAME'] + '.fits') f_name_size = 68 - if(len(self.h_prim['FILENAME'])>f_name_size): - self.updateHeaderInfo(header_flag='prim', keys = ['FILENAME'], values = [self.h_prim['FILENAME'][0:f_name_size]]) - - - + if (len(self.h_prim['FILENAME']) > f_name_size): + self.updateHeaderInfo(header_flag='prim', keys=['FILENAME'], values=[ + self.h_prim['FILENAME'][0:f_name_size]]) + hdu1 = fits.PrimaryHDU(header=self.h_prim) - - self.updateHeaderInfo(header_flag='ext', keys = ['DATASECT'], values = [str(chip.img.array.shape[1]) + 'x' + str(chip.img.array.shape[0])]) + + self.updateHeaderInfo(header_flag='ext', keys=['DATASECT'], values=[ + str(chip.img.array.shape[1]) + 'x' + str(chip.img.array.shape[0])]) hdu2 = fits.ImageHDU(chip.img.array, header=self.h_ext) hdu2.header.comments["XTENSION"] = "image extension" - + hdu = fits.HDUList([hdu1, hdu2]) hdu[0].add_datasum(when='data unit checksum') hdu[0].add_checksum(when='HDU checksum', override_datasum=True) diff --git a/ObservationSim/Straylight/SkybackgroundMap.py b/observation_sim/sky_background/SkybackgroundMap.py similarity index 78% rename from ObservationSim/Straylight/SkybackgroundMap.py rename to observation_sim/sky_background/SkybackgroundMap.py index 2b4e204bf77d5f2783bc193e08dccf66042646b5..1532784be4382ceb057c086b587d60fdbd46547e 100644 --- a/ObservationSim/Straylight/SkybackgroundMap.py +++ b/observation_sim/sky_background/SkybackgroundMap.py @@ -1,5 +1,5 @@ -from ObservationSim.MockObject.SpecDisperser import SpecDisperser -from ObservationSim.MockObject.SpecDisperser import rotate90 +from observation_sim.mock_objects.SpecDisperser import SpecDisperser +from observation_sim.mock_objects.SpecDisperser import rotate90 import galsim import numpy as np @@ -20,10 +20,10 @@ except ImportError: import importlib_resources as pkg_resources -###calculate sky map by sky SED +# calculate sky map by sky SED def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='sky_emiss_hubble_50_50_A.dat', conf=[''], pixelSize=0.074, isAlongY=0, - split_pos=3685, flat_cube = None, zoldial_spec = None): + split_pos=3685, flat_cube=None, zoldial_spec=None): # skyMap = np.ones([yLen, xLen], dtype='float32') # # if isAlongY == 1: @@ -45,19 +45,21 @@ def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='s fImg = galsim.Image(fimg) try: - with pkg_resources.files('ObservationSim.Straylight.data.sky').joinpath(skyfn) as data_path: + with pkg_resources.files('observation_sim.sky_background.data.sky').joinpath(skyfn) as data_path: skySpec = np.loadtxt(data_path) except AttributeError: - with pkg_resources.path('ObservationSim.Straylight.data.sky', skyfn) as data_path: + with pkg_resources.path('observation_sim.sky_background.data.sky', skyfn) as data_path: skySpec = np.loadtxt(data_path) # skySpec = np.loadtxt(skyfn) - spec = Table(np.array([skySpec[:, 0], skySpec[:, 1]]).T, names=('WAVELENGTH', 'FLUX')) + spec = Table(np.array([skySpec[:, 0], skySpec[:, 1]] + ).T, names=('WAVELENGTH', 'FLUX')) if zoldial_spec is not None: deltL = 0.5 lamb = np.arange(2000, 11000, deltL) - speci = interpolate.interp1d(zoldial_spec['WAVELENGTH'], zoldial_spec['FLUX']) + speci = interpolate.interp1d( + zoldial_spec['WAVELENGTH'], zoldial_spec['FLUX']) y = speci(lamb) # erg/s/cm2/A --> photo/s/m2/A @@ -65,7 +67,7 @@ def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='s spec = Table(np.array([lamb, s_flux]).T, names=('WAVELENGTH', 'FLUX')) if isAlongY == 0: directParm = 0 - if isAlongY ==1: + if isAlongY == 1: directParm = 1 if split_pos >= skyImg.array.shape[directParm]: @@ -90,25 +92,26 @@ def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='s sub_x_end_arr = sub_x_start_arr + delt_x sub_x_end_arr[-1] = min(sub_x_end_arr[-1], x_len) - for i,k1 in enumerate(sub_y_start_arr): + for i, k1 in enumerate(sub_y_start_arr): sub_y_s = k1 sub_y_e = sub_y_end_arr[i] sub_y_center = (sub_y_s+sub_y_e)/2. - for j,k2 in enumerate(sub_x_start_arr): + for j, k2 in enumerate(sub_x_start_arr): sub_x_s = k2 sub_x_e = sub_x_end_arr[j] - skyImg_sub = galsim.Image(skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e]) + skyImg_sub = galsim.Image( + skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e]) origin_sub = [sub_y_s, sub_x_s] sub_x_center = (sub_x_s + sub_x_e) / 2. sdp = SpecDisperser(orig_img=skyImg_sub, xcenter=sub_x_center, ycenter=sub_y_center, origin=origin_sub, - tar_spec=spec, - band_start=tbstart, band_end=tbend, - conf=conf2, - flat_cube=flat_cube, ignoreBeam=['D','E']) + tar_spec=spec, + band_start=tbstart, band_end=tbend, + conf=conf2, + flat_cube=flat_cube, ignoreBeam=['D', 'E']) spec_orders = sdp.compute_spec_orders() @@ -141,9 +144,7 @@ def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='s # if bounds.area() == 0: # continue # fImg[bounds] = fImg[bounds] + ssImg[bounds] - - else: # skyImg1 = galsim.Image(skyImg.array[:, 0:split_pos]) @@ -165,32 +166,33 @@ def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='s sub_y_start_arr = np.arange(0, y_len, delt_y) sub_y_end_arr = sub_y_start_arr + delt_y sub_y_end_arr[-1] = min(sub_y_end_arr[-1], y_len) - + delt_x = split_pos-0 sub_x_start_arr = np.arange(0, split_pos, delt_x) sub_x_end_arr = sub_x_start_arr + delt_x sub_x_end_arr[-1] = min(sub_x_end_arr[-1], split_pos) - for i,k1 in enumerate(sub_y_start_arr): + for i, k1 in enumerate(sub_y_start_arr): sub_y_s = k1 sub_y_e = sub_y_end_arr[i] sub_y_center = (sub_y_s+sub_y_e)/2. - for j,k2 in enumerate(sub_x_start_arr): + for j, k2 in enumerate(sub_x_start_arr): sub_x_s = k2 sub_x_e = sub_x_end_arr[j] # print(i,j,sub_y_s, sub_y_e,sub_x_s,sub_x_e) T1 = time.time() - skyImg_sub = galsim.Image(skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e]) + skyImg_sub = galsim.Image( + skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e]) origin_sub = [sub_y_s, sub_x_s] sub_x_center = (sub_x_s + sub_x_e) / 2. sdp = SpecDisperser(orig_img=skyImg_sub, xcenter=sub_x_center, ycenter=sub_y_center, origin=origin_sub, - tar_spec=spec, - band_start=tbstart, band_end=tbend, - conf=conf1, - flat_cube=flat_cube) + tar_spec=spec, + band_start=tbstart, band_end=tbend, + conf=conf1, + flat_cube=flat_cube) spec_orders = sdp.compute_spec_orders() @@ -204,10 +206,10 @@ def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='s if bounds.area() == 0: continue fImg[bounds] = fImg[bounds] + ssImg[bounds] - + T2 = time.time() - print('time: %s ms'% ((T2 - T1)*1000)) + print('time: %s ms' % ((T2 - T1)*1000)) delt_x = x_len-split_pos sub_x_start_arr = np.arange(split_pos, x_len, delt_x) @@ -224,18 +226,19 @@ def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='s sub_x_s = k2 sub_x_e = sub_x_end_arr[j] # print(i,j,sub_y_s, sub_y_e,sub_x_s,sub_x_e) - + T1 = time.time() - skyImg_sub = galsim.Image(skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e]) + skyImg_sub = galsim.Image( + skyImg.array[sub_y_s:sub_y_e, sub_x_s:sub_x_e]) origin_sub = [sub_y_s, sub_x_s] sub_x_center = (sub_x_s + sub_x_e) / 2. sdp = SpecDisperser(orig_img=skyImg_sub, xcenter=sub_x_center, ycenter=sub_y_center, origin=origin_sub, - tar_spec=spec, - band_start=tbstart, band_end=tbend, - conf=conf2, - flat_cube=flat_cube) + tar_spec=spec, + band_start=tbstart, band_end=tbend, + conf=conf2, + flat_cube=flat_cube) spec_orders = sdp.compute_spec_orders() @@ -251,17 +254,19 @@ def calculateSkyMap_split_g(skyMap=None, blueLimit=4200, redLimit=6500, skyfn='s fImg[bounds] = fImg[bounds] + ssImg[bounds] T2 = time.time() - print('time: %s ms'% ((T2 - T1)*1000)) + print('time: %s ms' % ((T2 - T1)*1000)) if isAlongY == 1: - fimg, tmx, tmy = rotate90(array_orig=fImg.array, xc=0, yc=0, isClockwise=0) + fimg, tmx, tmy = rotate90( + array_orig=fImg.array, xc=0, yc=0, isClockwise=0) else: fimg = fImg.array fimg = fimg * pixelSize * pixelSize return fimg - + + def calculateSkyMap(xLen=9232, yLen=9126, blueLimit=4200, redLimit=6500, skyfn='sky_emiss_hubble_50_50_A.dat', conf='', pixelSize=0.074, isAlongY=0): skyMap = np.ones([yLen, xLen], dtype='float32') @@ -277,14 +282,15 @@ def calculateSkyMap(xLen=9232, yLen=9126, blueLimit=4200, redLimit=6500, fimg = np.zeros_like(skyMap) fImg = galsim.Image(fimg) try: - with pkg_resources.files('ObservationSim.Straylight.data.sky').joinpath(skyfn) as data_path: + with pkg_resources.files('observation_sim.sky_background.data.sky').joinpath(skyfn) as data_path: skySpec = np.loadtxt(data_path) except AttributeError: - with pkg_resources.path('ObservationSim.Straylight.data.sky', skyfn) as data_path: + with pkg_resources.path('observation_sim.sky_background.data.sky', skyfn) as data_path: skySpec = np.loadtxt(data_path) # skySpec = np.loadtxt(skyfn) - - spec = Table(np.array([skySpec[:, 0], skySpec[:, 1]]).T, names=('WAVELENGTH', 'FLUX')) + + spec = Table(np.array([skySpec[:, 0], skySpec[:, 1]] + ).T, names=('WAVELENGTH', 'FLUX')) sdp = SpecDisperser(orig_img=skyImg, xcenter=skyImg.center.x, ycenter=skyImg.center.y, origin=[1, 1], tar_spec=spec, @@ -303,10 +309,11 @@ def calculateSkyMap(xLen=9232, yLen=9126, blueLimit=4200, redLimit=6500, fImg[bounds] = fImg[bounds] + ssImg[bounds] if isAlongY == 1: - fimg, tmx, tmy = rotate90(array_orig=fImg.array, xc=0, yc=0, isClockwise=0) + fimg, tmx, tmy = rotate90( + array_orig=fImg.array, xc=0, yc=0, isClockwise=0) else: fimg = fImg.array - + fimg = fimg * pixelSize * pixelSize return fimg diff --git a/ObservationSim/Straylight/Straylight.py b/observation_sim/sky_background/Straylight.py similarity index 55% rename from ObservationSim/Straylight/Straylight.py rename to observation_sim/sky_background/Straylight.py index 189fe40f79a9f4c2bf1a29386c56db9138ba9f05..d461e79424707b7fea424f0ca24627fce03f7a14 100644 --- a/ObservationSim/Straylight/Straylight.py +++ b/observation_sim/sky_background/Straylight.py @@ -15,270 +15,291 @@ except ImportError: # Try backported to PY<37 'importlib_resources' import importlib_resources as pkg_resources -filterPivotWave = {'nuv':2875.5,'u':3629.6,'g':4808.4,'r':6178.2, 'i':7609.0, 'z':9012.9,'y':9627.9} -filterIndex = {'nuv':0,'u':1,'g':2,'r':3, 'i':4, 'z':5,'y':6} -filterCCD = {'nuv':'UV0','u':'UV0','g':'Astro_MB','r':'Astro_MB', 'i':'Basic_NIR', 'z':'Basic_NIR','y':'Basic_NIR'} -bandRange = {'nuv':[2504.0,3230.0],'u':[3190.0,4039.0],'g':[3989.0,5498.0],'r':[5438.0,6956.0], 'i':[6886.0,8469.0], 'z':[8379.0,10855.0],'y':[9217.0, 10900.0], 'GU':[2550, 4000],'GV':[4000, 6200],'GI':[6200,10000]} +filterPivotWave = {'nuv': 2875.5, 'u': 3629.6, 'g': 4808.4, + 'r': 6178.2, 'i': 7609.0, 'z': 9012.9, 'y': 9627.9} +filterIndex = {'nuv': 0, 'u': 1, 'g': 2, 'r': 3, 'i': 4, 'z': 5, 'y': 6} +filterCCD = {'nuv': 'UV0', 'u': 'UV0', 'g': 'Astro_MB', + 'r': 'Astro_MB', 'i': 'Basic_NIR', 'z': 'Basic_NIR', 'y': 'Basic_NIR'} +bandRange = {'nuv': [2504.0, 3230.0], 'u': [3190.0, 4039.0], 'g': [3989.0, 5498.0], 'r': [5438.0, 6956.0], 'i': [ + 6886.0, 8469.0], 'z': [8379.0, 10855.0], 'y': [9217.0, 10900.0], 'GU': [2550, 4000], 'GV': [4000, 6200], 'GI': [6200, 10000]} # Instrument_dir = '/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_C6/straylight/straylight/Instrument/' -SpecOrder = ['-2','-1','0','1','2'] +SpecOrder = ['-2', '-1', '0', '1', '2'] + +filterMirrorEff = {'nuv': 0.54, 'u': 0.68, 'g': 0.8, + 'r': 0.8, 'i': 0.8, 'z': 0.8, 'y': 0.8} -filterMirrorEff = {'nuv':0.54,'u':0.68,'g':0.8,'r':0.8, 'i':0.8, 'z':0.8,'y':0.8} def transRaDec2D(ra, dec): - x1 = np.cos(dec / 57.2957795) * np.cos(ra / 57.2957795); - y1 = np.cos(dec / 57.2957795) * np.sin(ra / 57.2957795); - z1 = np.sin(dec / 57.2957795); + x1 = np.cos(dec / 57.2957795) * np.cos(ra / 57.2957795) + y1 = np.cos(dec / 57.2957795) * np.sin(ra / 57.2957795) + z1 = np.sin(dec / 57.2957795) return np.array([x1, y1, z1]) -def getAngle132(x1 = 0, y1 = 0, z1 = 0, x2 = 0, y2 = 0, z2 = 0, x3 = 0, y3 = 0, z3 = 0): - - cosValue = 0; - angle = 0; - - x11 = x1-x3; - y11 = y1-y3; - z11 = z1-z3; - - x22 = x2-x3; - y22 = y2-y3; - z22 = z2-z3; - - tt = np.sqrt((x11*x11 + y11*y11 + z11* z11) * (x22*x22 + y22*y22 + z22*z22)); - if(tt==0): - return 0; - - cosValue = (x11*x22+y11*y22+z11*z22)/tt; - - if (cosValue > 1): - cosValue = 1; - if (cosValue < -1): - cosValue = -1; - angle = math.acos(cosValue); - return angle * 360 / (2 * math.pi); - -def calculateAnglePwithEarth(sat = np.array([0,0,0]), pointing = np.array([0,0,0]), sun = np.array([0,0,0])): + +def getAngle132(x1=0, y1=0, z1=0, x2=0, y2=0, z2=0, x3=0, y3=0, z3=0): + + cosValue = 0 + angle = 0 + + x11 = x1-x3 + y11 = y1-y3 + z11 = z1-z3 + + x22 = x2-x3 + y22 = y2-y3 + z22 = z2-z3 + + tt = np.sqrt((x11*x11 + y11*y11 + z11 * z11) + * (x22*x22 + y22*y22 + z22*z22)) + if (tt == 0): + return 0 + + cosValue = (x11*x22+y11*y22+z11*z22)/tt + + if (cosValue > 1): + cosValue = 1 + if (cosValue < -1): + cosValue = -1 + angle = math.acos(cosValue) + return angle * 360 / (2 * math.pi) + + +def calculateAnglePwithEarth(sat=np.array([0, 0, 0]), pointing=np.array([0, 0, 0]), sun=np.array([0, 0, 0])): modSat = np.sqrt(sat[0]*sat[0] + sat[1]*sat[1]+sat[2]*sat[2]) - modPoint = np.sqrt(pointing[0]*pointing[0] + pointing[1]*pointing[1] + pointing[2]*pointing[2]) - withLocalZenithAngle = (pointing[0] * sat[0] + pointing[1] * sat[1] + pointing[2] * sat[2]) / (modPoint*modSat) + modPoint = np.sqrt(pointing[0]*pointing[0] + + pointing[1]*pointing[1] + pointing[2]*pointing[2]) + withLocalZenithAngle = ( + pointing[0] * sat[0] + pointing[1] * sat[1] + pointing[2] * sat[2]) / (modPoint*modSat) innerM_sat_sun = sat[0] * sun[0] + sat[1] * sun[1] + sat[2] * sun[2] cosAngle = innerM_sat_sun / (modSat * cons.au.value/1000) isInSunSide = 1 - if (cosAngle < -0.3385737): #cos109.79 - isInSunSide = -1; + if (cosAngle < -0.3385737): # cos109.79 + isInSunSide = -1 elif cosAngle >= -0.3385737 and cosAngle <= 0.3385737: - isInSunSide = 0; + isInSunSide = 0 - return math.acos(withLocalZenithAngle)*180/math.pi,isInSunSide + return math.acos(withLocalZenithAngle)*180/math.pi, isInSunSide # /** # * *eCoor = ra, *eCoor+1 = dec # */ -def Cartesian2Equatorial(carCoor = np.array([0,0,0])): +def Cartesian2Equatorial(carCoor=np.array([0, 0, 0])): eCoor = np.zeros(2) if (carCoor[0] > 0 and carCoor[1] >= 0): eCoor[0] = math.atan(carCoor[1] / carCoor[0]) * 360 / (2 * math.pi) elif (carCoor[0] < 0): - eCoor[0] = (math.atan(carCoor[1] / carCoor[0]) + math.pi) * 360 / (2 * math.pi) + eCoor[0] = (math.atan(carCoor[1] / carCoor[0]) + + math.pi) * 360 / (2 * math.pi) elif (carCoor[0] > 0 and carCoor[1] < 0): - eCoor[0] = (math.atan(carCoor[1] / carCoor[0]) + 2 * math.pi) * 360 / (2 * math.pi) + eCoor[0] = (math.atan(carCoor[1] / carCoor[0]) + + 2 * math.pi) * 360 / (2 * math.pi) elif (carCoor[0] == 0 and carCoor[1] < 0): eCoor[0] = 270 elif (carCoor[0] == 0 and carCoor[1] > 0): eCoor[0] = 90 - eCoor[1] = math.atan(carCoor[2] / np.sqrt(carCoor[0] * carCoor[0] + carCoor[1] * carCoor[1])) * 360 / (2 * math.pi) + eCoor[1] = math.atan(carCoor[2] / np.sqrt(carCoor[0] * + carCoor[0] + carCoor[1] * carCoor[1])) * 360 / (2 * math.pi) return eCoor - class Straylight(object): - def __init__(self, jtime = 2460843., sat_pos = np.array([0,0,0]), pointing_radec = np.array([0,0]), sun_pos = np.array([0,0,0])): + def __init__(self, jtime=2460843., sat_pos=np.array([0, 0, 0]), pointing_radec=np.array([0, 0]), sun_pos=np.array([0, 0, 0])): self.jtime = jtime self.sat = sat_pos self.sun_pos = sun_pos - self.equator = coord.SkyCoord(pointing_radec[0]*u.degree, pointing_radec[1]*u.degree,frame='icrs') + self.equator = coord.SkyCoord( + pointing_radec[0]*u.degree, pointing_radec[1]*u.degree, frame='icrs') self.ecliptic = self.equator.transform_to('barycentrictrueecliptic') self.pointing = transRaDec2D(pointing_radec[0], pointing_radec[1]) platForm = sys.platform if platForm == 'darwin': try: - with pkg_resources.files('ObservationSim.Straylight.lib').joinpath('libstraylight.dylib') as dllFn: + with pkg_resources.files('observation_sim.sky_background.lib').joinpath('libstraylight.dylib') as dllFn: self.slcdll = ctypes.CDLL(dllFn) except AttributeError: - with pkg_resources.path('ObservationSim.Straylight.lib', 'libstraylight.dylib') as dllFn: + with pkg_resources.path('observation_sim.sky_background.lib', 'libstraylight.dylib') as dllFn: self.slcdll = ctypes.CDLL(dllFn) elif platForm == 'linux': try: - with pkg_resources.files('ObservationSim.Straylight.lib').joinpath('libstraylight.so') as dllFn: + with pkg_resources.files('observation_sim.sky_background.lib').joinpath('libstraylight.so') as dllFn: self.slcdll = ctypes.CDLL(dllFn) except AttributeError: - with pkg_resources.path('ObservationSim.Straylight.lib', 'libstraylight.so') as dllFn: + with pkg_resources.path('observation_sim.sky_background.lib', 'libstraylight.so') as dllFn: self.slcdll = ctypes.CDLL(dllFn) # self.slcdll=ctypes.CDLL('./libstraylight.dylib') self.slcdll.Calculate.argtypes = [ctypes.c_double, ctypes.POINTER(ctypes.c_double), - ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), + ctypes.POINTER(ctypes.c_double), ctypes.POINTER( + ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_char_p] self.slcdll.PointSource.argtypes = [ctypes.c_double, ctypes.POINTER(ctypes.c_double), - ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), + ctypes.POINTER(ctypes.c_double), ctypes.POINTER( + ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_char_p] self.slcdll.EarthShine.argtypes = [ctypes.c_double, ctypes.POINTER(ctypes.c_double), - ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), + ctypes.POINTER(ctypes.c_double), ctypes.POINTER( + ctypes.c_double), ctypes.POINTER(ctypes.c_double)] self.slcdll.Zodiacal.argtypes = [ctypes.c_double, ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double)] self.slcdll.ComposeY.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double)] - self.slcdll.Init.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p] + self.slcdll.Init.argtypes = [ + ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p] try: - with pkg_resources.files('ObservationSim.Straylight.lib').joinpath('DE405') as tFn: + with pkg_resources.files('observation_sim.sky_background.lib').joinpath('DE405') as tFn: self.deFn = tFn.as_uri()[7:] except AttributeError: - with pkg_resources.path('ObservationSim.Straylight.lib', 'DE405') as tFn: + with pkg_resources.path('observation_sim.sky_background.lib', 'DE405') as tFn: self.deFn = tFn.as_uri()[7:] try: - with pkg_resources.files('ObservationSim.Straylight.lib').joinpath('PST') as tFn: + with pkg_resources.files('observation_sim.sky_background.lib').joinpath('PST') as tFn: self.PSTFn = tFn.as_uri()[7:] except AttributeError: - with pkg_resources.path('ObservationSim.Straylight.lib', 'PST') as tFn: + with pkg_resources.path('observation_sim.sky_background.lib', 'PST') as tFn: self.PSTFn = tFn.as_uri()[7:] try: - with pkg_resources.files('ObservationSim.Straylight.lib').joinpath('R') as tFn: + with pkg_resources.files('observation_sim.sky_background.lib').joinpath('R') as tFn: self.RFn = tFn.as_uri()[7:] except AttributeError: - with pkg_resources.path('ObservationSim.Straylight.lib', 'R') as tFn: + with pkg_resources.path('observation_sim.sky_background.lib', 'R') as tFn: self.RFn = tFn.as_uri()[7:] try: - with pkg_resources.files('ObservationSim.Straylight.lib').joinpath('Zodiacal') as tFn: + with pkg_resources.files('observation_sim.sky_background.lib').joinpath('Zodiacal') as tFn: self.ZolFn = tFn.as_uri()[7:] except AttributeError: - with pkg_resources.path('ObservationSim.Straylight.lib', 'Zodiacal') as tFn: + with pkg_resources.path('observation_sim.sky_background.lib', 'Zodiacal') as tFn: self.ZolFn = tFn.as_uri()[7:] try: - with pkg_resources.files('ObservationSim.Straylight.lib').joinpath('BrightGaia_with_csst_mag') as tFn: + with pkg_resources.files('observation_sim.sky_background.lib').joinpath('BrightGaia_with_csst_mag') as tFn: self.brightStarTabFn = tFn.as_uri()[7:] except AttributeError: - with pkg_resources.path('ObservationSim.Straylight.lib', 'BrightGaia_with_csst_mag') as tFn: + with pkg_resources.path('observation_sim.sky_background.lib', 'BrightGaia_with_csst_mag') as tFn: self.brightStarTabFn = tFn.as_uri()[7:] print(self.deFn) - self.slcdll.Init(str.encode(self.deFn), str.encode(self.PSTFn), str.encode(self.RFn), str.encode(self.ZolFn)) + self.slcdll.Init(str.encode(self.deFn), str.encode( + self.PSTFn), str.encode(self.RFn), str.encode(self.ZolFn)) - def getFilterAndCCD_Q(self, filter = 'i'): + def getFilterAndCCD_Q(self, filter='i'): try: - with pkg_resources.files('ObservationSim.Instrument.data.ccd').joinpath(filterCCD[filter] + '.txt') as ccd_fn: + with pkg_resources.files('observation_sim.instruments.data.ccd').joinpath(filterCCD[filter] + '.txt') as ccd_fn: q_ccd_f = np.loadtxt(ccd_fn) except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data.ccd', filterCCD[filter] + '.txt') as ccd_fn: + with pkg_resources.path('observation_sim.instruments.data.ccd', filterCCD[filter] + '.txt') as ccd_fn: q_ccd_f = np.loadtxt(ccd_fn) try: - with pkg_resources.files('ObservationSim.Instrument.data.filters').joinpath(filter + '.txt') as filter_fn: + with pkg_resources.files('observation_sim.instruments.data.filters').joinpath(filter + '.txt') as filter_fn: q_fil_f = np.loadtxt(filter_fn) except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data.filters', filter + '.txt') as filter_fn: + with pkg_resources.path('observation_sim.instruments.data.filters', filter + '.txt') as filter_fn: q_fil_f = np.loadtxt(filter_fn) band_s = 2000 band_e = 11000 - q_ccd_f[:,0] = q_ccd_f[:,0]*10 - q_ccd = np.zeros([q_ccd_f.shape[0]+2,q_ccd_f.shape[1]]) - q_ccd[1:-1,:] = q_ccd_f - q_ccd[0] = [band_s,0] - q_ccd[-1] = [band_e,0] - - q_fil = np.zeros([q_fil_f.shape[0]+2,q_fil_f.shape[1]]) - q_fil[1:-1,:] = q_fil_f - q_fil[0] = [band_s,0] - q_fil[-1] = [band_e,0] - - - q_fil_i = interpolate.interp1d(q_fil[:,0], q_fil[:,1]) - q_ccd_i = interpolate.interp1d(q_ccd[:,0], q_ccd[:,1]) - bands = np.arange(bandRange[filter][0], bandRange[filter][1],0.5) + q_ccd_f[:, 0] = q_ccd_f[:, 0]*10 + q_ccd = np.zeros([q_ccd_f.shape[0]+2, q_ccd_f.shape[1]]) + q_ccd[1:-1, :] = q_ccd_f + q_ccd[0] = [band_s, 0] + q_ccd[-1] = [band_e, 0] + + q_fil = np.zeros([q_fil_f.shape[0]+2, q_fil_f.shape[1]]) + q_fil[1:-1, :] = q_fil_f + q_fil[0] = [band_s, 0] + q_fil[-1] = [band_e, 0] + + q_fil_i = interpolate.interp1d(q_fil[:, 0], q_fil[:, 1]) + q_ccd_i = interpolate.interp1d(q_ccd[:, 0], q_ccd[:, 1]) + bands = np.arange(bandRange[filter][0], bandRange[filter][1], 0.5) q_ccd_fil = q_fil_i(bands)*q_ccd_i(bands) - + return np.trapz(q_ccd_fil, bands)/(bandRange[filter][1]-bandRange[filter][0]) - - def calculateEarthShineFilter(self, filter = 'i', pixel_size_phy = 10 ): + + def calculateEarthShineFilter(self, filter='i', pixel_size_phy=10): sat = (ctypes.c_double*3)() sat[:] = self.sat ob = (ctypes.c_double*3)() - ob[:]=self.pointing - - + ob[:] = self.pointing + py1 = (ctypes.c_double*3)() py2 = (ctypes.c_double*3)() - self.slcdll.ComposeY(ob,py1,py2) - + self.slcdll.ComposeY(ob, py1, py2) earth_e1 = (ctypes.c_double*7)() - self.slcdll.EarthShine(self.jtime,sat,ob,py1,earth_e1) + self.slcdll.EarthShine(self.jtime, sat, ob, py1, earth_e1) earth_e2 = (ctypes.c_double*7)() - self.slcdll.EarthShine(self.jtime,sat,ob,py2,earth_e2) - + self.slcdll.EarthShine(self.jtime, sat, ob, py2, earth_e2) + band_earth_e1 = earth_e1[:][filterIndex[filter]] band_earth_e2 = earth_e2[:][filterIndex[filter]] - - q=self.getFilterAndCCD_Q(filter=filter) + + q = self.getFilterAndCCD_Q(filter=filter) p_lambda = filterPivotWave[filter] c = cons.c.value h = cons.h.value - pix_earth_e1 = band_earth_e1/(h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q - pix_earth_e2 = band_earth_e2/(h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q + pix_earth_e1 = band_earth_e1 / \ + (h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q + pix_earth_e2 = band_earth_e2 / \ + (h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q - if pix_earth_e1< pix_earth_e2: + if pix_earth_e1 < pix_earth_e2: return pix_earth_e1, py1[:] else: return pix_earth_e2, py2[:] - + """ calculate zodiacal call c++ program, seems to have some problem """ - def calculateZodiacalFilter1(self, filter = 'i', pixel_size_phy = 10 ): + + def calculateZodiacalFilter1(self, filter='i', pixel_size_phy=10): sat = (ctypes.c_double*3)() sat[:] = self.sat ob = (ctypes.c_double*3)() - ob[:]=self.pointing - + ob[:] = self.pointing + zodical_e = (ctypes.c_double*7)() - self.slcdll.Zodiacal(self.jtime,ob,zodical_e) + self.slcdll.Zodiacal(self.jtime, ob, zodical_e) ob1 = (ctypes.c_double*2)() ob1[:] = np.array([self.ecliptic.lon.value, self.ecliptic.lat.value]) zodical_e1 = (ctypes.c_double*7)() - self.slcdll.Zodiacal1(ob1,zodical_e1) - + self.slcdll.Zodiacal1(ob1, zodical_e1) + band_zodical_e = zodical_e[:][filterIndex[filter]] - - q=self.getFilterAndCCD_Q(filter=filter) + + q = self.getFilterAndCCD_Q(filter=filter) p_lambda = filterPivotWave[filter] c = cons.c.value h = cons.h.value - pix_zodical_e = band_zodical_e/(h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q - + pix_zodical_e = band_zodical_e / \ + (h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q + return pix_zodical_e, band_zodical_e - + """ calculate zodiacal use python """ - def calculateZodiacalFilter2(self,filter = 'i', aper = 2, pixelsize = 0.074, sun_pos = np.array([0,0,0])): - - spec, v_mag = self.calculateZodicalSpec(longitude = self.ecliptic.lon.value, latitude = self.ecliptic.lat.value, sun_pos = sun_pos) + + def calculateZodiacalFilter2(self, filter='i', aper=2, pixelsize=0.074, sun_pos=np.array([0, 0, 0])): + + spec, v_mag = self.calculateZodicalSpec( + longitude=self.ecliptic.lon.value, latitude=self.ecliptic.lat.value, sun_pos=sun_pos) # spec = self.calculateZodicalSpec(longitude = lon, latitude = lat) try: - with pkg_resources.files('ObservationSim.Instrument.data.throughputs').joinpath(filter + '_throughput.txt') as throughputFn: + with pkg_resources.files('observation_sim.instruments.data.throughputs').joinpath(filter + '_throughput.txt') as throughputFn: throughput = np.loadtxt(throughputFn) except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.data.throughputs', filter + '_throughput.txt') as throughputFn: + with pkg_resources.path('observation_sim.instruments.data.throughputs', filter + '_throughput.txt') as throughputFn: throughput = np.loadtxt(throughputFn) deltL = 0.5 @@ -294,61 +315,60 @@ class Straylight(object): throughput_ = throughput_i(lamb) - sky_pix = np.trapz(flux*throughput_, lamb) * math.pi * aper*aper/4 * pixelsize * pixelsize + sky_pix = np.trapz(flux*throughput_, lamb) * \ + math.pi * aper*aper/4 * pixelsize * pixelsize # sky_pix_e = np.trapz(y, lamb) * math.pi * aper*aper/4 * pixelsize * pixelsize/(10*10*1e-6*1e-6)*1e-7*1e4 - return sky_pix, v_mag#, sky_pix_e - - def calculateStarLightFilter(self, filter = 'i', pointYaxis = np.array([1,1,1]), pixel_size_phy = 10 ): + return sky_pix, v_mag # , sky_pix_e + + def calculateStarLightFilter(self, filter='i', pointYaxis=np.array([1, 1, 1]), pixel_size_phy=10): sat = (ctypes.c_double*3)() sat[:] = self.sat ob = (ctypes.c_double*3)() - ob[:]=self.pointing - - + ob[:] = self.pointing + py = (ctypes.c_double*3)() py[:] = pointYaxis - q=self.getFilterAndCCD_Q(filter=filter) + q = self.getFilterAndCCD_Q(filter=filter) p_lambda = filterPivotWave[filter] c = cons.c.value h = cons.h.value - star_e1 = (ctypes.c_double*7)() - self.slcdll.PointSource(self.jtime,sat,ob,py,star_e1, str.encode(self.brightStarTabFn)) + self.slcdll.PointSource(self.jtime, sat, ob, py, + star_e1, str.encode(self.brightStarTabFn)) band_star_e1 = star_e1[:][filterIndex[filter]] - pix_star_e1 = band_star_e1/(h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q - + pix_star_e1 = band_star_e1 / \ + (h*c/(p_lambda*1e-10))*pixel_size_phy*1e-6*pixel_size_phy*1e-6*q + return pix_star_e1 - def calculateEarthshineGrating(self, grating = 'GU', pixel_size_phy = 10, normFilter = 'g', aper = 2, pixelsize = 0.074): + def calculateEarthshineGrating(self, grating='GU', pixel_size_phy=10, normFilter='g', aper=2, pixelsize=0.074): sat = (ctypes.c_double*3)() sat[:] = self.sat ob = (ctypes.c_double*3)() - ob[:]=self.pointing - - + ob[:] = self.pointing + py1 = (ctypes.c_double*3)() py2 = (ctypes.c_double*3)() - self.slcdll.ComposeY(ob,py1,py2) - + self.slcdll.ComposeY(ob, py1, py2) earth_e1 = (ctypes.c_double*7)() - self.slcdll.EarthShine(self.jtime,sat,ob,py1,earth_e1) + self.slcdll.EarthShine(self.jtime, sat, ob, py1, earth_e1) earth_e2 = (ctypes.c_double*7)() - self.slcdll.EarthShine(self.jtime,sat,ob,py2,earth_e2) + self.slcdll.EarthShine(self.jtime, sat, ob, py2, earth_e2) # zodical_e = (ctypes.c_double*7)() # self.slcdll.Zodiacal(self.jtime,ob,zodical_e) - + band_earth_e1 = earth_e1[:][filterIndex[normFilter]] band_earth_e2 = earth_e2[:][filterIndex[normFilter]] band_earth_e = band_earth_e2 py = py2[:] - if band_earth_e1 photo/s/m2/A flux = y * lamb / (cons.h.value * cons.c.value) * 1e-13 - return sky_pix, Table(np.array([lamb, flux]).T,names=('WAVELENGTH', 'FLUX')) + return sky_pix, Table(np.array([lamb, flux]).T, names=('WAVELENGTH', 'FLUX')) - def calculateZodicalSpec(self,longitude = 50, latitude = 60, sun_pos = np.array([0,0,0])): + def calculateZodicalSpec(self, longitude=50, latitude=60, sun_pos=np.array([0, 0, 0])): from scipy.interpolate import interp2d from scipy.interpolate import griddata try: - with pkg_resources.files('ObservationSim.Straylight.data').joinpath('Zodiacal_map1.dat') as z_map_fn: - ZL = np.loadtxt(z_map_fn) + with pkg_resources.files('observation_sim.sky_background.data').joinpath('Zodiacal_map1.dat') as z_map_fn: + ZL = np.loadtxt(z_map_fn) except AttributeError: - with pkg_resources.path('ObservationSim.Straylight.data', + with pkg_resources.path('observation_sim.sky_background.data', 'Zodiacal_map1.dat') as z_map_fn: ZL = np.loadtxt(z_map_fn) # zl_sh = ZL.shape # x = np.arange(0,zl_sh[1],1) # y = np.arange(0,zl_sh[0],1) - x = ZL[0,1:] - y = ZL[1:,0] - X,Y = np.meshgrid(x,y) + x = ZL[0, 1:] + y = ZL[1:, 0] + X, Y = np.meshgrid(x, y) # f_sur = interp2d(X,Y,ZL,kind='linear') sun_radec = Cartesian2Equatorial(sun_pos) - sun_eclip = coord.SkyCoord(sun_radec[0]*u.degree, sun_radec[1]*u.degree,frame='icrs') + sun_eclip = coord.SkyCoord( + sun_radec[0]*u.degree, sun_radec[1]*u.degree, frame='icrs') sun_equtor = sun_eclip.transform_to('barycentrictrueecliptic') longitude = longitude - (sun_equtor.lon*u.degree).value @@ -526,15 +551,16 @@ class Straylight(object): latitude = np.abs(latitude) lo = longitude la = latitude - zl = griddata((X.flatten(),Y.flatten()),ZL[1:,1:].flatten(),(la,lo), method='cubic').min() + zl = griddata((X.flatten(), Y.flatten()), + ZL[1:, 1:].flatten(), (la, lo), method='cubic').min() zl = zl*(math.pi*math.pi)/(180*180)/(3600*3600)*1e-4*1e7*1e-8*1e-4 # print(zl , '\n') try: - with pkg_resources.files('ObservationSim.Straylight.data.sky').joinpath('zodiacal.dat') as zodical_fn: + with pkg_resources.files('observation_sim.sky_background.data.sky').joinpath('zodiacal.dat') as zodical_fn: spec = np.loadtxt(zodical_fn) except AttributeError: - with pkg_resources.path('ObservationSim.Straylight.data.sky', + with pkg_resources.path('observation_sim.sky_background.data.sky', 'zodiacal.dat') as zodical_fn: spec = np.loadtxt(zodical_fn) @@ -545,29 +571,37 @@ class Straylight(object): v_mag = np.log10(f_ration)*(-2.5)+22.1 # print("factor:", v_mag, lo, la) - return Table(np.array([spec[:,0], spec[:,1]*f_ration]).T,names=('WAVELENGTH', 'FLUX')), v_mag - - def calculateStrayLightFilter(self, filter = 'i', pixel_size_phy = 10, pixel_scale = 0.074): - e1,py = self.calculateEarthShineFilter(filter = filter, pixel_size_phy = pixel_size_phy) - e2, _ = self.calculateZodiacalFilter2(filter = filter, sun_pos=self.sun_pos, pixelsize = pixel_scale) - e3 = self.calculateStarLightFilter(filter = filter,pointYaxis = py, pixel_size_phy = pixel_size_phy) - + return Table(np.array([spec[:, 0], spec[:, 1]*f_ration]).T, names=('WAVELENGTH', 'FLUX')), v_mag + + def calculateStrayLightFilter(self, filter='i', pixel_size_phy=10, pixel_scale=0.074): + e1, py = self.calculateEarthShineFilter( + filter=filter, pixel_size_phy=pixel_size_phy) + e2, _ = self.calculateZodiacalFilter2( + filter=filter, sun_pos=self.sun_pos, pixelsize=pixel_scale) + e3 = self.calculateStarLightFilter( + filter=filter, pointYaxis=py, pixel_size_phy=pixel_size_phy) + return e1+e2+e3 - - def calculateStrayLightGrating(self, grating = 'GI', pixel_size_phy = 10, normFilter_es = 'g'): - e1,py = self.calculateEarthshineGrating(grating = grating, pixel_size_phy = pixel_size_phy, normFilter = normFilter_es) - e2 = self.calculateStarLightGrating(grating = grating, pointYaxis = py) - spec, _ = self.calculateZodicalSpec(longitude = self.ecliptic.lon.value, latitude = self.ecliptic.lat.value, sun_pos = self.sun_pos) - + + def calculateStrayLightGrating(self, grating='GI', pixel_size_phy=10, normFilter_es='g'): + e1, py = self.calculateEarthshineGrating( + grating=grating, pixel_size_phy=pixel_size_phy, normFilter=normFilter_es) + e2 = self.calculateStarLightGrating(grating=grating, pointYaxis=py) + spec, _ = self.calculateZodicalSpec( + longitude=self.ecliptic.lon.value, latitude=self.ecliptic.lat.value, sun_pos=self.sun_pos) + return e1+e2, spec - -def testZodiacal(lon = 285.04312526255366, lat = 30.): - c_eclip = coord.SkyCoord(lon*u.degree, lat*u.degree,frame='barycentrictrueecliptic') + +def testZodiacal(lon=285.04312526255366, lat=30.): + c_eclip = coord.SkyCoord(lon*u.degree, lat*u.degree, + frame='barycentrictrueecliptic') c_equtor = c_eclip.transform_to('icrs') - sl = Straylight(jtime = 2459767.00354975, sat = np.array([]), radec = np.array([(c_equtor.ra*u.degree).value, (c_equtor.dec*u.degree).value])) - e_zol, v_mag = sl.calculateZodiacalFilter2(filter = 'i', sun_pos=np.array([-3.70939436e+07, 1.35334903e+08, 5.86673104e+07])) + sl = Straylight(jtime=2459767.00354975, sat=np.array([]), radec=np.array( + [(c_equtor.ra*u.degree).value, (c_equtor.dec*u.degree).value])) + e_zol, v_mag = sl.calculateZodiacalFilter2(filter='i', sun_pos=np.array( + [-3.70939436e+07, 1.35334903e+08, 5.86673104e+07])) print(e_zol) # ju=2.4608437604166665e+06 @@ -639,4 +673,3 @@ def testZodiacal(lon = 285.04312526255366, lat = 30.): # print(e1+e2,e1_+e3+e4,e5,e6) # # # print(e1,e2,e3,e4) - diff --git a/ObservationSim/Straylight/__init__.py b/observation_sim/sky_background/__init__.py similarity index 100% rename from ObservationSim/Straylight/__init__.py rename to observation_sim/sky_background/__init__.py diff --git a/ObservationSim/Straylight/data/Zodiacal_map1.dat b/observation_sim/sky_background/data/Zodiacal_map1.dat similarity index 100% rename from ObservationSim/Straylight/data/Zodiacal_map1.dat rename to observation_sim/sky_background/data/Zodiacal_map1.dat diff --git a/ObservationSim/Straylight/data/sky/__init__.py b/observation_sim/sky_background/data/__init__.py similarity index 100% rename from ObservationSim/Straylight/data/sky/__init__.py rename to observation_sim/sky_background/data/__init__.py diff --git a/ObservationSim/Straylight/lib/__init__.py b/observation_sim/sky_background/data/sky/__init__.py similarity index 100% rename from ObservationSim/Straylight/lib/__init__.py rename to observation_sim/sky_background/data/sky/__init__.py diff --git a/ObservationSim/Straylight/data/sky/earthShine.dat b/observation_sim/sky_background/data/sky/earthShine.dat similarity index 100% rename from ObservationSim/Straylight/data/sky/earthShine.dat rename to observation_sim/sky_background/data/sky/earthShine.dat diff --git a/ObservationSim/Straylight/data/sky/earthshine1.dat b/observation_sim/sky_background/data/sky/earthshine1.dat similarity index 100% rename from ObservationSim/Straylight/data/sky/earthshine1.dat rename to observation_sim/sky_background/data/sky/earthshine1.dat diff --git a/ObservationSim/Straylight/data/sky/sky.dat b/observation_sim/sky_background/data/sky/sky.dat similarity index 100% rename from ObservationSim/Straylight/data/sky/sky.dat rename to observation_sim/sky_background/data/sky/sky.dat diff --git a/ObservationSim/Straylight/data/sky/sky_emiss_hubble_50_50_A.dat b/observation_sim/sky_background/data/sky/sky_emiss_hubble_50_50_A.dat similarity index 100% rename from ObservationSim/Straylight/data/sky/sky_emiss_hubble_50_50_A.dat rename to observation_sim/sky_background/data/sky/sky_emiss_hubble_50_50_A.dat diff --git a/ObservationSim/Straylight/data/sky/zodiacal.dat b/observation_sim/sky_background/data/sky/zodiacal.dat similarity index 100% rename from ObservationSim/Straylight/data/sky/zodiacal.dat rename to observation_sim/sky_background/data/sky/zodiacal.dat diff --git a/ObservationSim/Straylight/data/sky/zodiacal_.dat b/observation_sim/sky_background/data/sky/zodiacal_.dat similarity index 100% rename from ObservationSim/Straylight/data/sky/zodiacal_.dat rename to observation_sim/sky_background/data/sky/zodiacal_.dat diff --git a/ObservationSim/Straylight/lib/BrightGaia_with_csst_mag b/observation_sim/sky_background/lib/BrightGaia_with_csst_mag similarity index 100% rename from ObservationSim/Straylight/lib/BrightGaia_with_csst_mag rename to observation_sim/sky_background/lib/BrightGaia_with_csst_mag diff --git a/ObservationSim/Straylight/lib/DE405 b/observation_sim/sky_background/lib/DE405 similarity index 100% rename from ObservationSim/Straylight/lib/DE405 rename to observation_sim/sky_background/lib/DE405 diff --git a/ObservationSim/Straylight/lib/PST b/observation_sim/sky_background/lib/PST similarity index 100% rename from ObservationSim/Straylight/lib/PST rename to observation_sim/sky_background/lib/PST diff --git a/ObservationSim/Straylight/lib/R b/observation_sim/sky_background/lib/R similarity index 100% rename from ObservationSim/Straylight/lib/R rename to observation_sim/sky_background/lib/R diff --git a/ObservationSim/Straylight/lib/Zodiacal b/observation_sim/sky_background/lib/Zodiacal similarity index 100% rename from ObservationSim/Straylight/lib/Zodiacal rename to observation_sim/sky_background/lib/Zodiacal diff --git a/ObservationSim/__init__.py b/observation_sim/sky_background/lib/__init__.py similarity index 100% rename from ObservationSim/__init__.py rename to observation_sim/sky_background/lib/__init__.py diff --git a/ObservationSim/Straylight/lib/libstraylight.dylib b/observation_sim/sky_background/lib/libstraylight.dylib similarity index 100% rename from ObservationSim/Straylight/lib/libstraylight.dylib rename to observation_sim/sky_background/lib/libstraylight.dylib diff --git a/ObservationSim/Straylight/lib/libstraylight.so b/observation_sim/sky_background/lib/libstraylight.so similarity index 100% rename from ObservationSim/Straylight/lib/libstraylight.so rename to observation_sim/sky_background/lib/libstraylight.so diff --git a/profile_C6.sh b/profile_C6.sh deleted file mode 100755 index c7d03048dc0c4b4f85238f79d3c8e8d1f88e4710..0000000000000000000000000000000000000000 --- a/profile_C6.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -date - -python -m cProfile -o C6_profiler_test.pstats /share/home/fangyuedong/new_sim/csst-simulation/run_sim.py \ - --config_file config_C6.yaml \ - --catalog C6_Catalog \ - -c /share/home/fangyuedong/new_sim/csst-simulation/config - - # --config_file config_test_new_sim.yaml \ - # --catalog New_sim_Test \ - # -c /share/home/fangyuedong/new_sim/csst-simulation/config - - # --config_file config_50sqdeg.yaml \ - # --catalog C6_50sqdeg \ - # -c /share/home/fangyuedong/new_sim/csst-simulation/config - - # --config_file config_fgs.yaml \ - # --catalog FGS_Catalog \ - # -c /share/home/fangyuedong/csst-simulation/config - - # --config_file test_fd_C6.yaml \ - # --catalog fd_test_C6 \ - # --config_file config_C6_test_wcs.yaml \ - # --catalog wcs_test_C6 \ diff --git a/profile_run.sh b/profile_run.sh new file mode 100755 index 0000000000000000000000000000000000000000..bde7199c25f44227bf106083a6b252afe7a765bb --- /dev/null +++ b/profile_run.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +date + +python -m cProfile -o profiler_test.pstats /share/home/fangyuedong/new_sim/csst-simulation/run_sim.py \ + --config_file config_overall.yaml \ + --catalog C9_Catalog \ + -c /share/home/fangyuedong/new_sim/csst-simulation/config diff --git a/run_sim.py b/run_sim.py index 0cc1368633c80a2c84f7a39d4171eb11b6cc5783..f1179851f87e066259bbc9cbd1e63939da78e3fc 100755 --- a/run_sim.py +++ b/run_sim.py @@ -1,5 +1,5 @@ -from ObservationSim.ObservationSim import Observation -from ObservationSim._util import parse_args, make_run_dirs, generate_pointing_list +from observation_sim.ObservationSim import Observation +from observation_sim._util import parse_args, make_run_dirs, generate_pointing_list from importlib.metadata import version import os import yaml @@ -18,7 +18,7 @@ def run_sim(): Parameters ---------- Catalog : Class - a catalog class which is inherited from ObservationSim.MockObject.CatalogBase + a catalog class which is inherited from observation_sim.mock_objects.CatalogBase Returns ---------- @@ -94,7 +94,7 @@ def run_sim(): # Initialize the simulation if args.catalog is not None: - catalog_module = importlib.import_module('Catalog.'+args.catalog) + catalog_module = importlib.import_module('catalog.'+args.catalog) obs = Observation(config=config, Catalog=catalog_module.Catalog, work_dir=config['work_dir'], data_dir=config['data_dir']) else: diff --git a/setup.py b/setup.py index 921688eb4a29fd6ae500407c0fb34ce45e692c10..5bf45b9ce754aeac9bb29d11f2cd8825e1e11dba 100644 --- a/setup.py +++ b/setup.py @@ -39,26 +39,26 @@ class build_ext(build_ext): extensions = [ - Extension("ObservationSim.MockObject.SpecDisperser.disperse_c.interp", ["ObservationSim/MockObject/SpecDisperser/disperse_c/interp.pyx"], + Extension("observation_sim.mock_objects.SpecDisperser.disperse_c.interp", ["observation_sim/mock_objects/SpecDisperser/disperse_c/interp.pyx"], include_dirs=[numpy.get_include()], libraries=["m"]), - Extension("ObservationSim.MockObject.SpecDisperser.disperse_c.disperse", ["ObservationSim/MockObject/SpecDisperser/disperse_c/disperse.pyx"], + Extension("observation_sim.mock_objects.SpecDisperser.disperse_c.disperse", ["observation_sim/mock_objects/SpecDisperser/disperse_c/disperse.pyx"], include_dirs=[numpy.get_include()], libraries=["m"]), ] -df_module = [CTypes('ObservationSim.Instrument.Chip.libBF.libmoduleBF', - ['ObservationSim/Instrument/Chip/libBF/diffusion_X1.c', - 'ObservationSim/Instrument/Chip/libBF/nrutil.c'], +df_module = [CTypes('observation_sim.instruments.chip.libBF.libmoduleBF', + ['observation_sim/instruments/chip/libBF/diffusion_X1.c', + 'observation_sim/instruments/chip/libBF/nrutil.c'], include_dirs=[ - 'ObservationSim/Instrument/Chip/libBF/', '/usr/include'] + 'observation_sim/instruments/chip/libBF/', '/usr/include'] )] -cti_module = [CTypes('ObservationSim.Instrument.Chip.libCTI.libmoduleCTI', - ['ObservationSim/Instrument/Chip/libCTI/src/add_CTI.c', 'ObservationSim/Instrument/Chip/libCTI/src/nrutil.c', 'ObservationSim/Instrument/Chip/libCTI/src/ran1.c', 'ObservationSim/Instrument/Chip/libCTI/src/ran2.c', 'ObservationSim/Instrument/Chip/libCTI/src/poidev.c', - 'ObservationSim/Instrument/Chip/libCTI/src/gammln.c', 'ObservationSim/Instrument/Chip/libCTI/src/gasdev.c', 'ObservationSim/Instrument/Chip/libCTI/src/sort.c', 'ObservationSim/Instrument/Chip/libCTI/src/creattraps.c'], +cti_module = [CTypes('observation_sim.instruments.chip.libCTI.libmoduleCTI', + ['observation_sim/instruments/chip/libCTI/src/add_CTI.c', 'observation_sim/instruments/chip/libCTI/src/nrutil.c', 'observation_sim/instruments/chip/libCTI/src/ran1.c', 'observation_sim/instruments/chip/libCTI/src/ran2.c', 'observation_sim/instruments/chip/libCTI/src/poidev.c', + 'observation_sim/instruments/chip/libCTI/src/gammln.c', 'observation_sim/instruments/chip/libCTI/src/gasdev.c', 'observation_sim/instruments/chip/libCTI/src/sort.c', 'observation_sim/instruments/chip/libCTI/src/creattraps.c'], include_dirs=[ - 'ObservationSim/Instrument/Chip/libCTI/src/', '/usr/include'] + 'observation_sim/instruments/chip/libCTI/src/', '/usr/include'] )] @@ -76,7 +76,7 @@ with open("requirements.txt", "r") as f: ] setup(name='csst_msc_sim', - version='3.0.0rc', + version='3.0.0', packages=find_packages(), # install_requires=[ # # 'numpy>=1.18.5', @@ -93,23 +93,23 @@ setup(name='csst_msc_sim', # ], package_data={ - 'ObservationSim.Astrometry.lib': ['libshao.so'], - 'ObservationSim.Instrument.Chip.libBF': ['libmoduleBF.so'], - 'ObservationSim.Instrument.Chip.libCTI': ['libmoduleCTI.so'], - 'ObservationSim.MockObject.data': ['*.dat'], - 'ObservationSim.MockObject.data.led': ['*.fits'], - 'ObservationSim.Instrument.data': ['*.txt', '*.dat', '*.json'], - 'ObservationSim.Instrument.data.field_distortion': ['*.pickle'], - 'ObservationSim.Instrument.data.ccd': ['*.txt', '*.json'], - 'ObservationSim.Instrument.data.filters': ['*.txt', '*.list', '*.dat'], - 'ObservationSim.Instrument.data.throughputs': ['*.txt', '*.dat'], - 'ObservationSim.Instrument.data.sls_conf': ['*.conf', '*.fits'], - # 'ObservationSim.Instrument.data.flatCube': ['*.fits'], - 'Catalog.data': ['*.fits', '*.so'], - 'ObservationSim.Config.Header': ['*.fits', '*.lst'], - 'ObservationSim.Straylight.data': ['*.dat'], - 'ObservationSim.Straylight.data.sky': ['*.dat'], - 'ObservationSim.Straylight.lib': ['*'], + 'observation_sim.astrometry.lib': ['libshao.so'], + 'observation_sim.instruments.chip.libBF': ['libmoduleBF.so'], + 'observation_sim.instruments.chip.libCTI': ['libmoduleCTI.so'], + 'observation_sim.mock_objects.data': ['*.dat'], + 'observation_sim.mock_objects.data.led': ['*.fits'], + 'observation_sim.instruments.data': ['*.txt', '*.dat', '*.json'], + 'observation_sim.instruments.data.field_distortion': ['*.pickle'], + 'observation_sim.instruments.data.ccd': ['*.txt', '*.json'], + 'observation_sim.instruments.data.filters': ['*.txt', '*.list', '*.dat'], + 'observation_sim.instruments.data.throughputs': ['*.txt', '*.dat'], + 'observation_sim.instruments.data.sls_conf': ['*.conf', '*.fits'], + # 'observation_sim.Instrument.data.flatCube': ['*.fits'], + 'catalog.data': ['*.fits', '*.so'], + 'observation_sim.config.header': ['*.fits', '*.lst'], + 'observation_sim.sky_background.data': ['*.dat'], + 'observation_sim.sky_background.data.sky': ['*.dat'], + 'observation_sim.sky_background.lib': ['*'], }, python_requires=">=3.11", # Python版本要求 install_requires=requirements, diff --git a/run_C6.pbs b/submit_jobs.slurm similarity index 85% rename from run_C6.pbs rename to submit_jobs.slurm index 32cfa73df9123ce6714f5d91c12b6e7cfdcff32b..34867ae2a24730ab5f485dd69725642343272687 100755 --- a/run_C6.pbs +++ b/submit_jobs.slurm @@ -12,4 +12,4 @@ date #限定单节点任务数 srun hostname -s | sort -n | awk -F"-" '{print $2}' | uniq > pnodes -mpirun -mca pml ucx -x UCX_NET_DEVICES=mlx5_0:1 -machinefile pnodes -np 6 --map-by node python3 /public/home/fangyuedong/project/csst_msc_sim/run_sim.py --config_file config_overall.yaml --catalog C6_50sqdeg_ns -c /public/home/fangyuedong/project/csst_msc_sim/config \ No newline at end of file +mpirun -mca pml ucx -x UCX_NET_DEVICES=mlx5_0:1 -machinefile pnodes -np 6 --map-by node python3 /public/home/fangyuedong/project/csst_msc_sim/run_sim.py --config_file config_overall.yaml --catalog C9_Catalog -c /public/home/fangyuedong/project/csst_msc_sim/config \ No newline at end of file diff --git a/test_C6.sh b/test_C6.sh deleted file mode 100755 index 1ce5be63ec599042c43f680178ef7a0ce877721f..0000000000000000000000000000000000000000 --- a/test_C6.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -date - -python3 /public/home/fangyuedong/project/csst_msc_sim/run_sim.py \ - --config_file config_overall.yaml \ - -c /public/home/fangyuedong/project/csst_msc_sim/config \ - --catalog C6_50sqdeg - -# python3 /share/home/fangyuedong/20231211/csst-simulation/run_sim.py \ -# --config_file config_C6_dev.yaml \ -# --catalog C6_Catalog \ -# -c /share/home/fangyuedong/20231211/csst-simulation/config - -# python3 /share/home/fangyuedong/20231211/csst-simulation/run_sim.py \ -# --config_file config_ooc_c6.yaml \ -# --catalog C6_Catalog \ -# -c /share/home/fangyuedong/20231211/csst-simulation/config - diff --git a/test_run.sh b/test_run.sh new file mode 100755 index 0000000000000000000000000000000000000000..436bfaa90c61cce627534e4923440b06fe19c46e --- /dev/null +++ b/test_run.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +date + +python3 /public/home/fangyuedong/project/csst_msc_sim/run_sim.py \ + --config_file config_overall.yaml \ + -c /public/home/fangyuedong/project/csst_msc_sim/config \ + --catalog C9_Catalog + diff --git a/tests/libshao.so b/tests/libshao.so deleted file mode 100644 index 47d97a44a74c8f011914dc07f52d8957c81eff39..0000000000000000000000000000000000000000 Binary files a/tests/libshao.so and /dev/null differ diff --git a/tests/shao_test.py b/tests/shao_test.py deleted file mode 100644 index a4dab231537136780a79181e36928db1181fc787..0000000000000000000000000000000000000000 --- a/tests/shao_test.py +++ /dev/null @@ -1,75 +0,0 @@ -import os -import sys - -from ObservationSim.Astrometry.Astrometry_util import on_orbit_obs_position - -def readFits2List(fn): - from astropy.io import fits - if not os.path.exists(fn): - print("Can not find "+fn); return False - - hdul=fits.open(fn) - data = hdul[1].data - ra_list = data['RA'].tolist() - dec_list = data['Dec'].tolist() - pmra_list = data['pmra'].tolist() - pmdec_list = data['pmdec'].tolist() - parallax_list = data['parallax'].tolist() - rv_list = [0.0 for i in range(len(ra_list))] - hdul.close() - return ra_list, dec_list, pmra_list, pmdec_list, rv_list, parallax_list - -def usageExample(targets_fn, results_fn, x, y, z, vx, vy, vz, date_str, time_str): - if not os.path.exists(targets_fn): - print("Can not find " + targets_fn) - sys.exit(1) - ra_list, dec_list, pmra_list, pmdec_list, rv_list, parallax_list = readFits2List(targets_fn) - output_ra_list, output_dec_list = on_orbit_obs_position(ra_list, dec_list, pmra_list, \ - pmdec_list, rv_list, parallax_list, len(ra_list), \ - x, y, z, vx, vy, vz, "J2015.5", date_str, time_str, lib_path='./libshao.so') - f = open(results_fn, "w") - ll = list() - ll.append("n,date,time,ra,dec,pm_ra,pm_dec,rv,parallax,obs_ra,obs_dec\n") - for i in range(len(output_ra_list)): - ra_str = str(ra_list[i]) - dec_str = str(dec_list[i]) - pmra_str = str(pmra_list[i]) - pmdec_str = str(pmdec_list[i]) - rv_str = str(rv_list[i]) - parallax_str = str(parallax_list[i]) - ora_str = str(output_ra_list[i]) - odec_str = str(output_dec_list[i]) - l = str(i)+date_str+","+time_str+","+ra_str+","+dec_str+","+pmra_str+","+pmdec_str+","+rv_str+","+parallax_str+","+ora_str+","+odec_str+"\n" - ll.append(l) - f.writelines(ll) - f.close() - print("Process finished. Results save to "+results_fn) - -def usageTips(): - print("Usage 1: python3 ./shao_test.py") - print("Usage 2: python3 ./shao_test.py yyyy-MM-dd HH:mm:ss.ms Positon1_KM Positon2_KM Positon3_KM Velocity1_MK/S Velocity2_MK/S Velocity3_MK/S $PATH1/MMW_Gaia_Cluster_D20_SS_astrometry.fits $PATH2/results.csv") - print("Caution: Do no include space in path; Unit is KM or KM/S") - print("Example: python3 ./shao_test.py 2025-03-05 22:20:15.12 2347.766100 5132.421392 3726.591334 5.282357 4.644825 -3.074722 ./MMW_Gaia_Cluster_D20_SS_astrometry.fits ./results.csv") - -if __name__ == "__main__": - args_value = sys.argv - if len(args_value) == 1: - usageExample("./MMW_Gaia_Cluster_D20_SS_astrometry.fits", "./results.csv", 2347.766100, 5132.421392, 3726.591334, 5.282357, 4.644825, -3.074722, "2025-03-05", "22:20:15.12"); sys.exit(1) - elif len(args_value) == 11: - date_str = args_value[1] - time_str = args_value[2] - x = float(args_value[3]) - y = float(args_value[4]) - z = float(args_value[5]) - vx = float(args_value[6]) - vy = float(args_value[7]) - vz = float(args_value[8]) - targets_fn = args_value[9] - results_fn = args_value[10] - if not os.path.exists(targets_fn): - print("Can not find " + targets_fn) - sys.exit(1) - usageExample(targets_fn, results_fn, x, y, z, vx, vy, vz, date_str, time_str) - else: - usageTips() - diff --git a/tests/test_BF_CTE.py b/tests/test_BF_CTE.py index 4b3ef74015b99d9fe4d51a51fa8acc26ca248a92..26b9dad3912ec479b1bba258e4b9433bffa99b4c 100644 --- a/tests/test_BF_CTE.py +++ b/tests/test_BF_CTE.py @@ -1,6 +1,8 @@ import unittest -import sys,os,math +import sys +import os +import math from itertools import islice import numpy as np import copy @@ -9,10 +11,9 @@ import galsim import yaml from astropy.io import fits -from ObservationSim.Instrument import Chip, Filter, FilterParam, FocalPlane -from ObservationSim.Instrument.Chip import ChipUtils as chip_utils -#from ObservationSim.sim_steps import add_brighter_fatter_CTE -from ObservationSim.Instrument.Chip.libCTI.CTI_modeling import CTI_sim +from observation_sim.instruments import Chip, Filter, FilterParam, FocalPlane +from observation_sim.instruments.chip import chip_utils +from observation_sim.instruments.chip.libCTI.CTI_modeling import CTI_sim try: import importlib.resources as pkg_resources @@ -23,14 +24,15 @@ except ImportError: ### test FUNCTION --- START ### def add_brighter_fatter(img): - #Inital dynamic lib + # Inital dynamic lib try: - with pkg_resources.files('ObservationSim.Instrument.Chip.libBF').joinpath("libmoduleBF.so") as lib_path: + with pkg_resources.files('observation_sim.instruments.chip.libBF').joinpath("libmoduleBF.so") as lib_path: lib_bf = ctypes.CDLL(lib_path) except AttributeError: - with pkg_resources.path('ObservationSim.Instrument.Chip.libBF', "libmoduleBF.so") as lib_path: + with pkg_resources.path('observation_sim.instruments.chip.libBF', "libmoduleBF.so") as lib_path: lib_bf = ctypes.CDLL(lib_path) - lib_bf.addEffects.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_int] + lib_bf.addEffects.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.POINTER( + ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_int] # Set bit flag bit_flag = 1 @@ -38,11 +40,11 @@ def add_brighter_fatter(img): nx, ny = img.array.shape nn = nx * ny - arr_ima= (ctypes.c_float*nn)() - arr_imc= (ctypes.c_float*nn)() + arr_ima = (ctypes.c_float*nn)() + arr_imc = (ctypes.c_float*nn)() - arr_ima[:]= img.array.reshape(nn) - arr_imc[:]= np.zeros(nn) + arr_ima[:] = img.array.reshape(nn) + arr_imc[:] = np.zeros(nn) lib_bf.addEffects(nx, ny, arr_ima, arr_imc, bit_flag) img.array[:, :] = np.reshape(arr_imc, [nx, ny]) @@ -50,20 +52,24 @@ def add_brighter_fatter(img): return img ### test FUNCTION --- END ### + def defineCCD(iccd, config_file): with open(config_file, "r") as stream: try: config = yaml.safe_load(stream) - #for key, value in config.items(): + # for key, value in config.items(): # print (key + " : " + str(value)) except yaml.YAMLError as exc: print(exc) chip = Chip(chipID=iccd, config=config) - chip.img = galsim.ImageF(400, 200) #galsim.ImageF(chip.npix_x, chip.npix_y) + # galsim.ImageF(chip.npix_x, chip.npix_y) + chip.img = galsim.ImageF(400, 200) focal_plane = FocalPlane(chip_list=[iccd]) - chip.img.wcs= focal_plane.getTanWCS(192.8595, 27.1283, -113.4333*galsim.degrees, chip.pix_scale) + chip.img.wcs = focal_plane.getTanWCS( + 192.8595, 27.1283, -113.4333*galsim.degrees, chip.pix_scale) return chip + def defineFilt(chip): filter_param = FilterParam() filter_id, filter_type = chip.getChipFilter() @@ -79,11 +85,11 @@ def defineFilt(chip): class detModule_coverage(unittest.TestCase): def __init__(self, methodName='runTest'): super(detModule_coverage, self).__init__(methodName) - ##self.dataPath = "/public/home/chengliang/CSSOSDataProductsSims/csst-simulation/tests/UNIT_TEST_DATA" ##os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), 'csst_fz_gc1') - self.dataPath = os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), 'csst_msc_sim/csst_fz_msc') + # self.dataPath = "/public/home/chengliang/CSSOSDataProductsSims/csst-simulation/tests/UNIT_TEST_DATA" ##os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), 'csst_fz_gc1') + self.dataPath = os.path.join( + os.getenv('UNIT_TEST_DATA_ROOT'), 'csst_msc_sim/csst_fz_msc') self.iccd = 1 - def test_add_brighter_fatter(self): config_file = os.path.join(self.dataPath, 'config_test.yaml') chip = defineCCD(self.iccd, config_file) @@ -91,32 +97,31 @@ class detModule_coverage(unittest.TestCase): print(chip.chipID) print(chip.cen_pix_x, chip.cen_pix_y) - #objA-lowSFB + # objA-lowSFB obj = galsim.Gaussian(sigma=0.2, flux=1000) arr = obj.drawImage(nx=64, ny=64, scale=0.074).array - chip.img.array[(100-32):(100+32),(200-32):(200+32)] = arr[:,:] + chip.img.array[(100-32):(100+32), (200-32):(200+32)] = arr[:, :] img_old = copy.deepcopy(chip.img) img_new = add_brighter_fatter(img=chip.img) - arr1= img_old.array - arr2= img_new.array + arr1 = img_old.array + arr2 = img_new.array deltaA_max = np.max(np.abs(arr2-arr1)) - print('deltaA-max:', np.max(np.abs(arr2-arr1))) - print('deltaA-min:', np.min(np.abs(arr2-arr1))) + print('deltaA-max:', np.max(np.abs(arr2-arr1))) + print('deltaA-min:', np.min(np.abs(arr2-arr1))) - #objB-highSFB + # objB-highSFB obj = galsim.Gaussian(sigma=0.2, flux=10000) arr = obj.drawImage(nx=64, ny=64, scale=0.074).array - chip.img.array[(100-32):(100+32),(200-32):(200+32)] = arr[:,:] + chip.img.array[(100-32):(100+32), (200-32):(200+32)] = arr[:, :] img_old = copy.deepcopy(chip.img) img_new = add_brighter_fatter(img=chip.img) - arr3= img_old.array - arr4= img_new.array + arr3 = img_old.array + arr4 = img_new.array deltaB_max = np.max(np.abs(arr4-arr3)) - print('deltaB-max:', np.max(np.abs(arr4-arr3))) - print('deltaB-min:', np.min(np.abs(arr4-arr3))) - - self.assertTrue( deltaB_max > deltaA_max ) + print('deltaB-max:', np.max(np.abs(arr4-arr3))) + print('deltaB-min:', np.min(np.abs(arr4-arr3))) + self.assertTrue(deltaB_max > deltaA_max) def test_apply_CTE(self): config_file = os.path.join(self.dataPath, 'config_test.yaml') @@ -126,18 +131,21 @@ class detModule_coverage(unittest.TestCase): print(chip.cen_pix_x, chip.cen_pix_y) print(" Apply CTE Effect") - nx,ny,noverscan,nsp,nmax = 4608,4616,84,3,10 + nx, ny, noverscan, nsp, nmax = 4608, 4616, 84, 3, 10 ntotal = 4700 - beta,w,c = 0.478,84700,0 - t = np.array([0.74,7.7,37],dtype=np.float32) - rho_trap = np.array([0.6,1.6,1.4],dtype=np.float32) - trap_seeds = np.array([0,100,1000],dtype=np.int32) + beta, w, c = 0.478, 84700, 0 + t = np.array([0.74, 7.7, 37], dtype=np.float32) + rho_trap = np.array([0.6, 1.6, 1.4], dtype=np.float32) + trap_seeds = np.array([0, 100, 1000], dtype=np.int32) release_seed = 500 - image = fits.getdata(os.path.join(self.dataPath, "testCTE_image_before.fits")).astype(np.int32) - #get_trap_map(trap_seeds,nx,ny,nmax,rho_trap,beta,c,".") - #bin2fits("trap.bin",".",nsp,nx,ny,nmax) - image_cti = CTI_sim(image,nx,ny,noverscan,nsp,nmax,beta,w,c,t,rho_trap,trap_seeds,release_seed) - fits.writeto(os.path.join(self.dataPath, "testCTE_image_after.fits"),data=image_cti,overwrite=True) + image = fits.getdata(os.path.join( + self.dataPath, "testCTE_image_before.fits")).astype(np.int32) + # get_trap_map(trap_seeds,nx,ny,nmax,rho_trap,beta,c,".") + # bin2fits("trap.bin",".",nsp,nx,ny,nmax) + image_cti = CTI_sim(image, nx, ny, noverscan, nsp, nmax, + beta, w, c, t, rho_trap, trap_seeds, release_seed) + fits.writeto(os.path.join( + self.dataPath, "testCTE_image_after.fits"), data=image_cti, overwrite=True) if __name__ == '__main__': diff --git a/tests/test_PSFmodule.py b/tests/test_PSFmodule.py index c0399aaf0ea9c1e26483ef442a9c41a218115564..a977dd9960377866e86168452e2c9930ba0a6b52 100644 --- a/tests/test_PSFmodule.py +++ b/tests/test_PSFmodule.py @@ -1,29 +1,33 @@ import unittest -import sys,os,math +import sys +import os +import math from itertools import islice import numpy as np import galsim import yaml -from ObservationSim.Instrument import Chip, Filter, FilterParam, FocalPlane -from ObservationSim.PSF.PSFInterp import PSFInterp +from observation_sim.instruments import Chip, Filter, FilterParam, FocalPlane +from observation_sim.psf.PSFInterp import PSFInterp def defineCCD(iccd, config_file): with open(config_file, "r") as stream: try: config = yaml.safe_load(stream) - #for key, value in config.items(): + # for key, value in config.items(): # print (key + " : " + str(value)) except yaml.YAMLError as exc: print(exc) chip = Chip(chipID=iccd, config=config) chip.img = galsim.ImageF(chip.npix_x, chip.npix_y) focal_plane = FocalPlane(chip_list=[iccd]) - chip.img.wcs= focal_plane.getTanWCS(192.8595, 27.1283, -113.4333*galsim.degrees, chip.pix_scale) + chip.img.wcs = focal_plane.getTanWCS( + 192.8595, 27.1283, -113.4333*galsim.degrees, chip.pix_scale) return chip + def defineFilt(chip): filter_param = FilterParam() filter_id, filter_type = chip.getChipFilter() @@ -39,7 +43,8 @@ def defineFilt(chip): class PSFInterpModule_coverage(unittest.TestCase): def __init__(self, methodName='runTest'): super(PSFInterpModule_coverage, self).__init__(methodName) - self.dataPath = os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), 'csst_msc_sim/csst_fz_msc') + self.dataPath = os.path.join( + os.getenv('UNIT_TEST_DATA_ROOT'), 'csst_msc_sim/csst_fz_msc') self.iccd = 8 def test_loadPSFSet(self): @@ -48,23 +53,28 @@ class PSFInterpModule_coverage(unittest.TestCase): bandpass = defineFilt(chip) print(chip.chipID) print(chip.cen_pix_x, chip.cen_pix_y) - - pathTemp = self.dataPath #"/public/share/yangxuliu/CSSOSDataProductsSims/psfCube/set1_dynamic/" - psfModel= PSFInterp(chip, npsf=900, PSF_data_file=pathTemp, PSF_data_prefix="", HocBuild=True, LOG_DEBUG=True) - - x, y = 4096, 4096 #imgPos[iobj, :] # try get the PSF at some location (1234, 1234) on the chip + + # "/public/share/yangxuliu/CSSOSDataProductsSims/psfCube/set1_dynamic/" + pathTemp = self.dataPath + psfModel = PSFInterp(chip, npsf=900, PSF_data_file=pathTemp, + PSF_data_prefix="", HocBuild=True, LOG_DEBUG=True) + + # imgPos[iobj, :] # try get the PSF at some location (1234, 1234) on the chip + x, y = 4096, 4096 x = x+chip.bound.xmin y = y+chip.bound.ymin pos_img = galsim.PositionD(x, y) - psf,_ = psfModel.get_PSF(chip=chip, pos_img=pos_img, bandpass=0, galsimGSObject=True) - psfA = psfModel.get_PSF(chip=chip, pos_img=pos_img, bandpass=bandpass[0], galsimGSObject=False) - psfB = psfModel.get_PSF(chip=chip, pos_img=pos_img, findNeighMode='hoclistFind', bandpass=bandpass[0], galsimGSObject=False) - - self.assertTrue( psf != None ) - self.assertTrue( np.max(np.abs(psfA-psfB))<1e-6 ) + psf, _ = psfModel.get_PSF( + chip=chip, pos_img=pos_img, bandpass=0, galsimGSObject=True) + psfA = psfModel.get_PSF( + chip=chip, pos_img=pos_img, bandpass=bandpass[0], galsimGSObject=False) + psfB = psfModel.get_PSF( + chip=chip, pos_img=pos_img, findNeighMode='hoclistFind', bandpass=bandpass[0], galsimGSObject=False) + + self.assertTrue(psf != None) + self.assertTrue(np.max(np.abs(psfA-psfB)) < 1e-6) if __name__ == '__main__': unittest.main() - diff --git a/tests/test_SpecDisperse.py b/tests/test_SpecDisperse.py index 2b9529d86724db8b4d35b5b72845dee52bd98a84..4a6553eae3e617f19c173bad1ec61f2c475326f2 100644 --- a/tests/test_SpecDisperse.py +++ b/tests/test_SpecDisperse.py @@ -1,15 +1,15 @@ # -#need add environment parameter UNIT_TEST_DATA_ROOT, link to "testData/" -#linx and mac can run as follow, need modify the name of file directory -#export UNIT_TEST_DATA_ROOT=/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_develop/csst-simulation/tests/testData +# need add environment parameter UNIT_TEST_DATA_ROOT, link to "testData/" +# linx and mac can run as follow, need modify the name of file directory +# export UNIT_TEST_DATA_ROOT=/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_develop/csst-simulation/tests/testData # import unittest -from ObservationSim.MockObject.SpecDisperser import rotate90, SpecDisperser +from observation_sim.mock_objects.SpecDisperser import rotate90, SpecDisperser -from ObservationSim.Config import ChipOutput -from ObservationSim.Instrument import Telescope, Chip, FilterParam, Filter, FocalPlane -from ObservationSim.MockObject import MockObject, Star -from ObservationSim.PSF import PSFGauss +from observation_sim.config import ChipOutput +from observation_sim.instruments import Telescope, Chip, FilterParam, Filter, FocalPlane +from observation_sim.mock_objects import MockObject, Star +from observation_sim.psf import PSFGauss import numpy as np import galsim @@ -20,36 +20,37 @@ import matplotlib.pyplot as plt from lmfit.models import LinearModel, GaussianModel -from ObservationSim.Config.Header import generateExtensionHeader +from observation_sim.config.header import generateExtensionHeader import math import yaml import os def getAngle132(x1=0, y1=0, z1=0, x2=0, y2=0, z2=0, x3=0, y3=0, z3=0): - cosValue = 0; - angle = 0; + cosValue = 0 + angle = 0 - x11 = x1 - x3; - y11 = y1 - y3; - z11 = z1 - z3; + x11 = x1 - x3 + y11 = y1 - y3 + z11 = z1 - z3 - x22 = x2 - x3; - y22 = y2 - y3; - z22 = z2 - z3; + x22 = x2 - x3 + y22 = y2 - y3 + z22 = z2 - z3 - tt = np.sqrt((x11 * x11 + y11 * y11 + z11 * z11) * (x22 * x22 + y22 * y22 + z22 * z22)); + tt = np.sqrt((x11 * x11 + y11 * y11 + z11 * z11) + * (x22 * x22 + y22 * y22 + z22 * z22)) if (tt == 0): - return 0; + return 0 - cosValue = (x11 * x22 + y11 * y22 + z11 * z22) / tt; + cosValue = (x11 * x22 + y11 * y22 + z11 * z22) / tt if (cosValue > 1): - cosValue = 1; + cosValue = 1 if (cosValue < -1): - cosValue = -1; - angle = math.acos(cosValue); - return angle * 360 / (2 * math.pi); + cosValue = -1 + angle = math.acos(cosValue) + return angle * 360 / (2 * math.pi) def fit_SingleGauss(xX, yX, contmX, iHa0): @@ -71,26 +72,35 @@ def fit_SingleGauss(xX, yX, contmX, iHa0): # print outX.params['g_center'] outX.fit_report(min_correl=0.25) # print(outX.fit_report(min_correl=0.25)) - line_slopeX = float(outX.fit_report(min_correl=0.25).split('line_slope:')[1].split('+/-')[0]) * contmX + line_slopeX = float(outX.fit_report(min_correl=0.25).split( + 'line_slope:')[1].split('+/-')[0]) * contmX err_line_slopeX = float( outX.fit_report(min_correl=0.25).split('line_slope:')[1].split('+/-')[1].split('(')[0]) * contmX - line_interceptX = float(outX.fit_report(min_correl=0.25).split('line_intercept:')[1].split('+/-')[0]) * contmX + line_interceptX = float(outX.fit_report(min_correl=0.25).split( + 'line_intercept:')[1].split('+/-')[0]) * contmX err_line_interceptX = float( outX.fit_report(min_correl=0.25).split('line_intercept:')[1].split('+/-')[1].split('(')[0]) * contmX - sigmaX = float(outX.fit_report(min_correl=0.25).split('g_sigma:')[1].split('+/-')[0]) - err_sigmaX = float(outX.fit_report(min_correl=0.25).split('g_sigma:')[1].split('+/-')[1].split('(')[0]) + sigmaX = float(outX.fit_report(min_correl=0.25).split( + 'g_sigma:')[1].split('+/-')[0]) + err_sigmaX = float(outX.fit_report(min_correl=0.25).split( + 'g_sigma:')[1].split('+/-')[1].split('(')[0]) - fwhmX = float(outX.fit_report(min_correl=0.25).split('g_fwhm:')[1].split('+/-')[0]) - err_fwhmX = float(outX.fit_report(min_correl=0.25).split('g_fwhm:')[1].split('+/-')[1].split('(')[0]) + fwhmX = float(outX.fit_report(min_correl=0.25).split( + 'g_fwhm:')[1].split('+/-')[0]) + err_fwhmX = float(outX.fit_report(min_correl=0.25).split( + 'g_fwhm:')[1].split('+/-')[1].split('(')[0]) - centerX = float(outX.fit_report(min_correl=0.25).split('g_center:')[1].split('+/-')[0]) - err_centerX = float(outX.fit_report(min_correl=0.25).split('g_center:')[1].split('+/-')[1].split('(')[0]) + centerX = float(outX.fit_report(min_correl=0.25).split( + 'g_center:')[1].split('+/-')[0]) + err_centerX = float(outX.fit_report(min_correl=0.25).split( + 'g_center:')[1].split('+/-')[1].split('(')[0]) return sigmaX, err_sigmaX, fwhmX, err_fwhmX, centerX, err_centerX -def produceObj(x,y,chip, ra, dec, pa): + +def produceObj(x, y, chip, ra, dec, pa): pos_img = galsim.PositionD(x, y) param = {} @@ -104,22 +114,22 @@ def produceObj(x,y,chip, ra, dec, pa): obj = Star(param) header_wcs = generateExtensionHeader(chip, - xlen=chip.npix_x, - ylen=chip.npix_y, - ra=ra, - dec=dec, - pa=pa, - gain=chip.gain, - readout=chip.read_noise, - dark=chip.dark_noise, - saturation=90000, - row_num=chip.rowID, - col_num=chip.colID, - pixel_scale=chip.pix_scale, - pixel_size=chip.pix_size, - xcen=chip.x_cen, - ycen=chip.y_cen, - extName='SCI') + xlen=chip.npix_x, + ylen=chip.npix_y, + ra=ra, + dec=dec, + pa=pa, + gain=chip.gain, + readout=chip.read_noise, + dark=chip.dark_noise, + saturation=90000, + row_num=chip.rowID, + col_num=chip.colID, + pixel_scale=chip.pix_scale, + pixel_size=chip.pix_size, + xcen=chip.x_cen, + ycen=chip.y_cen, + extName='SCI') chip_wcs = galsim.FitsWCS(header=header_wcs) param["ra"] = chip_wcs.posToWorld(pos_img).ra.deg @@ -143,50 +153,56 @@ def produceObj(x,y,chip, ra, dec, pa): class TestSpecDisperse(unittest.TestCase): def __init__(self, methodName='runTest'): - super(TestSpecDisperse,self).__init__(methodName) + super(TestSpecDisperse, self).__init__(methodName) self.filePath('csst_msc_sim/test_sls_and_straylight') - + # self.conff = conff # self.throughputf = throughputf - def filePath(self, file_name): fn = os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), file_name) - self.conff= os.path.join(fn, 'CSST_GI2.conf') - self.throughputf= os.path.join(fn, 'GI.Throughput.1st.fits') + self.conff = os.path.join(fn, 'CSST_GI2.conf') + self.throughputf = os.path.join(fn, 'GI.Throughput.1st.fits') self.testDir = fn - self.outDataFn = os.path.join(fn,'output') + self.outDataFn = os.path.join(fn, 'output') if os.path.isdir(self.outDataFn): pass else: os.mkdir(self.outDataFn) def test_rotate901(self): - m = np.array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20],[21,22,23,24,25]]) - m1 = np.array([[21,16,11,6,1],[22,17,12,7,2],[23,18,13,8,3],[24,19,14,9,4],[25,20,15,10,5]]) - m2 = np.array([[5,10,15,20,25],[4,9,14,19,24],[3,8,13,18,23],[2,7,12,17,22],[1,6,11,16,21]]) + m = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [ + 16, 17, 18, 19, 20], [21, 22, 23, 24, 25]]) + m1 = np.array([[21, 16, 11, 6, 1], [22, 17, 12, 7, 2], [ + 23, 18, 13, 8, 3], [24, 19, 14, 9, 4], [25, 20, 15, 10, 5]]) + m2 = np.array([[5, 10, 15, 20, 25], [4, 9, 14, 19, 24], [ + 3, 8, 13, 18, 23], [2, 7, 12, 17, 22], [1, 6, 11, 16, 21]]) xc = 2 yc = 2 isClockwise = 0 - m1, xc1, yc1 = rotate90(array_orig=m, xc=xc, yc=yc, isClockwise=isClockwise) + m1, xc1, yc1 = rotate90(array_orig=m, xc=xc, + yc=yc, isClockwise=isClockwise) self.assertTrue(xc1-xc == 0) self.assertTrue(yc1-yc == 0) self.assertTrue(np.sum(m-m1) == 0) def test_rotate902(self): - m = np.array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20],[21,22,23,24,25]]) - m1 = np.array([[21,16,11,6,1],[22,17,12,7,2],[23,18,13,8,3],[24,19,14,9,4],[25,20,15,10,5]]) - m2 = np.array([[5,10,15,20,25],[4,9,14,19,24],[3,8,13,18,23],[2,7,12,17,22],[1,6,11,16,21]]) + m = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [ + 16, 17, 18, 19, 20], [21, 22, 23, 24, 25]]) + m1 = np.array([[21, 16, 11, 6, 1], [22, 17, 12, 7, 2], [ + 23, 18, 13, 8, 3], [24, 19, 14, 9, 4], [25, 20, 15, 10, 5]]) + m2 = np.array([[5, 10, 15, 20, 25], [4, 9, 14, 19, 24], [ + 3, 8, 13, 18, 23], [2, 7, 12, 17, 22], [1, 6, 11, 16, 21]]) xc = 2 yc = 2 - isClockwise =1 - m1, xc1, yc1 = rotate90(array_orig=m, xc=xc, yc=yc, isClockwise=isClockwise) + isClockwise = 1 + m1, xc1, yc1 = rotate90(array_orig=m, xc=xc, + yc=yc, isClockwise=isClockwise) self.assertTrue(xc1-xc == 0) self.assertTrue(yc1-yc == 0) self.assertTrue(np.sum(m-m2) == 0) - def test_Specdistperse1(self): star = galsim.Gaussian(fwhm=0.39) @@ -236,7 +252,8 @@ class TestSpecDisperse(unittest.TestCase): ids = wave_pix < 9700 ids1 = wave_pix[ids] > 6500 print('Spec disperse flux test') - self.assertTrue(np.mean((wave_flux[ids][ids1] - sed_i(wave_pix[ids][ids1]))/sed_i(wave_pix[ids][ids1]))<0.004) + self.assertTrue(np.mean( + (wave_flux[ids][ids1] - sed_i(wave_pix[ids][ids1]))/sed_i(wave_pix[ids][ids1])) < 0.004) # plt.figure() # plt.plot(wave_pix, wave_flux) # plt.plot(sed['WAVELENGTH'], sed['FLUX']) @@ -299,14 +316,17 @@ class TestSpecDisperse(unittest.TestCase): input_em_lam = 6600 ids = wave_pix < input_em_lam+200 ids1 = wave_pix[ids] > input_em_lam-200 - deltLamda_pix = (max(wave_pix[ids][ids1]) - min(wave_pix[ids][ids1])) / (wave_pix[ids][ids1].shape[0] - 1) - _, _, fwhmx, fwhmx_err, center, center_err = fit_SingleGauss(wave_pix[ids][ids1], wave_flux[ids][ids1], 1.0, 6600) + deltLamda_pix = (max( + wave_pix[ids][ids1]) - min(wave_pix[ids][ids1])) / (wave_pix[ids][ids1].shape[0] - 1) + _, _, fwhmx, fwhmx_err, center, center_err = fit_SingleGauss( + wave_pix[ids][ids1], wave_flux[ids][ids1], 1.0, 6600) print('Emission line position and shape test') self.assertTrue(input_em_lam-center < deltLamda_pix) # print(fwhmx/deltLamda_pix*pix_scale - psf_fwhm) - self.assertTrue(fwhmx/deltLamda_pix*pix_scale - psf_fwhm < np.abs(0.02)) + self.assertTrue(fwhmx/deltLamda_pix*pix_scale - + psf_fwhm < np.abs(0.02)) # print('error is ',np.mean((wave_flux[ids][ids1] - sed_i(wave_pix[ids][ids1]))/sed_i(wave_pix[ids][ids1]))) # self.assertTrue(np.mean((wave_flux[ids][ids1] - sed_i(wave_pix[ids][ids1]))/sed_i(wave_pix[ids][ids1]))<0.004) # plt.figure() @@ -356,7 +376,6 @@ class TestSpecDisperse(unittest.TestCase): for i in range(sh[1]): spec_pix[i] = sum(Aimg[:, i]) - wave_flux = np.zeros(wave_pix.shape[0]) for i in np.arange(1, wave_pix.shape[0] - 1): w = wave_pix[i] @@ -414,14 +433,12 @@ class TestSpecDisperse(unittest.TestCase): plt.legend(['one spec', 'split in 8000 A']) plt.show() - - def test_double_disperse(self): # work_dir = "/public/home/fangyuedong/CSST_unittest/CSST/test/" # data_dir = "/Volumes/Extreme SSD/SimData/" # data_dir = "/data/simudata/CSSOSDataProductsSims/data/" configFn = os.path.join(self.testDir, 'config_C6.yaml') - normFilterFn = os.path.join(self.testDir, 'SLOAN_SDSS.g.fits') + normFilterFn = os.path.join(self.testDir, 'SLOAN_SDSS.g.fits') norm_star = Table.read(normFilterFn) with open(configFn, "r") as stream: try: @@ -431,9 +448,9 @@ class TestSpecDisperse(unittest.TestCase): except yaml.YAMLError as exc: print(exc) - filter_param = FilterParam() - focal_plane = FocalPlane(survey_type=config["obs_setting"]["survey_type"]) + focal_plane = FocalPlane( + survey_type=config["obs_setting"]["survey_type"]) chip = Chip(1, config=config) filter_id, filter_type = chip.getChipFilter() filt = Filter(filter_id=filter_id, filter_type=filter_type, filter_param=filter_param, @@ -442,13 +459,14 @@ class TestSpecDisperse(unittest.TestCase): psf_model = PSFGauss(chip=chip) - - wcs_fp = focal_plane.getTanWCS(float(config["obs_setting"]["ra_center"]), float(config["obs_setting"]["dec_center"]), float(config["obs_setting"]["image_rot"]) * galsim.degrees, chip.pix_scale) + wcs_fp = focal_plane.getTanWCS(float(config["obs_setting"]["ra_center"]), float( + config["obs_setting"]["dec_center"]), float(config["obs_setting"]["image_rot"]) * galsim.degrees, chip.pix_scale) chip.img = galsim.ImageF(chip.npix_x, chip.npix_y) chip.img.setOrigin(chip.bound.xmin, chip.bound.ymin) chip.img.wcs = wcs_fp - obj, pos_img = produceObj(2000,4500, chip,float(config["obs_setting"]["ra_center"]), float(config["obs_setting"]["dec_center"]), float(config["obs_setting"]["image_rot"])) + obj, pos_img = produceObj(2000, 4500, chip, float(config["obs_setting"]["ra_center"]), float( + config["obs_setting"]["dec_center"]), float(config["obs_setting"]["image_rot"])) # print(pos_img,chip.pix_scale) obj.drawObj_slitless( tel=tel, @@ -462,7 +480,8 @@ class TestSpecDisperse(unittest.TestCase): exptime=150, normFilter=norm_star) - obj, pos_img = produceObj(3685, 6500, chip,float(config["obs_setting"]["ra_center"]), float(config["obs_setting"]["dec_center"]), float(config["obs_setting"]["image_rot"])) + obj, pos_img = produceObj(3685, 6500, chip, float(config["obs_setting"]["ra_center"]), float( + config["obs_setting"]["dec_center"]), float(config["obs_setting"]["image_rot"])) obj.drawObj_slitless( tel=tel, pos_img=pos_img, @@ -475,7 +494,8 @@ class TestSpecDisperse(unittest.TestCase): exptime=150, normFilter=norm_star) - obj, pos_img = produceObj(5000, 2500, chip, float(config["obs_setting"]["ra_center"]), float(config["obs_setting"]["dec_center"]), float(config["obs_setting"]["image_rot"])) + obj, pos_img = produceObj(5000, 2500, chip, float(config["obs_setting"]["ra_center"]), float( + config["obs_setting"]["dec_center"]), float(config["obs_setting"]["image_rot"])) obj.drawObj_slitless( tel=tel, pos_img=pos_img, @@ -490,7 +510,8 @@ class TestSpecDisperse(unittest.TestCase): print('Spec double disperse test') from astropy.io import fits - fits.writeto(os.path.join(self.outDataFn,'test_sls_doubleDisp.fits'),chip.img.array, overwrite = True) + fits.writeto(os.path.join( + self.outDataFn, 'test_sls_doubleDisp.fits'), chip.img.array, overwrite=True) # plt.figure() # plt.imshow(chip.img.array) @@ -498,7 +519,7 @@ class TestSpecDisperse(unittest.TestCase): def test_SLSImage_rotation(self): from astropy.wcs import WCS - configFn = os.path.join(self.testDir,'config_C6.yaml') + configFn = os.path.join(self.testDir, 'config_C6.yaml') with open(configFn, "r") as stream: try: @@ -509,71 +530,71 @@ class TestSpecDisperse(unittest.TestCase): print(exc) chip = Chip(1, config=config) - ra=float(config["obs_setting"]["ra_center"]) - dec=float(config["obs_setting"]["dec_center"]) - pa=float(config["obs_setting"]["image_rot"]) + ra = float(config["obs_setting"]["ra_center"]) + dec = float(config["obs_setting"]["dec_center"]) + pa = float(config["obs_setting"]["image_rot"]) chip.rotate_angle = 0 header_wcs1 = generateExtensionHeader(chip, - xlen=chip.npix_x, - ylen=chip.npix_y, - ra=ra, - dec=dec, - pa=pa, - gain=chip.gain, - readout=chip.read_noise, - dark=chip.dark_noise, - saturation=90000, - pixel_scale=chip.pix_scale, - row_num=chip.rowID, - col_num=chip.colID, - extName='raw') + xlen=chip.npix_x, + ylen=chip.npix_y, + ra=ra, + dec=dec, + pa=pa, + gain=chip.gain, + readout=chip.read_noise, + dark=chip.dark_noise, + saturation=90000, + pixel_scale=chip.pix_scale, + row_num=chip.rowID, + col_num=chip.colID, + extName='raw') center = np.array([chip.npix_x / 2, chip.npix_y / 2]) h_wcs1 = WCS(header_wcs1) - x1, y1 = center + [100,0] - sky_1 = h_wcs1.pixel_to_world(x1,y1) + x1, y1 = center + [100, 0] + sky_1 = h_wcs1.pixel_to_world(x1, y1) chip = Chip(1, config=config) rot_angle = 1 chip.rotate_angle = rot_angle header_wcs2 = generateExtensionHeader(chip, - xlen=chip.npix_x, - ylen=chip.npix_y, - ra=ra, - dec=dec, - pa=pa, - gain=chip.gain, - readout=chip.read_noise, - dark=chip.dark_noise, - saturation=90000, - pixel_scale=chip.pix_scale, - row_num=chip.rowID, - col_num=chip.colID, - extName='raw') + xlen=chip.npix_x, + ylen=chip.npix_y, + ra=ra, + dec=dec, + pa=pa, + gain=chip.gain, + readout=chip.read_noise, + dark=chip.dark_noise, + saturation=90000, + pixel_scale=chip.pix_scale, + row_num=chip.rowID, + col_num=chip.colID, + extName='raw') h_wcs2 = WCS(header_wcs2) x2, y2 = h_wcs2.world_to_pixel(sky_1) - angle = getAngle132(x1,y1,0,x2,y2,0,center[0],center[1],0) + angle = getAngle132(x1, y1, 0, x2, y2, 0, center[0], center[1], 0) # print("rotation angle:" ,rot_angle ,chip.rotate_angle, angle) # self.assertTrue(rot_angle - angle < np.abs(0.001)) rot_angle = 10 - chip.rotate_angle = rot_angle + chip.rotate_angle = rot_angle header_wcs2 = generateExtensionHeader(chip, - xlen=chip.npix_x, - ylen=chip.npix_y, - ra=ra, - dec=dec, - pa=pa, - gain=chip.gain, - readout=chip.read_noise, - dark=chip.dark_noise, - saturation=90000, - pixel_scale=chip.pix_scale, - row_num=chip.rowID, - col_num=chip.colID, - extName='raw') + xlen=chip.npix_x, + ylen=chip.npix_y, + ra=ra, + dec=dec, + pa=pa, + gain=chip.gain, + readout=chip.read_noise, + dark=chip.dark_noise, + saturation=90000, + pixel_scale=chip.pix_scale, + row_num=chip.rowID, + col_num=chip.colID, + extName='raw') h_wcs2 = WCS(header_wcs2) x2, y2 = h_wcs2.world_to_pixel(sky_1) @@ -584,19 +605,19 @@ class TestSpecDisperse(unittest.TestCase): rot_angle = 50 chip.rotate_angle = rot_angle header_wcs2 = generateExtensionHeader(chip, - xlen=chip.npix_x, - ylen=chip.npix_y, - ra=ra, - dec=dec, - pa=pa, - gain=chip.gain, - readout=chip.read_noise, - dark=chip.dark_noise, - saturation=90000, - pixel_scale=chip.pix_scale, - row_num=chip.rowID, - col_num=chip.colID, - extName='raw') + xlen=chip.npix_x, + ylen=chip.npix_y, + ra=ra, + dec=dec, + pa=pa, + gain=chip.gain, + readout=chip.read_noise, + dark=chip.dark_noise, + saturation=90000, + pixel_scale=chip.pix_scale, + row_num=chip.rowID, + col_num=chip.colID, + extName='raw') h_wcs2 = WCS(header_wcs2) x2, y2 = h_wcs2.world_to_pixel(sky_1) @@ -604,7 +625,6 @@ class TestSpecDisperse(unittest.TestCase): # print(rot_angle - angle) self.assertTrue(rot_angle - angle < np.abs(0.001)) - chip = Chip(27, config=config) ra = float(config["obs_setting"]["ra_center"]) @@ -612,19 +632,19 @@ class TestSpecDisperse(unittest.TestCase): pa = float(config["obs_setting"]["image_rot"]) chip.rotate_angle = 0 header_wcs1 = generateExtensionHeader(chip, - xlen=chip.npix_x, - ylen=chip.npix_y, - ra=ra, - dec=dec, - pa=pa, - gain=chip.gain, - readout=chip.read_noise, - dark=chip.dark_noise, - saturation=90000, - pixel_scale=chip.pix_scale, - row_num=chip.rowID, - col_num=chip.colID, - extName='raw') + xlen=chip.npix_x, + ylen=chip.npix_y, + ra=ra, + dec=dec, + pa=pa, + gain=chip.gain, + readout=chip.read_noise, + dark=chip.dark_noise, + saturation=90000, + pixel_scale=chip.pix_scale, + row_num=chip.rowID, + col_num=chip.colID, + extName='raw') center = np.array([chip.npix_x / 2, chip.npix_y / 2]) h_wcs1 = WCS(header_wcs1) @@ -634,19 +654,19 @@ class TestSpecDisperse(unittest.TestCase): rot_angle = 1 chip.rotate_angle = rot_angle header_wcs2 = generateExtensionHeader(chip, - xlen=chip.npix_x, - ylen=chip.npix_y, - ra=ra, - dec=dec, - pa=pa, - gain=chip.gain, - readout=chip.read_noise, - dark=chip.dark_noise, - saturation=90000, - pixel_scale=chip.pix_scale, - row_num=chip.rowID, - col_num=chip.colID, - extName='raw') + xlen=chip.npix_x, + ylen=chip.npix_y, + ra=ra, + dec=dec, + pa=pa, + gain=chip.gain, + readout=chip.read_noise, + dark=chip.dark_noise, + saturation=90000, + pixel_scale=chip.pix_scale, + row_num=chip.rowID, + col_num=chip.colID, + extName='raw') h_wcs2 = WCS(header_wcs2) x2, y2 = h_wcs2.world_to_pixel(sky_1) @@ -657,19 +677,19 @@ class TestSpecDisperse(unittest.TestCase): rot_angle = 10 chip.rotate_angle = rot_angle header_wcs2 = generateExtensionHeader(chip, - xlen=chip.npix_x, - ylen=chip.npix_y, - ra=ra, - dec=dec, - pa=pa, - gain=chip.gain, - readout=chip.read_noise, - dark=chip.dark_noise, - saturation=90000, - pixel_scale=chip.pix_scale, - row_num=chip.rowID, - col_num=chip.colID, - extName='raw') + xlen=chip.npix_x, + ylen=chip.npix_y, + ra=ra, + dec=dec, + pa=pa, + gain=chip.gain, + readout=chip.read_noise, + dark=chip.dark_noise, + saturation=90000, + pixel_scale=chip.pix_scale, + row_num=chip.rowID, + col_num=chip.colID, + extName='raw') h_wcs2 = WCS(header_wcs2) x2, y2 = h_wcs2.world_to_pixel(sky_1) @@ -680,19 +700,19 @@ class TestSpecDisperse(unittest.TestCase): rot_angle = 50 chip.rotate_angle = rot_angle header_wcs2 = generateExtensionHeader(chip, - xlen=chip.npix_x, - ylen=chip.npix_y, - ra=ra, - dec=dec, - pa=pa, - gain=chip.gain, - readout=chip.read_noise, - dark=chip.dark_noise, - saturation=90000, - pixel_scale=chip.pix_scale, - row_num=chip.rowID, - col_num=chip.colID, - extName='raw') + xlen=chip.npix_x, + ylen=chip.npix_y, + ra=ra, + dec=dec, + pa=pa, + gain=chip.gain, + readout=chip.read_noise, + dark=chip.dark_noise, + saturation=90000, + pixel_scale=chip.pix_scale, + row_num=chip.rowID, + col_num=chip.colID, + extName='raw') h_wcs2 = WCS(header_wcs2) x2, y2 = h_wcs2.world_to_pixel(sky_1) @@ -701,11 +721,9 @@ class TestSpecDisperse(unittest.TestCase): self.assertTrue(rot_angle - angle < np.abs(0.001)) - - if __name__ == '__main__': - os.environ['UNIT_TEST_DATA_ROOT']="/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_develop/csst-simulation/tests/testData" + os.environ['UNIT_TEST_DATA_ROOT'] = "/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_develop/csst-simulation/tests/testData" testDir = os.getenv('UNIT_TEST_DATA_ROOT') # conff= os.path.join(testDir, 'CSST_GI2.conf') # throughputf= os.path.join(testDir, 'GI.Throughput.1st.fits') @@ -723,4 +741,4 @@ if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suit) # runner = unittest.TextTestRunner() - # runner.run(suit) \ No newline at end of file + # runner.run(suit) diff --git a/tests/test_Straylight.py b/tests/test_Straylight.py index 97761f7a4f7f93dcc5794a88ae5c2f78a6fd15ec..90f82a98a85da31fae83b1096be593d4634b1047 100644 --- a/tests/test_Straylight.py +++ b/tests/test_Straylight.py @@ -1,10 +1,10 @@ # -#need add environment parameter UNIT_TEST_DATA_ROOT, link to "testData/" -#linx and mac can run as follow, need modify the name of file directory -#export UNIT_TEST_DATA_ROOT=/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_develop/csst-simulation/tests/testData +# need add environment parameter UNIT_TEST_DATA_ROOT, link to "testData/" +# linx and mac can run as follow, need modify the name of file directory +# export UNIT_TEST_DATA_ROOT=/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_develop/csst-simulation/tests/testData # import unittest -from ObservationSim.Straylight import Straylight +from observation_sim.sky_background import Straylight import numpy as np import math @@ -17,8 +17,10 @@ import matplotlib.pyplot as plt import os -hubbleAverZodiacal = {'nuv':0.0035,'u':0.0163,'g':0.1109,'r':0.1471,'i':0.1568,'z':0.0953,'y':0.0283} -hubbleAverEarthShine = {'nuv':0.00024,'u':0.0051,'g':0.0506,'r':0.0591,'i':0.0568,'z':0.0315,'y':0.0090} +hubbleAverZodiacal = {'nuv': 0.0035, 'u': 0.0163, 'g': 0.1109, + 'r': 0.1471, 'i': 0.1568, 'z': 0.0953, 'y': 0.0283} +hubbleAverEarthShine = {'nuv': 0.00024, 'u': 0.0051, 'g': 0.0506, + 'r': 0.0591, 'i': 0.0568, 'z': 0.0315, 'y': 0.0090} # def transRaDec2D(ra, dec): # x1 = np.cos(dec / 57.2957795) * np.cos(ra / 57.2957795); @@ -28,63 +30,69 @@ hubbleAverEarthShine = {'nuv':0.00024,'u':0.0051,'g':0.0506,'r':0.0591,'i':0.056 def getAngle132(x1=0, y1=0, z1=0, x2=0, y2=0, z2=0, x3=0, y3=0, z3=0): - cosValue = 0; - angle = 0; + cosValue = 0 + angle = 0 - x11 = x1 - x3; - y11 = y1 - y3; - z11 = z1 - z3; + x11 = x1 - x3 + y11 = y1 - y3 + z11 = z1 - z3 - x22 = x2 - x3; - y22 = y2 - y3; - z22 = z2 - z3; + x22 = x2 - x3 + y22 = y2 - y3 + z22 = z2 - z3 - tt = np.sqrt((x11 * x11 + y11 * y11 + z11 * z11) * (x22 * x22 + y22 * y22 + z22 * z22)); + tt = np.sqrt((x11 * x11 + y11 * y11 + z11 * z11) + * (x22 * x22 + y22 * y22 + z22 * z22)) if (tt == 0): - return 0; + return 0 - cosValue = (x11 * x22 + y11 * y22 + z11 * z22) / tt; + cosValue = (x11 * x22 + y11 * y22 + z11 * z22) / tt if (cosValue > 1): - cosValue = 1; + cosValue = 1 if (cosValue < -1): - cosValue = -1; - angle = math.acos(cosValue); - return angle * 360 / (2 * math.pi); + cosValue = -1 + angle = math.acos(cosValue) + return angle * 360 / (2 * math.pi) -def calculateAnglePwithEarth(sat = np.array([0,0,0]), pointing = np.array([0,0,0]), sun = np.array([0,0,0])): + +def calculateAnglePwithEarth(sat=np.array([0, 0, 0]), pointing=np.array([0, 0, 0]), sun=np.array([0, 0, 0])): modSat = np.sqrt(sat[0]*sat[0] + sat[1]*sat[1]+sat[2]*sat[2]) - modPoint = np.sqrt(pointing[0]*pointing[0] + pointing[1]*pointing[1] + pointing[2]*pointing[2]) - withLocalZenithAngle = (pointing[0] * sat[0] + pointing[1] * sat[1] + pointing[2] * sat[2]) / (modPoint*modSat) + modPoint = np.sqrt(pointing[0]*pointing[0] + + pointing[1]*pointing[1] + pointing[2]*pointing[2]) + withLocalZenithAngle = ( + pointing[0] * sat[0] + pointing[1] * sat[1] + pointing[2] * sat[2]) / (modPoint*modSat) innerM_sat_sun = sat[0] * sun[0] + sat[1] * sun[1] + sat[2] * sun[2] cosAngle = innerM_sat_sun / (modSat * cons.au.value/1000) isInSunSide = 1 - if (cosAngle < -0.3385737): #cos109.79 - isInSunSide = -1; + if (cosAngle < -0.3385737): # cos109.79 + isInSunSide = -1 elif cosAngle >= -0.3385737 and cosAngle <= 0.3385737: - isInSunSide = 0; + isInSunSide = 0 + + return math.acos(withLocalZenithAngle)*180/math.pi, isInSunSide - return math.acos(withLocalZenithAngle)*180/math.pi,isInSunSide class TestStraylight(unittest.TestCase): - def __init__(self,methodName='runTest', filter = 'i', grating = "GI"): - super(TestStraylight,self).__init__(methodName) + def __init__(self, methodName='runTest', filter='i', grating="GI"): + super(TestStraylight, self).__init__(methodName) # print(file_name) # fn = os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), file_name) # self.pointingData = np.loadtxt(os.path.join(fn, 'Straylight_test.dat'), dtype=np.double) self.filePath('csst_msc_sim/test_sls_and_straylight') self.filter = filter self.grating = grating - + def filePath(self, file_name): fn = os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), file_name) - self.pointingData = np.loadtxt(os.path.join(fn, 'Straylight_test.dat'), dtype=np.double) + self.pointingData = np.loadtxt(os.path.join( + fn, 'Straylight_test.dat'), dtype=np.double) def test_EarthShineFilter(self): d_sh = self.pointingData.shape - sl_e_pix = np.zeros([d_sh[0],3],dtype=np.double) + sl_e_pix = np.zeros([d_sh[0], 3], dtype=np.double) for i in np.arange(d_sh[0]): # if i > 50: @@ -92,17 +100,19 @@ class TestStraylight(unittest.TestCase): ju = self.pointingData[i, 5] # pointing = transRaDec2D(self.pointingData[i, 0], self.pointingData[i, 1]) # print(ju, pointing, surveylist[i,3:9]) - sl = Straylight(jtime=ju, sat_pos=self.pointingData[i, 6:9], pointing_radec=np.array([self.pointingData[i, 0], self.pointingData[i, 1]]),sun_pos=self.pointingData[i,9:12]) + sl = Straylight(jtime=ju, sat_pos=self.pointingData[i, 6:9], pointing_radec=np.array( + [self.pointingData[i, 0], self.pointingData[i, 1]]), sun_pos=self.pointingData[i, 9:12]) e1, py = sl.calculateEarthShineFilter(filter=self.filter) - earthZenithAngle, isInSunSide = calculateAnglePwithEarth(sat=self.pointingData[i, 6:9], pointing= sl.pointing, sun=self.pointingData[i,9:12]) + earthZenithAngle, isInSunSide = calculateAnglePwithEarth( + sat=self.pointingData[i, 6:9], pointing=sl.pointing, sun=self.pointingData[i, 9:12]) # e2, _ = sl.calculateZodiacalFilter2(filter='i', sun_pos=sl.sun_pos) # e3 = sl.calculateStarLightFilter(filter='i', pointYaxis=py) # e_all = sl.calculateStrayLightFilter(filter='i') # s_pix, spec = sl.calculateStrayLightGrating(grating='GI') - sl_e_pix[i,0] = e1 + sl_e_pix[i, 0] = e1 sl_e_pix[i, 1] = earthZenithAngle sl_e_pix[i, 2] = isInSunSide - median = np.median(sl_e_pix[:,0]) + median = np.median(sl_e_pix[:, 0]) print(' average Earthshine %s: %e' % (self.filter, median)) self.assertTrue(median-hubbleAverEarthShine[self.filter] < 0.1) plt.figure() @@ -117,27 +127,29 @@ class TestStraylight(unittest.TestCase): def test_ZodiacalFilter(self): d_sh = self.pointingData.shape - sl_e_pix = np.zeros([d_sh[0],2],dtype=np.double) + sl_e_pix = np.zeros([d_sh[0], 2], dtype=np.double) for i in np.arange(d_sh[0]): ju = self.pointingData[i, 5] - sl = Straylight(jtime=ju, sat_pos=self.pointingData[i, 6:9], pointing_radec=np.array([self.pointingData[i, 0], self.pointingData[i, 1]]),sun_pos=self.pointingData[i,9:12]) - e1, _ = sl.calculateZodiacalFilter2(filter=self.filter, sun_pos=sl.sun_pos) - sl_e_pix[i,0] = e1 - sl_e_pix[i,1] = getAngle132(x1=self.pointingData[i,9], y1=self.pointingData[i,10], z1=self.pointingData[i,11], x2=sl.pointing[0], - y2=sl.pointing[1], z2=sl.pointing[2], x3=0, y3=0, z3=0) + sl = Straylight(jtime=ju, sat_pos=self.pointingData[i, 6:9], pointing_radec=np.array( + [self.pointingData[i, 0], self.pointingData[i, 1]]), sun_pos=self.pointingData[i, 9:12]) + e1, _ = sl.calculateZodiacalFilter2( + filter=self.filter, sun_pos=sl.sun_pos) + sl_e_pix[i, 0] = e1 + sl_e_pix[i, 1] = getAngle132(x1=self.pointingData[i, 9], y1=self.pointingData[i, 10], z1=self.pointingData[i, 11], x2=sl.pointing[0], + y2=sl.pointing[1], z2=sl.pointing[2], x3=0, y3=0, z3=0) plt.figure() plt.plot(sl_e_pix[:, 0], sl_e_pix[:, 1], 'r.') plt.xlabel('straylight-zodiacal(e-/pixel/s)') plt.ylabel('Angle between pointing and sun(degree)') plt.show() - median = np.median(sl_e_pix[:,0]) + median = np.median(sl_e_pix[:, 0]) print(' average Zodiacal %s: %f' % (self.filter, median)) self.assertTrue(median-hubbleAverZodiacal[self.filter] < 0.1) def test_StarFilter(self): d_sh = self.pointingData.shape - sl_e_pix = np.zeros(d_sh[0],dtype=np.double) + sl_e_pix = np.zeros(d_sh[0], dtype=np.double) tnum = 10 for i in np.arange(tnum): @@ -146,20 +158,21 @@ class TestStraylight(unittest.TestCase): ju = self.pointingData[i, 5] # pointing = transRaDec2D(self.pointingData[i, 0], self.pointingData[i, 1]) # print(ju, pointing, surveylist[i,3:9]) - sl = Straylight(jtime=ju, sat_pos=self.pointingData[i, 6:9], pointing_radec=np.array([self.pointingData[i, 0], self.pointingData[i, 1]]),sun_pos=self.pointingData[i,9:12]) + sl = Straylight(jtime=ju, sat_pos=self.pointingData[i, 6:9], pointing_radec=np.array( + [self.pointingData[i, 0], self.pointingData[i, 1]]), sun_pos=self.pointingData[i, 9:12]) e1, py = sl.calculateEarthShineFilter(filter=self.filter) # e2, _ = sl.calculateZodiacalFilter2(filter='i', sun_pos=sl.sun_pos) e3 = sl.calculateStarLightFilter(filter=self.filter, pointYaxis=py) # e_all = sl.calculateStrayLightFilter(filter='i') # s_pix, spec = sl.calculateStrayLightGrating(grating='GI') sl_e_pix[i] = e3 - median = np.median(sl_e_pix[0:tnum]) + median = np.median(sl_e_pix[0:tnum]) print(' average Earthshine %s: %e' % (self.filter, median)) self.assertTrue(median-hubbleAverEarthShine[self.filter] < 0.2) def test_GratingStraylight(self): d_sh = self.pointingData.shape - sl_e_pix = np.zeros(d_sh[0],dtype=np.double) + sl_e_pix = np.zeros(d_sh[0], dtype=np.double) tnum = 10 for i in np.arange(tnum): @@ -168,7 +181,8 @@ class TestStraylight(unittest.TestCase): ju = self.pointingData[i, 5] # pointing = transRaDec2D(self.pointingData[i, 0], self.pointingData[i, 1]) # print(ju, pointing, surveylist[i,3:9]) - sl = Straylight(jtime=ju, sat_pos=self.pointingData[i, 6:9], pointing_radec=np.array([self.pointingData[i, 0], self.pointingData[i, 1]]),sun_pos=self.pointingData[i,9:12]) + sl = Straylight(jtime=ju, sat_pos=self.pointingData[i, 6:9], pointing_radec=np.array( + [self.pointingData[i, 0], self.pointingData[i, 1]]), sun_pos=self.pointingData[i, 9:12]) # e1, py = sl.calculateEarthShineFilter(filter=self.filter) # e2, _ = sl.calculateZodiacalFilter2(filter='i', sun_pos=sl.sun_pos) # e3 = sl.calculateStarLightFilter(filter=self.filter, pointYaxis=py) @@ -179,18 +193,15 @@ class TestStraylight(unittest.TestCase): plt.plot(spec['WAVELENGTH'], spec['FLUX'], 'r') plt.xlabel('WAVELENGTH') plt.ylabel('F$\lambda$(erg/s/cm2/A/arcsec2)') - plt.xlim(2000,10000) + plt.xlim(2000, 10000) plt.show() - median = np.median(sl_e_pix[0:tnum]) + median = np.median(sl_e_pix[0:tnum]) print(' average Earthshine %s: %e' % (self.grating, median)) self.assertTrue(median < 0.8) - - - if __name__ == '__main__': - os.environ['UNIT_TEST_DATA_ROOT']="/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_develop/csst-simulation/tests/testData" + os.environ['UNIT_TEST_DATA_ROOT'] = "/Users/zhangxin/Work/SlitlessSim/CSST_SIM/CSST_develop/csst-simulation/tests/testData" # suit = unittest.TestSuite() # case1 = TestStraylight('test_EarthShineFilter', filter = 'i') @@ -201,4 +212,4 @@ if __name__ == '__main__': # suit.addTest(case3) # case4 = TestStraylight('test_GratingStraylight', grating = 'GI') # suit.addTest(case4) - # unittest.TextTestRunner(verbosity=2).run(suit) \ No newline at end of file + # unittest.TextTestRunner(verbosity=2).run(suit) diff --git a/tests/test_astrometry.py b/tests/test_astrometry.py new file mode 100644 index 0000000000000000000000000000000000000000..3e84e7d4bac1508c9c371fe774d10339d39ccf12 --- /dev/null +++ b/tests/test_astrometry.py @@ -0,0 +1,57 @@ +import unittest +import os +import sys +from astropy.time import Time +from datetime import datetime + +from observation_sim.astrometry.Astrometry_util import on_orbit_obs_position + + +class TestAstrometry(unittest.TestCase): + def __init__(self, methodName='runTest'): + super(TestAstrometry, self).__init__(methodName) + # self.dataPath = os.path.join( + # os.getenv('UNIT_TEST_DATA_ROOT'), 'csst_msc_sim/csst_fz_msc') + + def test_astrometry_method(self): + ra_list = [300.061827] + dec_list = [-60.132741] + pmra_list = [0.] + pmdec_list = [0.] + rv_list = [0.] + parallax_list = [1e-9] + sat_x = 5227.7501 + sat_y = -1521.2218 + sat_z = -4007.7662 + sat_vx = 0.13581745522969868 + sat_vy = 7.233066646238058 + sat_vz = -2.5770060087052116 + dt = datetime.utcfromtimestamp( + Time(2461865.75468577, format='jd').unix) + 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=len(ra_list), + input_x=sat_x, + input_y=sat_y, + input_z=sat_z, + input_vx=sat_vx, + input_vy=sat_vy, + input_vz=sat_vz, + input_epoch="J2000", + input_date_str=date_str, + input_time_str=time_str + ) + print(ra_arr[0], dec_arr[0]) + self.assertTrue(ra_arr[0] != ra_list[0]) + self.assertTrue(dec_arr[0] != dec_list[0]) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_darknoise_func.py b/tests/test_darknoise_func.py index 92a1e5d36eed4d7639b3c3b362d90e0ad7afaca4..42bf398a5b4d5114f67377aff8f45931843e191d 100644 --- a/tests/test_darknoise_func.py +++ b/tests/test_darknoise_func.py @@ -1,19 +1,22 @@ import unittest -import sys,os,math +import sys +import os +import math from itertools import islice import numpy as np import galsim import yaml -from ObservationSim.Instrument import Chip, Filter, FilterParam, FocalPlane -#from ObservationSim.Instrument.Chip import ChipUtils as chip_utils +from observation_sim.instruments import Chip, Filter, FilterParam, FocalPlane ### test FUNCTION --- START ### + + def get_base_img(img, chip, read_noise, readout_time, dark_noise, exptime=150., InputDark=None): if InputDark == None: # base_level = read_noise**2 + dark_noise*(exptime+0.5*readout_time) - ## base_level = dark_noise*(exptime+0.5*readout_time) + # base_level = dark_noise*(exptime+0.5*readout_time) base_level = dark_noise*(exptime) base_img1 = base_level * np.ones_like(img.array) else: @@ -25,8 +28,8 @@ def get_base_img(img, chip, read_noise, readout_time, dark_noise, exptime=150., arr = np.broadcast_to(arr, (ny, nx)) base_img2 = np.zeros_like(img.array) base_img2[:ny, :] = arr - base_img2[ny:, :] = arr[::-1,:] - base_img2[:,:] = base_img2[:,:]*(readout_time/ny)*dark_noise + base_img2[ny:, :] = arr[::-1, :] + base_img2[:, :] = base_img2[:, :]*(readout_time/ny)*dark_noise return base_img1+base_img2 ### test FUNCTION --- END ### @@ -35,16 +38,18 @@ def defineCCD(iccd, config_file): with open(config_file, "r") as stream: try: config = yaml.safe_load(stream) - #for key, value in config.items(): + # for key, value in config.items(): # print (key + " : " + str(value)) except yaml.YAMLError as exc: print(exc) chip = Chip(chipID=iccd, config=config) chip.img = galsim.ImageF(chip.npix_x, chip.npix_y) focal_plane = FocalPlane(chip_list=[iccd]) - chip.img.wcs= focal_plane.getTanWCS(192.8595, 27.1283, -113.4333*galsim.degrees, chip.pix_scale) + chip.img.wcs = focal_plane.getTanWCS( + 192.8595, 27.1283, -113.4333*galsim.degrees, chip.pix_scale) return chip + def defineFilt(chip): filter_param = FilterParam() filter_id, filter_type = chip.getChipFilter() @@ -60,7 +65,8 @@ def defineFilt(chip): class detModule_coverage(unittest.TestCase): def __init__(self, methodName='runTest'): super(detModule_coverage, self).__init__(methodName) - self.dataPath = os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), 'csst_msc_sim/csst_fz_msc') + self.dataPath = os.path.join( + os.getenv('UNIT_TEST_DATA_ROOT'), 'csst_msc_sim/csst_fz_msc') self.iccd = 1 def test_add_dark(self): @@ -70,16 +76,19 @@ class detModule_coverage(unittest.TestCase): print(chip.chipID) print(chip.cen_pix_x, chip.cen_pix_y) - exptime=150. - base_img = get_base_img(img=chip.img, chip=chip, read_noise=chip.read_noise, readout_time=chip.readout_time, dark_noise=chip.dark_noise, exptime=exptime, InputDark=None) + exptime = 150. + base_img = get_base_img(img=chip.img, chip=chip, read_noise=chip.read_noise, + readout_time=chip.readout_time, dark_noise=chip.dark_noise, exptime=exptime, InputDark=None) ny = int(chip.npix_y/2) - self.assertTrue( np.abs(np.max(base_img) - (exptime*chip.dark_noise+(ny-1)*(chip.readout_time/ny)*chip.dark_noise )) < 1e-6 ) - self.assertTrue( np.min(base_img) == 3 ) + self.assertTrue(np.abs(np.max(base_img) - (exptime*chip.dark_noise + + (ny-1)*(chip.readout_time/ny)*chip.dark_noise)) < 1e-6) + self.assertTrue(np.min(base_img) == 3) - base_img = get_base_img(img=chip.img, chip=chip, read_noise=chip.read_noise, readout_time=chip.readout_time, dark_noise=chip.dark_noise, exptime=150., InputDark="testTag") - self.assertTrue( np.abs(np.max(base_img) - ((ny-1)*(chip.readout_time/ny)*chip.dark_noise )) < 1e-6 ) - + base_img = get_base_img(img=chip.img, chip=chip, read_noise=chip.read_noise, + readout_time=chip.readout_time, dark_noise=chip.dark_noise, exptime=150., InputDark="testTag") + self.assertTrue(np.abs(np.max(base_img) - ((ny-1) * + (chip.readout_time/ny)*chip.dark_noise)) < 1e-6) if __name__ == '__main__': diff --git a/tests/test_effect_unit.py b/tests/test_effect_unit.py index d77c9b0bd84e8b0faeebb90270e953be9005ecf2..2a3bc46b9a029f8f767aa17ca9ae3be3b35dd6ba 100644 --- a/tests/test_effect_unit.py +++ b/tests/test_effect_unit.py @@ -1,9 +1,12 @@ import unittest import numpy as np -from ObservationSim.Instrument.Chip import Effects +from observation_sim.instruments.chip import effects import galsim import matplotlib.pyplot as plt -import os,sys,math,copy +import os +import sys +import math +import copy from numpy.random import Generator, PCG64 import warnings from astropy.io import fits @@ -13,20 +16,20 @@ warnings.filterwarnings("ignore", '.*Numba.*',) width = 9216 height = 9232 + class DetTest(unittest.TestCase): def __init__(self, methodName='runTest'): - super(DetTest,self).__init__(methodName) + super(DetTest, self).__init__(methodName) self.filePath('csst_msc_sim/test_sls_and_straylight') def filePath(self, file_name): self.datafn = os.path.join(os.getenv('UNIT_TEST_DATA_ROOT'), file_name) - self.outDataFn = os.path.join(self.datafn,'output') + self.outDataFn = os.path.join(self.datafn, 'output') if os.path.isdir(self.outDataFn): pass else: os.mkdir(self.outDataFn) - def test_prnu(self): ''' @@ -35,13 +38,14 @@ class DetTest(unittest.TestCase): print('PRNU Test:') sigma = 0.01 seed = 20210911 - prnuimg = Effects.PRNU_Img(width, height, sigma=sigma, seed=seed) + prnuimg = effects.PRNU_Img(width, height, sigma=sigma, seed=seed) meanval, stdval = np.mean(prnuimg.array), np.std(prnuimg.array) - print(' Mean & STDDEV of PRNU image are %6.4f & %6.4f.' % (meanval, stdval)) + print(' Mean & STDDEV of PRNU image are %6.4f & %6.4f.' % + (meanval, stdval)) print(' PRNU Image Array:') - print(' ',prnuimg.array) - self.assertTrue(np.abs(meanval-1)<1e-6) - self.assertTrue(np.abs(stdval-sigma)<0.002) + print(' ', prnuimg.array) + self.assertTrue(np.abs(meanval-1) < 1e-6) + self.assertTrue(np.abs(stdval-sigma) < 0.002) print('\nUnit test for PRNU has been passed.') del prnuimg @@ -50,15 +54,17 @@ class DetTest(unittest.TestCase): Test add dark current to image. Expected result: an image with dark current 3.4 e- and noise=1.844 e-. ''' rng_poisson = galsim.BaseDeviate(20210911) - dark_noise = galsim.DeviateNoise(galsim.PoissonDeviate(rng_poisson, 0.02*(150+0.5*40))) - img = galsim.Image(200,200,dtype=np.float32, init_value=0) - print('Initial Mean & STD = %6.3f & %6.3f' % (np.mean(img.array), np.std(img.array))) + dark_noise = galsim.DeviateNoise( + galsim.PoissonDeviate(rng_poisson, 0.02*(150+0.5*40))) + img = galsim.Image(200, 200, dtype=np.float32, init_value=0) + print('Initial Mean & STD = %6.3f & %6.3f' % + (np.mean(img.array), np.std(img.array))) img.addNoise(dark_noise) meanval = np.mean(img.array) stdval = np.std(img.array) print('Dark added Mean & STD = %6.3f & %6.3f' % (meanval, stdval)) - self.assertTrue(np.abs(meanval-3.4)<0.05) - self.assertTrue(np.abs(stdval-1.844)<0.02) + self.assertTrue(np.abs(meanval-3.4) < 0.05) + self.assertTrue(np.abs(stdval-1.844) < 0.02) print('\nUnit test for dark current has been passed.') del img @@ -66,149 +72,161 @@ class DetTest(unittest.TestCase): ''' Test saturation and bleeding. Expected result: an image with bleeding effect. ''' - img = galsim.Image(500,500,dtype=np.float32) - star = galsim.Gaussian(flux=60e5,fwhm=3) - img = star.drawImage(image=img,center=(150,200)) + img = galsim.Image(500, 500, dtype=np.float32) + star = galsim.Gaussian(flux=60e5, fwhm=3) + img = star.drawImage(image=img, center=(150, 200)) # gal = galsim.Sersic(n=1, half_light_radius=3,flux=50e5) # img = gal.drawImage(image=img,center=(350,300)) img.addNoise(galsim.GaussianNoise(sigma=7)) # plt.imshow(img.array) # plt.show() - filename1 = os.path.join(self.outDataFn,'test_satu_initimg.fits') + filename1 = os.path.join(self.outDataFn, 'test_satu_initimg.fits') img.write(filename1) - newimg = Effects.SaturBloom(img, fullwell=9e4) + newimg = effects.SaturBloom(img, fullwell=9e4) # plt.imshow(newimg.array) # plt.show() - filename2 = os.path.join(self.outDataFn,'test_satu_bleedimg.fits') + filename2 = os.path.join(self.outDataFn, 'test_satu_bleedimg.fits') newimg.write(filename2) - del img,newimg, star + del img, newimg, star def test_nonlinear(self): ''' Test non-linear effect. Expected result: an image with non-linearity effect. ''' - imgarr = np.arange(1,9e4,4).reshape((150,150)) + imgarr = np.arange(1, 9e4, 4).reshape((150, 150)) img = galsim.Image(copy.deepcopy(imgarr)) - filename1 = os.path.join(self.outDataFn,'test_nonlinear_initimg.fits') + filename1 = os.path.join(self.outDataFn, 'test_nonlinear_initimg.fits') img.write(filename1) - newimg = Effects.NonLinearity(img, beta1=5E-7, beta2=0) - filename2 = os.path.join(self.outDataFn,'test_nonlinear_finalimg.fits') + newimg = effects.NonLinearity(img, beta1=5E-7, beta2=0) + filename2 = os.path.join( + self.outDataFn, 'test_nonlinear_finalimg.fits') newimg.write(filename2) plt.scatter(imgarr.flatten(), newimg.array.flatten(), s=2, alpha=0.5) - plt.plot([-1e3,9e4],[-1e3,9e4],color='black', lw=1, ls='--') + plt.plot([-1e3, 9e4], [-1e3, 9e4], color='black', lw=1, ls='--') plt.xlabel('input (e-)') plt.ylabel('output (e-)') - plt.savefig(os.path.join(self.outDataFn,'test_nonlinearity.png'), dpi=200) + plt.savefig(os.path.join(self.outDataFn, + 'test_nonlinearity.png'), dpi=200) plt.show() - del img,newimg,imgarr + del img, newimg, imgarr def test_badpixel_HtrDtr(self): - img = galsim.Image(500,500,init_value=1000) + img = galsim.Image(500, 500, init_value=1000) rgbadpix = Generator(PCG64(20210911)) badfraction = 5E-5*(rgbadpix.random()*0.5+0.7) - img = Effects.DefectivePixels(img, IfHotPix=True, IfDeadPix=True, fraction=badfraction, seed=20210911, biaslevel=0) - img.write(os.path.join(self.outDataFn,'test_badpixel_HtrDtr.fits')) + img = effects.DefectivePixels( + img, IfHotPix=True, IfDeadPix=True, fraction=badfraction, seed=20210911, biaslevel=0) + img.write(os.path.join(self.outDataFn, 'test_badpixel_HtrDtr.fits')) del img + def test_badpixel_HfsDtr(self): - img = galsim.Image(500,500,init_value=1000) + img = galsim.Image(500, 500, init_value=1000) rgbadpix = Generator(PCG64(20210911)) badfraction = 5E-5*(rgbadpix.random()*0.5+0.7) - img = Effects.DefectivePixels(img, IfHotPix=False, IfDeadPix=True, fraction=badfraction, seed=20210911, biaslevel=0) - img.write(os.path.join(self.outDataFn,'test_badpixel_HfsDtr.fits')) + img = effects.DefectivePixels( + img, IfHotPix=False, IfDeadPix=True, fraction=badfraction, seed=20210911, biaslevel=0) + img.write(os.path.join(self.outDataFn, 'test_badpixel_HfsDtr.fits')) del img + def test_badpixel_HtrDfs(self): - img = galsim.Image(500,500,init_value=1000) + img = galsim.Image(500, 500, init_value=1000) rgbadpix = Generator(PCG64(20210911)) badfraction = 5E-5*(rgbadpix.random()*0.5+0.7) - img = Effects.DefectivePixels(img, IfHotPix=True, IfDeadPix=False, fraction=badfraction, seed=20210911, biaslevel=0) - img.write(os.path.join(self.outDataFn,'test_badpixel_HtrDfs.fits')) + img = effects.DefectivePixels( + img, IfHotPix=True, IfDeadPix=False, fraction=badfraction, seed=20210911, biaslevel=0) + img.write(os.path.join(self.outDataFn, 'test_badpixel_HtrDfs.fits')) del img + def test_badpixel_HfsDfs(self): - img = galsim.Image(500,500,init_value=1000) + img = galsim.Image(500, 500, init_value=1000) rgbadpix = Generator(PCG64(20210911)) badfraction = 5E-5*(rgbadpix.random()*0.5+0.7) - img = Effects.DefectivePixels(img, IfHotPix=False, IfDeadPix=False, fraction=badfraction, seed=20210911, biaslevel=0) - img.write(os.path.join(self.outDataFn,'test_badpixel_HfsDfs.fits')) + img = effects.DefectivePixels( + img, IfHotPix=False, IfDeadPix=False, fraction=badfraction, seed=20210911, biaslevel=0) + img.write(os.path.join(self.outDataFn, 'test_badpixel_HfsDfs.fits')) del img def test_badlines(self): - img = galsim.Image(500,500,init_value=-1000) + img = galsim.Image(500, 500, init_value=-1000) img.addNoise(galsim.GaussianNoise(sigma=7)) - newimg = Effects.BadColumns(copy.deepcopy(img), seed=20210911) - newimg.write(os.path.join(self.outDataFn,'test_badlines.fits')) - del newimg,img + newimg = effects.BadColumns(copy.deepcopy(img), seed=20210911) + newimg.write(os.path.join(self.outDataFn, 'test_badlines.fits')) + del newimg, img # def test_cte(self): # img = galsim.Image(200,200,init_value=1000) # img.array[50,80] = 1e4 # img.array[150,150] = 3e4 - # newimgcol = Effects.CTE_Effect(copy.deepcopy(img),direction='column') - # newimgrow = Effects.CTE_Effect(copy.deepcopy(img),direction='row') + # newimgcol = effects.CTE_Effect(copy.deepcopy(img),direction='column') + # newimgrow = effects.CTE_Effect(copy.deepcopy(img),direction='row') # newimgcol.write(os.path.join(self.outDataFn,'test_ctecol.fits')) # newimgrow.write(os.path.join(self.outDataFn,'test_cterow.fits')) # del img,newimgcol,newimgrow def test_readnoise(self): - img = galsim.Image(200,200,init_value=1000) + img = galsim.Image(200, 200, init_value=1000) seed = 20210911 rng_readout = galsim.BaseDeviate(seed) readout_noise = galsim.GaussianNoise(rng=rng_readout, sigma=5) img.addNoise(readout_noise) - img.write(os.path.join(self.outDataFn,'test_readnoise.fits')) + img.write(os.path.join(self.outDataFn, 'test_readnoise.fits')) stdval = np.std(img.array) - self.assertTrue(np.abs(stdval-5)<0.01*5) + self.assertTrue(np.abs(stdval-5) < 0.01*5) print('\nUnit test for readout noise has been passed.') del img def test_addbias(self): - img = galsim.Image(200,200,init_value=0) - img = Effects.AddBiasNonUniform16(img,bias_level=500, nsecy = 2, nsecx=8,seed=20210911) + img = galsim.Image(200, 200, init_value=0) + img = effects.AddBiasNonUniform16( + img, bias_level=500, nsecy=2, nsecx=8, seed=20210911) img.write('./output/test_addbias.fits') del img def test_apply16gains(self): - img = galsim.Image(500,500,init_value=100) - img,_ = Effects.ApplyGainNonUniform16(img, gain=1.5, nsecy=2, nsecx=8, seed=202102) - img.write(os.path.join(self.outDataFn,'test_apply16gains.fits')) + img = galsim.Image(500, 500, init_value=100) + img, _ = effects.ApplyGainNonUniform16( + img, gain=1.5, nsecy=2, nsecx=8, seed=202102) + img.write(os.path.join(self.outDataFn, 'test_apply16gains.fits')) rightedge = int(500/8)*8 print('gain=%6.2f' % 1.5) - meanimg = np.mean(img.array[:,:rightedge]) - sigmaimg = np.std(img.array[:,:rightedge]) - print('mean, sigma = %6.2f, %6.2f' % (meanimg,sigmaimg)) - self.assertTrue(np.abs(meanimg-100/1.5)<1) - self.assertTrue(np.abs(sigmaimg/meanimg-0.01)<0.001) + meanimg = np.mean(img.array[:, :rightedge]) + sigmaimg = np.std(img.array[:, :rightedge]) + print('mean, sigma = %6.2f, %6.2f' % (meanimg, sigmaimg)) + self.assertTrue(np.abs(meanimg-100/1.5) < 1) + self.assertTrue(np.abs(sigmaimg/meanimg-0.01) < 0.001) print('\nUnit test for applying 16 channel gains has been passed.') del img - def test_cosmicray(self): - attachedSizes = np.loadtxt(os.path.join(self.datafn,'wfc-cr-attachpixel.dat')) - cr_map,_ = Effects.produceCR_Map( - xLen=500, yLen=500, exTime=150+0.5*40, - cr_pixelRatio=0.003*(1+0.5*40/150), - gain=1, attachedSizes=attachedSizes, seed=20210911) + attachedSizes = np.loadtxt(os.path.join( + self.datafn, 'wfc-cr-attachpixel.dat')) + cr_map, _ = effects.produceCR_Map( + xLen=500, yLen=500, exTime=150+0.5*40, + cr_pixelRatio=0.003*(1+0.5*40/150), + gain=1, attachedSizes=attachedSizes, seed=20210911) crimg = galsim.Image(cr_map) - crimg.write(os.path.join(self.outDataFn,'test_cosmicray.fits')) - del cr_map,crimg + crimg.write(os.path.join(self.outDataFn, 'test_cosmicray.fits')) + del cr_map, crimg def test_shutter(self): - img = galsim.Image(5000,5000,init_value=1000) - shuttimg = Effects.ShutterEffectArr(img, t_exp=150, t_shutter=1.3, dist_bearing=735, dt=1E-3) # shutter effect normalized image for this chip + img = galsim.Image(5000, 5000, init_value=1000) + # shutter effect normalized image for this chip + shuttimg = effects.ShutterEffectArr( + img, t_exp=150, t_shutter=1.3, dist_bearing=735, dt=1E-3) img *= shuttimg - img.write(os.path.join(self.outDataFn,'test_shutter.fits')) + img.write(os.path.join(self.outDataFn, 'test_shutter.fits')) del img def test_vignette(self): - img = galsim.Image(2000,2000,init_value=1000) + img = galsim.Image(2000, 2000, init_value=1000) print(img.bounds) # # img.bounds = galsim.BoundsI(1, width, 1, height) - img.setOrigin(10000,10000) - flat_img = Effects.MakeFlatSmooth(img.bounds,20210911) + img.setOrigin(10000, 10000) + flat_img = effects.MakeFlatSmooth(img.bounds, 20210911) flat_normal = flat_img / np.mean(flat_img.array) - flat_normal.write(os.path.join(self.outDataFn,'test_vignette.fits')) - del flat_img,img,flat_normal - + flat_normal.write(os.path.join(self.outDataFn, 'test_vignette.fits')) + del flat_img, img, flat_normal if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() diff --git a/tests/test_field_distortion.py b/tests/test_field_distortion.py new file mode 100644 index 0000000000000000000000000000000000000000..0f77edbe4062a24d36f90bb07963045b700b4bc9 --- /dev/null +++ b/tests/test_field_distortion.py @@ -0,0 +1,517 @@ +import unittest + +import numpy as np +import galsim +import os +import sys +from astropy.table import Table +from scipy import interpolate +import pickle + + +class test_field_distortion(unittest.TestCase): + def __init__(self, methodName="runTest"): + super(test_field_distortion, self).__init__(methodName) + self.dataMainPath = os.path.join( + os.getenv("UNIT_TEST_DATA_ROOT"), "csst_msc_sim/field_distortion" + ) + self.dataInputPath = os.path.join(self.dataMainPath, "input_catalog") + self.fdModelName = "FieldDistModel_v2.0_test.pickle" + + def test_fd_model(self): + cat_dir = self.dataInputPath + model_dir = self.dataMainPath + model_date = "2024-05-08" + model_name = self.fdModelName + field_distortion_model( + cat_dir, + model_dir, + poly_degree=4, + model_date=model_date, + model_name=model_name, + ) + + def test_fd_apply(self): + model_name = self.fdModelName + model_dir = self.dataMainPath + cat_dir = self.dataMainPath + field_distortion_apply( + model_name, model_dir, cat_dir, ra_cen=60.0, dec_cen=-40.0, img_rot=0.0 + ) + + +def ccdParam(): + """ + Basic CCD size and noise parameters. + """ + # CCD size + xt, yt = 59516, 49752 + x0, y0 = 9216, 9232 + xgap, ygap = (534, 1309), 898 + xnchip, ynchip = 6, 5 + ccdSize = xt, yt, x0, y0, xgap, ygap, xnchip, ynchip + + # other parameters + readNoise = 5.0 # e/pix + darkNoise = 0.02 # e/pix/s + pixel_scale = 0.074 # pixel scale + gain = 1.0 + ccdBase = readNoise, darkNoise, pixel_scale, gain + + return ccdSize, ccdBase + + +def chipLim(chip): + ccdSize, ccdBase = ccdParam() + xt, yt, x0, y0, gx, gy, xnchip, ynchip = ccdSize + gx1, gx2 = gx + + rowID = ((chip - 1) % 5) + 1 + colID = 6 - ((chip - 1) // 5) + + xrem = 2 * (colID - 1) - (xnchip - 1) + xcen = (x0 // 2 + gx1 // 2) * xrem + if chip <= 5 or chip == 10: + xcen = (x0 // 2 + gx1 // 2) * xrem + (gx2 - gx1) + if chip >= 26 or chip == 21: + xcen = (x0 // 2 + gx1 // 2) * xrem - (gx2 - gx1) + nx0 = xcen - x0 // 2 + 1 + nx1 = xcen + x0 // 2 + + yrem = (rowID - 1) - ynchip // 2 + ycen = (y0 + gy) * yrem + ny0 = ycen - y0 // 2 + 1 + ny1 = ycen + y0 // 2 + + return nx0, nx1, ny0, ny1 + + +def chip_filter(nchip): + """ + return filter name of a given chip + """ + filtype = ["nuv", "u", "g", "r", "i", "z", "y"] + + # updated configurations + # if nchip>24 or nchip<7: raise ValueError("!!! Chip ID: [7,24]") + if nchip in [6, 15, 16, 25]: + filter_name = "y" + if nchip in [11, 20]: + filter_name = "z" + if nchip in [7, 24]: + filter_name = "i" + if nchip in [14, 17]: + filter_name = "u" + if nchip in [9, 22]: + filter_name = "r" + if nchip in [12, 13, 18, 19]: + filter_name = "nuv" + if nchip in [8, 23]: + filter_name = "g" + + filter_id = filtype.index(filter_name) + + return filter_id, filter_name + + +def skyLim(wcs, x0, x1, y0, y1): + """ + The sky coverage of a single exposure image + """ + r2d = 180.0 / np.pi + # xt, yt, x0, y0, gx, gy, xnchip, ynchip = ccdSize() + s1 = wcs.toWorld(galsim.PositionD(x0, y0)) + s2 = wcs.toWorld(galsim.PositionD(x0, y1)) + + s3 = wcs.toWorld(galsim.PositionD(x1, y0)) + s4 = wcs.toWorld(galsim.PositionD(x1, y1)) + ra = [s1.ra.rad * r2d, s2.ra.rad * r2d, s3.ra.rad * r2d, s4.ra.rad * r2d] + dec = [s1.dec.rad * r2d, s2.dec.rad * r2d, s3.dec.rad * r2d, s4.dec.rad * r2d] + + return min(ra), max(ra), min(dec), max(dec) + + +def wcsMain(imgRotation=0.0, raCenter=0.0, decCenter=0.0): + ccdSize, ccdBase = ccdParam() + xsize, ysize, _, _, _, _, _, _ = ccdSize + _, _, pixelScale, _ = ccdBase + xmcen, ymcen = 0.0, 0.0 + imrot = imgRotation * galsim.degrees + racen = raCenter * galsim.degrees + deccen = decCenter * galsim.degrees + + # define the wcs + dudx = -np.cos(imrot.rad) * pixelScale + dudy = +np.sin(imrot.rad) * pixelScale + dvdx = -np.sin(imrot.rad) * pixelScale + dvdy = -np.cos(imrot.rad) * pixelScale + moscen = galsim.PositionD(x=xmcen, y=ymcen) + skyCenter = galsim.CelestialCoord(ra=racen, dec=deccen) + affine = galsim.AffineTransform(dudx, dudy, dvdx, dvdy, origin=moscen) + wcs = galsim.TanWCS(affine, skyCenter, units=galsim.arcsec) + + return wcs + + +# FD model +def field_distortion_model( + cat_dir, + model_dir, + poly_degree=4, + model_date="2024-05-08", + model_name="FieldDistModel_v2.0_test.pickle", +): + # default parameter setup + nccd, nwave, npsf = 30, 4, 30 * 30 + + # load a CSST-like wcs + wcs = wcsMain() + cd11, cd12 = wcs.cd[0, 0], wcs.cd[0, 1] + cd21, cd22 = wcs.cd[1, 0], wcs.cd[1, 1] + xmcen, ymcen = wcs.crpix + + # obtain the interpolation model + fdFunList = {} + fdFunList["date"] = model_date + for iwave in range(1, nwave + 1): + # if iwave!=1: continue + iwaveKey = "wave%d" % iwave + + # first construct the global interpolation + xwList, ywList = [], [] + xdList, ydList = [], [] + fdFunList[iwaveKey] = {} + for iccd in range(1, nccd + 1): + # if iccd!=9: continue + iccdKey = "ccd" + str("0%d" % (iccd))[-2:] + + # load PSF data + ipsfDatn = os.path.join(cat_dir, "ccd%d_%s.dat" % (iccd, iwaveKey)) + ipsfDat = Table.read(ipsfDatn, format="ascii") + for ipsf in range(1, npsf + 1): + # if ipsf!=2: continue + xField = ipsfDat["field_x"][ipsf - 1] + yField = ipsfDat["field_y"][ipsf - 1] + + # image coordinate with field distortion + xImage = 100.0 * ( + ipsfDat["image_x"][ipsf - 1] + ipsfDat["centroid_x"][ipsf - 1] + ) + yImage = 100.0 * ( + ipsfDat["image_y"][ipsf - 1] + ipsfDat["centroid_y"][ipsf - 1] + ) + + # image coordinate only with wcs projection + xwcs = (cd12 * yField - cd22 * xField) / ( + cd12 * cd21 - cd11 * cd22 + ) + xmcen + ywcs = (cd21 * xField - cd11 * yField) / ( + cd12 * cd21 - cd11 * cd22 + ) + ymcen + + xwList += [xwcs] + ywList += [ywcs] + xdList += [xImage] + ydList += [yImage] + + # global interpolation + xImageFun = interpolate.SmoothBivariateSpline( + xwList, ywList, xdList, kx=poly_degree, ky=poly_degree + ) + yImageFun = interpolate.SmoothBivariateSpline( + xwList, ywList, ydList, kx=poly_degree, ky=poly_degree + ) + fdFunList[iwaveKey] = { + "xImagePos": xImageFun, + "yImagePos": yImageFun, + "interpLimit": [ + np.min(xwList), + np.max(xwList), + np.min(ywList), + np.max(ywList), + ], + } + + # construct the residual interpolation + fdFunList[iwaveKey]["residual"] = {} + for iccd in range(1, nccd + 1): + # if iccd!=1: continue + iccdKey = "ccd" + str("0%d" % (iccd))[-2:] + # open the ditortion data + ipsfDatn = os.path.join(cat_dir, "ccd%d_%s.dat" % (iccd, iwaveKey)) + ipsfDat = Table.read(ipsfDatn, format="ascii") + + ixwList, iywList = [], [] + idxList, idyList = [], [] + for ipsf in range(1, npsf + 1): + # if ipsf!=1: continue + print( + "^_^ loading: iccd-{:} iwave-{:} ipsf-{:}".format(iccd, iwave, ipsf) + ) + xField = ipsfDat["field_x"][ipsf - 1] + yField = ipsfDat["field_y"][ipsf - 1] + xImage = 100.0 * ( + ipsfDat["image_x"][ipsf - 1] + ipsfDat["centroid_x"][ipsf - 1] + ) + yImage = 100.0 * ( + ipsfDat["image_y"][ipsf - 1] + ipsfDat["centroid_y"][ipsf - 1] + ) + + # image coordinate only with wcs projection + xwcs = (cd12 * yField - cd22 * xField) / ( + cd12 * cd21 - cd11 * cd22 + ) + xmcen + ywcs = (cd21 * xField - cd11 * yField) / ( + cd12 * cd21 - cd11 * cd22 + ) + ymcen + + ixPred = xImageFun(xwcs, ywcs)[0][0] + iyPred = yImageFun(xwcs, ywcs)[0][0] + idx = xImage - ixPred + idy = yImage - iyPred + # print(idx, idy) + ixwList += [xwcs] + iywList += [ywcs] + idxList += [idx] + idyList += [idy] + + # interpolation + xResFun = interpolate.SmoothBivariateSpline( + ixwList, iywList, idxList, kx=poly_degree, ky=poly_degree + ) + yResFun = interpolate.SmoothBivariateSpline( + ixwList, iywList, idyList, kx=poly_degree, ky=poly_degree + ) + + fdFunList[iwaveKey]["residual"][iccdKey] = { + "xResidual": xResFun, + "yResidual": yResFun, + "interpLimit": [ + np.min(ixwList), + np.max(ixwList), + np.min(iywList), + np.max(iywList), + ], + } + + # save the interpolation functions + model_name_full = os.path.join(model_dir, model_name) + with open(model_name_full, "wb") as out: + pickle.dump(fdFunList, out, pickle.HIGHEST_PROTOCOL) + + return + + +def field_distortion_apply( + model_name, model_dir, cat_dir, ra_cen=60.0, dec_cen=-40.0, img_rot=0.0 +): + # CCD and observation + ccdSize, ccdBase = ccdParam() + xsize, ysize, xchip, ychip, xgap, ygap, xnchip, ynchip = ccdSize + nchip = xnchip * ynchip + + ################################################# + xmcen, ymcen = 0.0, 0.0 + ################################################# + + badchip = list(range(1, 6)) + list(range(26, 31)) + [10, 21] + + # define the wcs of the image mosaic + print( + "^_^ Construct the wcs of the entire image mosaic using Gnomonic/TAN projection" + ) + wcs = wcsMain(imgRotation=img_rot, raCenter=ra_cen, decCenter=dec_cen) + + ################################################# + # load the field distortion model + model_name_full = os.path.join(model_dir, model_name) + with open(model_name_full, "rb") as f: + fdModel = pickle.load(f) + ################################################# + + raLow, raUp, decLow, decUp = skyLim( + wcs, -xsize // 2 + 1, xsize // 2, -ysize // 2 + 1, ysize // 2 + ) + dra = (raUp - raLow) * np.cos(dec_cen * np.pi / 180.0) + ddec = decUp - decLow + print( + " Image pixel size: %d*%d; center: (Ra, Dec)=(%.3f, %.3f)." + % (xsize, ysize, ra_cen, dec_cen) + ) + print(" Field of Veiw: %.2f * %.2f deg^2." % (dra, ddec)) + + # filters and corresponding bounds in the image mosaic + fbound = {} + print(" Model the filter distributions in the image mosaic ...") + stats = {} + for i in range(nchip): + chip_id = i + 1 + if chip_id in badchip: + continue + cx0, cx1, cy0, cy1 = chipLim(chip_id) + chip_bound = galsim.BoundsD(cx0 - 1, cx1 - 1, cy0 - 1, cy1 - 1) + chip_filter_id, chip_filt = chip_filter(chip_id) + # print "^_^ CHIP %d, Filter %s"%(chip_id,chip_filter) + fbound[chip_id] = [chip_filter_id, chip_filt, chip_bound] + stats[chip_id] = [0, 0, 0] + + # generate object grid + ra_input = np.arange(ra_cen - 1.0, ra_cen + 1.0, 0.00125) + dec_input = np.arange(dec_cen - 1.0, dec_cen + 1.0, 0.00125) + nobj = len(ra_input) * len(dec_input) + crdCat = np.zeros((nobj, 2)) + cid = 0 + for id1 in range(len(ra_input)): + ira = ra_input[id1] + for id2 in range(len(dec_input)): + idec = dec_input[id2] + crdCat[cid, :] = ira, idec + cid += 1 + print("^_^ Total %d objects are generaged" % nobj) + + # main program + for i in range(nchip): + # if i not in [6]: continue + if i + 1 in badchip: + continue + filtidk, filtnmk, boundk = fbound[i + 1] + idStr = str("0%d" % (i + 1))[-2:] + + ################################################################### + # 1) Use global field distortion model: FieldDistModelGlobal_v2.0.pickle + ifdModel = fdModel["wave1"] + irsModel = fdModel["wave1"]["residual"]["ccd" + idStr] + xLowI, xUpI, yLowI, yUpI = ifdModel["interpLimit"] + xlLowI, xlUpI, ylLowI, ylUpI = irsModel["interpLimit"] + + # field distortion model along x/y-axis + ixfdModel = ifdModel["xImagePos"] + iyfdModel = ifdModel["yImagePos"] + ixrsModel = irsModel["xResidual"] + iyrsModel = irsModel["yResidual"] + + # first-order derivatives of the global field distortion model + ifx_dx = ixfdModel.partial_derivative(1, 0) + ifx_dy = ixfdModel.partial_derivative(0, 1) + ify_dx = iyfdModel.partial_derivative(1, 0) + ify_dy = iyfdModel.partial_derivative(0, 1) + # first-order derivatives of the residual field distortion model + irx_dx = ixrsModel.partial_derivative(1, 0) + irx_dy = ixrsModel.partial_derivative(0, 1) + iry_dx = iyrsModel.partial_derivative(1, 0) + iry_dy = iyrsModel.partial_derivative(0, 1) + ################################################################### + + # construct the image mosaic firstly + xorigin, yorigin = xmcen - boundk.xmin, ymcen - boundk.ymin + print(" Construct the chip mosaic ...") + fimage = galsim.ImageF(xchip, ychip) + fimage.setOrigin(boundk.xmin, boundk.ymin) + + fimage.wcs = wcs + raLow, raUp, decLow, decUp = skyLim( + wcs, boundk.xmin, boundk.xmax, boundk.ymin, boundk.ymax + ) + dra = (raUp - raLow) * np.cos(dec_cen * np.pi / 180.0) + ddec = decUp - decLow + print(" Image coverage: %.2f * %.2f arcmin^2." % (dra * 60.0, ddec * 60.0)) + # enlarge the sky coverage in order to catch the galaxies at the chip edge + raLow -= 0.2 / 60.0 + decLow -= 0.2 / 60.0 + raUp += 0.2 / 60.0 + decUp += 0.2 / 60.0 + print( + " Range: RA=[%.4f, %.4f]; DEC=[%.4f, %.4f]" + % (raLow, raUp, decLow, decUp) + ) + + # generate the galaxy and star images + catxxn = os.path.join( + cat_dir, "csst_mainfocus_field_distortion_ccd%s_%s.cat" % (idStr, filtnmk) + ) + hdrxx = "#id_obj id_chip filter ra_true dec_ture x_image_ture y_image_ture x_image y_image g1_fd g2_fd\n" + fmtxx = "%8d %3d %4s %12.6f %12.6f %13.6f %13.6f %13.6f %13.6f %9.5f %9.5f\n" + catxx = open(catxxn, "w") + catxx.write(hdrxx) + oidxx = 0 + for k in range(nobj): + # if k != 0: continue + # input galaxy parameters + rak = crdCat[k, 0] + deck = crdCat[k, 1] + + # reject objects out of the image + if (rak - raLow) * (rak - raUp) > 0.0 or (deck - decLow) * ( + deck - decUp + ) > 0.0: + continue + + world_pos = galsim.CelestialCoord( + ra=rak * galsim.degrees, dec=deck * galsim.degrees + ) + image_pos = fimage.wcs.toImage(world_pos) + xk_true = image_pos.x + yk_true = image_pos.y + + ################################################################# + # field distortion + if (xLowI - xk_true) * (xUpI - xk_true) > 0 or (yLowI - yk_true) * ( + yUpI - yk_true + ) > 0: + continue + xk = ixfdModel(xk_true, yk_true)[0][0] + yk = iyfdModel(xk_true, yk_true)[0][0] + + # global offset correction + if (xlLowI - xk) * (xlUpI - xk) > 0 or (ylLowI - yk) * (ylUpI - yk) > 0: + continue + dxk = ixrsModel(xk, yk)[0][0] + dyk = iyrsModel(xk, yk)[0][0] + xk = xk + dxk + yk = yk + dyk + + # field distortion induced ellipticity + ix_dx = ifx_dx(xk, yk) + irx_dx(xk, yk) + ix_dy = ifx_dy(xk, yk) + irx_dy(xk, yk) + iy_dx = ify_dx(xk, yk) + iry_dx(xk, yk) + iy_dy = ify_dy(xk, yk) + iry_dy(xk, yk) + + g1k_fd = 0.0 + (iy_dy - ix_dx) / (iy_dy + ix_dx) + g2k_fd = 0.0 - (iy_dx + ix_dy) / (iy_dy + ix_dx) + ################################################################# + dxk_true, dyk_true = xk_true - xmcen, yk_true - ymcen + xLock_true, yLock_true = dxk_true + xorigin + 1.0, dyk_true + yorigin + 1.0 + + dxk, dyk = xk - xmcen, yk - ymcen + xLock, yLock = dxk + xorigin + 1.0, dyk + yorigin + 1.0 + + if (xLock_true < 0) or (xLock_true > xchip): + continue + if (yLock_true < 0) or (yLock_true > ychip): + continue + if (xLock < 0) or (xLock > xchip): + continue + if (yLock < 0) or (yLock > ychip): + continue + linexx = fmtxx % ( + k + 1, + i + 1, + filtnmk.lower(), + rak, + deck, + xLock_true, + yLock_true, + xLock, + yLock, + g1k_fd[0][0], + g2k_fd[0][0], + ) + catxx.write(linexx) + + catxx.close() + + return + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_focalplane.py b/tests/test_focalplane.py index 43ea11292f42330d8f0c72fc8cdb6ed825d84687..74ab61b7ece12f2aa1ca15d3f888f437f7e84bd1 100644 --- a/tests/test_focalplane.py +++ b/tests/test_focalplane.py @@ -1,7 +1,7 @@ import unittest import os import galsim -from ObservationSim.Instrument import FocalPlane, Chip +from observation_sim.instruments import FocalPlane, Chip class TestFocalPlane(unittest.TestCase): @@ -20,12 +20,12 @@ class TestFocalPlane(unittest.TestCase): def test_fp_method(self): wcs = self.focal_plane.getTanWCS( - 192.8595, 0., 0.*galsim.degrees, 0.0074) + 192.8595, 0., 0.*galsim.degrees, 0.074) sky_coverage = self.focal_plane.getSkyCoverage( wcs, x0=-1, x1=0, y0=-1, y1=0) print(sky_coverage.area()) - self.assertTrue(abs(sky_coverage.area() - 0.0074**2/(3600.**2)) < 1e13) + self.assertTrue(abs(sky_coverage.area() - 0.074**2/(3600.**2)) < 1e13) -if __name__ == '__main_': +if __name__ == '__main__': unittest.main() diff --git a/tests/test_imaging.py b/tests/test_imaging.py index e7175d62074da17dbff4627444f18fd2a4ea306e..6fa0bca26068c2f52e459a15775f9038c7a1cbd3 100644 --- a/tests/test_imaging.py +++ b/tests/test_imaging.py @@ -15,12 +15,12 @@ import copy from astropy.cosmology import FlatLambdaCDM from astropy import constants from astropy import units as U -from ObservationSim.MockObject._util import getObservedSED -from ObservationSim.MockObject import CatalogBase, Galaxy +from observation_sim.mock_objects._util import getObservedSED +from observation_sim.mock_objects import CatalogBase, Galaxy -from ObservationSim.Instrument import Chip, Filter, FilterParam, FocalPlane -from ObservationSim.PSF.PSFInterp import PSFInterp -from ObservationSim.MockObject._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getABMAG +from observation_sim.instruments import Chip, Filter, FilterParam, FocalPlane +from observation_sim.psf.PSFInterp import PSFInterp +from observation_sim.mock_objects._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getABMAG class Catalog(CatalogBase): diff --git a/tests/test_prescan_overscan_func.py b/tests/test_prescan_overscan_func.py index 1a6a1303edc31c8b8482037f1d17248cfc7af11e..b1a11a345646204603da70045c1bda9c04b4254a 100644 --- a/tests/test_prescan_overscan_func.py +++ b/tests/test_prescan_overscan_func.py @@ -6,8 +6,7 @@ import numpy as np import galsim import yaml -from ObservationSim.Instrument import Chip, Filter, FilterParam, FocalPlane -#from ObservationSim.Instrument.Chip import ChipUtils as chip_utils +from observation_sim.instruments import Chip, Filter, FilterParam, FocalPlane ### test FUNCTION --- START ### def AddPreScan(GSImage, pre1=27, pre2=4, over1=71, over2=80, nsecy = 2, nsecx=8): diff --git a/tools/create_chip_json.py b/tools/create_chip_json.py index b08337566c48707a89550db1e837e7c25087c058..aca80c3ecc1cf2a6ee2eac9b938e8da4927fd857 100644 --- a/tools/create_chip_json.py +++ b/tools/create_chip_json.py @@ -14,17 +14,19 @@ chip_filename = 'chip_definition.json' # "npix_y": 7680, # "x_cen": -273.35, # [mm] # "y_cen": 211.36, # [mm] -# "rotate_angle": 90. # [deg] +# "rotate_angle": 90. # [deg] # } # chip_list[chip_id] = chip_dict + def get_chip_row_col_main_fp(chip_id): rowID = ((chip_id - 1) % 5) + 1 colID = 6 - ((chip_id - 1) // 5) return rowID, colID + def get_chip_center_main_fp(chip_id, pixel_size=1e-2): - + row, col = get_chip_row_col_main_fp(chip_id) npix_x = 9216 npix_y = 9232 @@ -39,16 +41,20 @@ def get_chip_center_main_fp(chip_id, pixel_size=1e-2): xcen = (npix_x//2 + gx1//2) * xrem - (gx2-gx1) if chip_id <= 5 or chip_id == 10: xcen = (npix_x//2 + gx1//2) * xrem + (gx2-gx1) - + # ylim of a given CCD chip yrem = (row - 1) - nchip_y // 2 ycen = (npix_y + gy) * yrem return xcen * pixel_size, ycen * pixel_size + def create_chip_dict_main_fp(chip_id, pixel_size=1e-2): - filter_list = ["GV", "GI", "y", "z", "y", "GI", "GU", "r", "u", "NUV", "i", "GV", "GU", "g", "NUV", "NUV", "g", "GU", "GV", "i", "NUV", "u", "r", "GU", "GI", "y", "z", "y", "GI", "GV"] - chip_label_list = [3,3,3,1,1,1,3,2,2,1,1,1,4,2,3,2,1,1,4,2,4,1,1,2,4,2,2,4,2,2] - chip_id_list = [26, 21, 16, 11, 6, 1, 27, 22, 17, 12, 7, 2, 28, 23, 18, 13, 8, 3, 29, 24, 19, 14, 9, 4, 30, 25, 20, 15, 10, 5] + filter_list = ["GV", "GI", "y", "z", "y", "GI", "GU", "r", "u", "NUV", "i", "GV", "GU", "g", + "NUV", "NUV", "g", "GU", "GV", "i", "NUV", "u", "r", "GU", "GI", "y", "z", "y", "GI", "GV"] + chip_label_list = [3, 3, 3, 1, 1, 1, 3, 2, 2, 1, 1, 1, + 4, 2, 3, 2, 1, 1, 4, 2, 4, 1, 1, 2, 4, 2, 2, 4, 2, 2] + chip_id_list = [26, 21, 16, 11, 6, 1, 27, 22, 17, 12, 7, 2, 28, + 23, 18, 13, 8, 3, 29, 24, 19, 14, 9, 4, 30, 25, 20, 15, 10, 5] npix_x = 9216 npix_y = 9232 idx = chip_id_list.index(chip_id) @@ -63,10 +69,10 @@ def create_chip_dict_main_fp(chip_id, pixel_size=1e-2): chip_dict = { "chip_name": chip_name, "pix_size": 1e-2, # [mm] - "pix_scale": 0.074, # [arcsec/pix] + "pix_scale": 0.074, # [arcsec/pix] "npix_x": npix_x, "npix_y": npix_y, - "x_cen": xcen, # [mm] + "x_cen": xcen, # [mm] "y_cen": ycen, # [mm] "rotate_angle": rotate_angle, # [deg] "n_psf_samples": 900, @@ -80,6 +86,7 @@ def create_chip_dict_main_fp(chip_id, pixel_size=1e-2): } return chip_dict + def set_fgs_chips(filepath): with open(filepath, "r") as f: data = json.load(f) @@ -94,7 +101,7 @@ def set_fgs_chips(filepath): data[chip_id]["full_well"] = 90000 with open(filepath, "w") as f: json.dump(data, f, indent=4) - + def add_main_fp(filepath): for i in range(30): @@ -102,6 +109,7 @@ def add_main_fp(filepath): chip_dict = create_chip_dict_main_fp(chip_id) add_dict_to_json(filepath, str(chip_id), chip_dict) + def add_dict_to_json(filepath, key, value): with open(filepath, 'r') as f: data = json.load(f) @@ -109,8 +117,9 @@ def add_dict_to_json(filepath, key, value): with open(filepath, "w") as f: json.dump(data, f, indent=4) -if __name__=="__main__": - src = "../ObservationSim/Instrument/data/ccd/chip_definition.json" + +if __name__ == "__main__": + src = "../observation_sim/instruments/data/ccd/chip_definition.json" shutil.copy(src, chip_filename) add_main_fp(chip_filename) - set_fgs_chips(chip_filename) \ No newline at end of file + set_fgs_chips(chip_filename) diff --git a/tools/getPSF.py b/tools/get_PSF.py similarity index 63% rename from tools/getPSF.py rename to tools/get_PSF.py index f35218e92f19a571da416090a2fa668a2d952593..f861bd5070d7f402e63a89b408d191224f3cf4e5 100644 --- a/tools/getPSF.py +++ b/tools/get_PSF.py @@ -1,26 +1,26 @@ import os import numpy as np -import ObservationSim.PSF.PSFInterp as PSFInterp -from ObservationSim.Instrument import Chip, Filter, FilterParam +import observation_sim.psf.PSFInterp as PSFInterp +from observation_sim.instruments import Chip, Filter, FilterParam import yaml import galsim import astropy.io.fits as fitsio # Setup PATH SIMPATH = "/share/simudata/CSSOSDataProductsSims/data/CSSTSimImage_C8/testRun_FGS" -config_filename= SIMPATH+"/config_C6_fits.yaml" -cat_filename = SIMPATH+"/MSC_00000000/MSC_10106100000000_chip_40_filt_FGS.cat" +config_filename = SIMPATH+"/config_C6_fits.yaml" +cat_filename = SIMPATH+"/MSC_00000000/MSC_10106100000000_chip_40_filt_FGS.cat" # Read cat file -catFn = open(cat_filename,"r") +catFn = open(cat_filename, "r") line = catFn.readline() -print(cat_filename,'\n',line) +print(cat_filename, '\n', line) imgPos = [] chipID = -1 for line in catFn: line = line.strip() columns = line.split() - + if chipID == -1: chipID = int(columns[1]) else: @@ -37,41 +37,46 @@ with open(config_filename, "r") as stream: try: config = yaml.safe_load(stream) for key, value in config.items(): - print (key + " : " + str(value)) + print(key + " : " + str(value)) except yaml.YAMLError as exc: print(exc) # Setup Chip chip = Chip(chipID=chipID, config=config) -print('chip.bound::', chip.bound.xmin, chip.bound.xmax, chip.bound.ymin, chip.bound.ymax) +print('chip.bound::', chip.bound.xmin, chip.bound.xmax, + chip.bound.ymin, chip.bound.ymax) for iobj in range(nobj): print("\nget psf for iobj-", iobj, '\t', 'bandpass:', end=" ", flush=True) # Setup Position on focalplane - x, y = imgPos[iobj, :] # try get the PSF at some location (1234, 1234) on the chip + # try get the PSF at some location (1234, 1234) on the chip + x, y = imgPos[iobj, :] x = x+chip.bound.xmin y = y+chip.bound.ymin pos_img = galsim.PositionD(x, y) - + # Setup sub-bandpass # (There are 4 sub-bandpasses for each PSF sample) filter_param = FilterParam() filter_id, filter_type = chip.getChipFilter() filt = Filter( - filter_id=filter_id, - filter_type=filter_type, - filter_param=filter_param, + filter_id=filter_id, + filter_type=filter_type, + filter_param=filter_param, ccd_bandpass=chip.effCurve) bandpass_list = filt.bandpass_sub_list for i in range(len(bandpass_list)): print(i, end=" ", flush=True) - bandpass = bandpass_list[i] # say you want to access the PSF for the sub-bandpass at the blue end for that chip - + # say you want to access the PSF for the sub-bandpass at the blue end for that chip + bandpass = bandpass_list[i] + # Get corresponding PSF model - psf_model = PSFInterp(chip=chip, npsf=100, PSF_data_file=config["psf_setting"]["psf_dir"]) - psf = psf_model.get_PSF(chip=chip, pos_img=pos_img, bandpass=bandpass, galsimGSObject=False) - + psf_model = PSFInterp(chip=chip, npsf=100, + PSF_data_file=config["psf_setting"]["psf_dir"]) + psf = psf_model.get_PSF( + chip=chip, pos_img=pos_img, bandpass=bandpass, galsimGSObject=False) + if True: fn = "psf_{:}.{:}.{:}.fits".format(chipID, iobj, i) if fn != None: @@ -81,6 +86,3 @@ for iobj in range(nobj): hdu.data = psf hdu.header.set('pixScale', 5) hdu.writeto(fn) - - - diff --git a/tools/indexFits_hdf5.py b/tools/index_fits_hdf5.py similarity index 68% rename from tools/indexFits_hdf5.py rename to tools/index_fits_hdf5.py index 1585ea4a3b675975d6574f0c3cfc3ff3d5ff0321..779cbc0e550af590b9e28765067d1f20735d7ddd 100644 --- a/tools/indexFits_hdf5.py +++ b/tools/index_fits_hdf5.py @@ -26,7 +26,8 @@ import galsim def test_fits(nfits=100, dir_cat=None): for ifits in range(nfits): - gal = galsim.Gaussian(sigma=np.random.uniform(0.2, 0.3)).shear(g1=np.random.uniform(-0.5, 0.5), g2=np.random.uniform(-0.5, 0.5)) + gal = galsim.Gaussian(sigma=np.random.uniform(0.2, 0.3)).shear( + g1=np.random.uniform(-0.5, 0.5), g2=np.random.uniform(-0.5, 0.5)) arr = gal.drawImage(nx=64, ny=64, scale=0.074).array hdu = fitsio.PrimaryHDU() @@ -38,41 +39,44 @@ def test_fits(nfits=100, dir_cat=None): hdu.header.set('mag_g', 22+np.random.uniform(-1, 1)) hdu.header.set('pixScale', 0.074) - fout=dir_cat+"stampCats/testStamp_{:}.fits".format(ifits) + fout = dir_cat+"stampCats/testStamp_{:}.fits".format(ifits) if os.path.exists(fout): os.remove(fout) hdu.writeto(fout) def write_StampsIndex(dir_cat=None, DEBUG=False): - MAXNUMBERINDEX = 10000 + MAXNUMBERINDEX = 10000 NSIDE = 128 fp = h5py.File(dir_cat+'stampCatsIndex.hdf5', 'w') grp1 = fp.create_group('Stamps') dataSet_Size = np.zeros(healpy.nside2npix(NSIDE), dtype=np.int64) - fitsList = os.listdir(dir_cat+'stampCats/') #获取fits文件列表 + fitsList = os.listdir(dir_cat+'stampCats/') # 获取fits文件列表 for istamp in range(len(fitsList)): print(istamp, ': ', fitsList[istamp], end='\r') - hdu=fitsio.open(dir_cat+"stampCats/"+fitsList[istamp]) + hdu = fitsio.open(dir_cat+"stampCats/"+fitsList[istamp]) tra = hdu[0].header['RA'] - tdec= hdu[0].header['DEC'] + tdec = hdu[0].header['DEC'] - healpixID= healpy.ang2pix(NSIDE, tra, tdec, nest=False, lonlat=True) + healpixID = healpy.ang2pix(NSIDE, tra, tdec, nest=False, lonlat=True) - if not(str(healpixID) in grp1): + if not (str(healpixID) in grp1): grp2 = grp1.create_group(str(healpixID)) else: grp2 = grp1[str(healpixID)] - if not('ra' in grp2): - dset_ra = grp2.create_dataset('ra', (0,), dtype='f16' , maxshape=(MAXNUMBERINDEX, )) - dset_dec= grp2.create_dataset('dec', (0,), dtype='f16', maxshape=(MAXNUMBERINDEX, )) + if not ('ra' in grp2): + dset_ra = grp2.create_dataset( + 'ra', (0,), dtype='f16', maxshape=(MAXNUMBERINDEX, )) + dset_dec = grp2.create_dataset( + 'dec', (0,), dtype='f16', maxshape=(MAXNUMBERINDEX, )) dt = h5py.special_dtype(vlen=str) - dset_fn = grp2.create_dataset('filename', (0,), dtype=dt, maxshape=(MAXNUMBERINDEX, )) + dset_fn = grp2.create_dataset( + 'filename', (0,), dtype=dt, maxshape=(MAXNUMBERINDEX, )) else: - dset_ra = grp2['ra'] + dset_ra = grp2['ra'] dset_dec = grp2['dec'] dset_fn = grp2['filename'] @@ -82,13 +86,13 @@ def write_StampsIndex(dir_cat=None, DEBUG=False): grp2['filename'].resize((dataSet_Size[healpixID],)) dset_ra[dataSet_Size[healpixID]-1] = tra - dset_dec[dataSet_Size[healpixID]-1]= tdec - dset_fn[dataSet_Size[healpixID]-1]= fitsList[istamp] + dset_dec[dataSet_Size[healpixID]-1] = tdec + dset_fn[dataSet_Size[healpixID]-1] = fitsList[istamp] fp.close() if DEBUG: print('\n') - ff = h5py.File(dir_cat+"stampCatsIndex.hdf5","r") + ff = h5py.File(dir_cat+"stampCatsIndex.hdf5", "r") ss = 0 for kk in ff['Stamps'].keys(): print(kk, ff['Stamps'][kk]['ra'].size) @@ -98,6 +102,5 @@ def write_StampsIndex(dir_cat=None, DEBUG=False): if __name__ == '__main__': dir_temp = "./Catalog_test/" - #test_fits(dir_cat=dir_temp) + # test_fits(dir_cat=dir_temp) write_StampsIndex(dir_cat=dir_temp) - diff --git a/tools/TargetLocationCheck.py b/tools/target_location_check.py similarity index 67% rename from tools/TargetLocationCheck.py rename to tools/target_location_check.py index 69020761fbc5fe38b5615e2b5c0b6c65c92e8a96..34293be892b00d330c8fac94037a3502e2b6055e 100644 --- a/tools/TargetLocationCheck.py +++ b/tools/target_location_check.py @@ -1,15 +1,17 @@ -# NOTE: This is a stand-alone function, meaning that you do not need -# to install the entire CSST image simulation pipeline. +# NOTE: This is a stand-alone function, meaning that you do not need +# to install the entire CSST image simulation pipeline. -# For a given object's coordinate (Ra, Dec), the function will predict -# the object's image position and corresponding filter in the focal plane +# For a given object's coordinate (Ra, Dec), the function will predict +# the object's image position and corresponding filter in the focal plane # under a specified CSST pointing centered at (rap, decp). import galsim import numpy as np import argparse import matplotlib.pyplot as plt -import os, sys +import os +import sys + def focalPlaneInf(ra_target, dec_target, ra_point, dec_point, image_rot=-113.4333, figout="zTargetOnCCD.pdf"): """ @@ -37,60 +39,71 @@ def focalPlaneInf(ra_target, dec_target, ra_point, dec_point, image_rot=-113.433 or type >> python TargetLocationCheck.py ra_target dec_target ra_point dec_point -image_rot=floatNum or type >> python TargetLocationCheck.py ra_target dec_target ra_point dec_point -image_rot=floatNum -figout=FigureName """ - print("^_^ Input target coordinate: [Ra, Dec] = [%10.6f, %10.6f]"%(ra_target,dec_target)) - print("^_^ Input telescope pointing center: [Ra, Dec] = [%10.6f, %10.6f]"%(ra_point,dec_point)) - print("^_^ Input camera orientation: %12.6f degree(s)"%image_rot) + print("^_^ Input target coordinate: [Ra, Dec] = [%10.6f, %10.6f]" % ( + ra_target, dec_target)) + print("^_^ Input telescope pointing center: [Ra, Dec] = [%10.6f, %10.6f]" % ( + ra_point, dec_point)) + print("^_^ Input camera orientation: %12.6f degree(s)" % image_rot) print(" ") # load ccd parameters xsize, ysize, xchip, ychip, xgap, ygap, xnchip, ynchip = ccdParam() - print("^_^ Pixel range of focal plane: x = [%5d, %5d], y = [%5d, %5d]"%(-xsize/2,xsize/2,-ysize/2,ysize/2)) - # wcs - wcs = getTanWCS(ra_point, dec_point, image_rot, pix_scale=0.074) - skyObj = galsim.CelestialCoord(ra=ra_target*galsim.degrees,dec=dec_target*galsim.degrees) - pixObj = wcs.toImage(skyObj) + print("^_^ Pixel range of focal plane: x = [%5d, %5d], y = [%5d, %5d]" % ( + -xsize/2, xsize/2, -ysize/2, ysize/2)) + # wcs + wcs = getTanWCS(ra_point, dec_point, image_rot, pix_scale=0.074) + skyObj = galsim.CelestialCoord( + ra=ra_target*galsim.degrees, dec=dec_target*galsim.degrees) + pixObj = wcs.toImage(skyObj) xpixObj = pixObj.x ypixObj = pixObj.y - print("^_^ Image position of target: [xImage, yImage] = [%9.3f, %9.3f]"%(xpixObj,ypixObj)) - + print("^_^ Image position of target: [xImage, yImage] = [%9.3f, %9.3f]" % ( + xpixObj, ypixObj)) + # first determine if the target is in the focal plane xin = (xpixObj+xsize/2)*(xpixObj-xsize/2) yin = (ypixObj+ysize/2)*(ypixObj-ysize/2) - if xin>0 or yin>0: raise ValueError("!!! Input target is out of the focal plane") - + if xin > 0 or yin > 0: + raise ValueError("!!! Input target is out of the focal plane") + # second determine the location of the target trigger = False for i in range(30): - ichip = i+1 - ischip = str("0%d"%ichip)[-2:] - fId, fType = getChipFilter(ichip) + ichip = i+1 + ischip = str("0%d" % ichip)[-2:] + fId, fType = getChipFilter(ichip) ix0, ix1, iy0, iy1 = getChipLim(ichip) - ixin = (xpixObj-ix0)*(xpixObj-ix1) - iyin = (ypixObj-iy0)*(ypixObj-iy1) - if ixin<=0 and iyin<=0: + ixin = (xpixObj-ix0)*(xpixObj-ix1) + iyin = (ypixObj-iy0)*(ypixObj-iy1) + if ixin <= 0 and iyin <= 0: trigger = True - idx = xpixObj - ix0 - idy = ypixObj - iy0 + idx = xpixObj - ix0 + idy = ypixObj - iy0 print(" ---------------------------------------------") - print(" ** Target locates in CHIP#%s with filter %s **"%(ischip,fType)) - print(" ** Target position in the chip: [x, y] = [%7.2f, %7.2f]"%(idx, idy)) + print(" ** Target locates in CHIP#%s with filter %s **" % + (ischip, fType)) + print( + " ** Target position in the chip: [x, y] = [%7.2f, %7.2f]" % (idx, idy)) print(" ---------------------------------------------") break - if not trigger: print("^|^ Target locates in CCD gap") + if not trigger: + print("^|^ Target locates in CCD gap") # show the figure - print(" Target on CCD layout is saved into %s"%figout) + print(" Target on CCD layout is saved into %s" % figout) ccdLayout(xpixObj, ypixObj, figout=figout) return + def ccdParam(): xt, yt = 59516, 49752 x0, y0 = 9216, 9232 - xgap, ygap = (534,1309), 898 + xgap, ygap = (534, 1309), 898 xnchip, ynchip = 6, 5 ccdSize = xt, yt, x0, y0, xgap, ygap, xnchip, ynchip return ccdSize + def getTanWCS(ra, dec, img_rot, pix_scale=0.074): """ Get the WCS of the image mosaic using Gnomonic/TAN projection @@ -105,40 +118,53 @@ def getTanWCS(ra, dec, img_rot, pix_scale=0.074): WCS of the focal plane """ xcen, ycen = 0, 0 - img_rot = img_rot * galsim.degrees - dudx = -np.cos(img_rot.rad) * pix_scale - dudy = -np.sin(img_rot.rad) * pix_scale - dvdx = -np.sin(img_rot.rad) * pix_scale - dvdy = +np.cos(img_rot.rad) * pix_scale - - moscen = galsim.PositionD(x=xcen, y=ycen) - sky_center = galsim.CelestialCoord(ra=ra*galsim.degrees, dec=dec*galsim.degrees) - affine = galsim.AffineTransform(dudx, dudy, dvdx, dvdy, origin=moscen) - WCS = galsim.TanWCS(affine, sky_center, units=galsim.arcsec) + img_rot = img_rot * galsim.degrees + dudx = -np.cos(img_rot.rad) * pix_scale + dudy = -np.sin(img_rot.rad) * pix_scale + dvdx = -np.sin(img_rot.rad) * pix_scale + dvdy = +np.cos(img_rot.rad) * pix_scale + + moscen = galsim.PositionD(x=xcen, y=ycen) + sky_center = galsim.CelestialCoord( + ra=ra*galsim.degrees, dec=dec*galsim.degrees) + affine = galsim.AffineTransform(dudx, dudy, dvdx, dvdy, origin=moscen) + WCS = galsim.TanWCS(affine, sky_center, units=galsim.arcsec) return WCS + def getChipFilter(chipID): """ Return the filter index and type for a given chip #(chipID) """ - filter_type_list = ["nuv","u", "g", "r", "i","z","y","GU", "GV", "GI"] + filter_type_list = ["nuv", "u", "g", "r", "i", "z", "y", "GU", "GV", "GI"] # TODO: maybe a more elegent way other than hard coded? # e.g. use something like a nested dict: - if chipID in [6, 15, 16, 25]: filter_type = "y" - if chipID in [11, 20]: filter_type = "z" - if chipID in [7, 24]: filter_type = "i" - if chipID in [14, 17]: filter_type = "u" - if chipID in [9, 22]: filter_type = "r" - if chipID in [12, 13, 18, 19]: filter_type = "nuv" - if chipID in [8, 23]: filter_type = "g" - if chipID in [1, 10, 21, 30]: filter_type = "GI" - if chipID in [2, 5, 26, 29]: filter_type = "GV" - if chipID in [3, 4, 27, 28]: filter_type = "GU" + if chipID in [6, 15, 16, 25]: + filter_type = "y" + if chipID in [11, 20]: + filter_type = "z" + if chipID in [7, 24]: + filter_type = "i" + if chipID in [14, 17]: + filter_type = "u" + if chipID in [9, 22]: + filter_type = "r" + if chipID in [12, 13, 18, 19]: + filter_type = "nuv" + if chipID in [8, 23]: + filter_type = "g" + if chipID in [1, 10, 21, 30]: + filter_type = "GI" + if chipID in [2, 5, 26, 29]: + filter_type = "GV" + if chipID in [3, 4, 27, 28]: + filter_type = "GU" filter_id = filter_type_list.index(filter_type) return filter_id, filter_type + def getChipLim(chipID): """ Calculate the edges in pixel for a given CCD chip on the focal plane @@ -173,20 +199,22 @@ def getChipLim(chipID): return nx0-1, nx1-1, ny0-1, ny1-1 + def ccdLayout(xpixTar, ypixTar, figout="ccdLayout.pdf"): - fig = plt.figure(figsize=(10.0,8.0)) - ax = fig.add_axes([0.1,0.1,0.80,0.80]) + fig = plt.figure(figsize=(10.0, 8.0)) + ax = fig.add_axes([0.1, 0.1, 0.80, 0.80]) # plot the layout of the ccd distribution for i in range(30): ichip = i+1 fId, fType = getChipFilter(ichip) - ischip = str("0%d"%ichip)[-2:] + ischip = str("0%d" % ichip)[-2:] ix0, ix1, iy0, iy1 = getChipLim(ichip) - ax.plot([ix0,ix1],[iy0,iy0],"k-", linewidth=2.5) - ax.plot([ix0,ix1],[iy1,iy1],"k-", linewidth=2.5) - ax.plot([ix0,ix0],[iy0,iy1],"k-", linewidth=2.5) - ax.plot([ix1,ix1],[iy0,iy1],"k-", linewidth=2.5) - ax.text(ix0+500,iy0+1500,"%s#%s"%(fType, ischip), fontsize=12, color="grey") + ax.plot([ix0, ix1], [iy0, iy0], "k-", linewidth=2.5) + ax.plot([ix0, ix1], [iy1, iy1], "k-", linewidth=2.5) + ax.plot([ix0, ix0], [iy0, iy1], "k-", linewidth=2.5) + ax.plot([ix1, ix1], [iy0, iy1], "k-", linewidth=2.5) + ax.text(ix0+500, iy0+1500, "%s#%s" % + (fType, ischip), fontsize=12, color="grey") ax.plot(xpixTar, ypixTar, "r*", ms=12) ax.set_xlabel("$X\,[\mathrm{pixels}]$", fontsize=20) ax.set_ylabel("$Y\,[\mathrm{pixels}]$", fontsize=20) @@ -194,6 +222,7 @@ def ccdLayout(xpixTar, ypixTar, figout="ccdLayout.pdf"): ax.axis('off') plt.savefig(figout) + def parseArguments(): # Create argument parser parser = argparse.ArgumentParser() @@ -203,7 +232,7 @@ def parseArguments(): parser.add_argument("dec_target", type=float) parser.add_argument("ra_point", type=float) parser.add_argument("dec_point", type=float) - + # Optional arguments parser.add_argument("-image_rot", type=float, default=-113.4333) parser.add_argument("-figout", type=str, default="zTargetOnCCD.pdf") @@ -213,10 +242,11 @@ def parseArguments(): return args + if __name__ == "__main__": # Parse the arguments args = parseArguments() # Run function - focalPlaneInf(args.ra_target, args.dec_target, args.ra_point, args.dec_point, args.image_rot, args.figout) - + focalPlaneInf(args.ra_target, args.dec_target, args.ra_point, + args.dec_point, args.image_rot, args.figout)