def __init__(self, wavemin=None, wavemax=None, dw=0.2, rand=None, verbose=False): from desimodel.io import load_throughput self.tree = BGStree() # Build a default (buffered) wavelength vector. if wavemin is None: wavemin = load_throughput('b').wavemin - 10.0 if wavemax is None: wavemax = load_throughput('z').wavemax + 10.0 self.wavemin = wavemin self.wavemax = wavemax self.dw = dw self.wave = np.arange(round(wavemin, 1), wavemax, dw) self.rand = rand self.verbose = verbose # Initialize the templates once: from desisim.templates import BGS self.bgs_templates = BGS( wave=self.wave ) #, normfilter='sdss2010-r') # Need to generalize this! self.bgs_templates.normline = None # no emission lines!
def test_HBETA(self): '''Confirm that BGS H-beta flux matches meta table description''' print('In function test_HBETA, seed = {}'.format(self.seed)) wave = np.arange(5000, 7000.1, 0.2) # Need to choose just the star-forming galaxies. from desisim.io import read_basis_templates baseflux, basewave, basemeta = read_basis_templates(objtype='BGS') keep = np.where(basemeta['HBETA_LIMIT'] == 0)[0] bgs = BGS(wave=wave, basewave=basewave, baseflux=baseflux[keep, :], basemeta=basemeta[keep]) flux, ww, meta = bgs.make_templates( seed=self.seed, nmodel=10, zrange=(0.05, 0.4), logvdisp_meansig=[np.log10(75), 0.0], nocolorcuts=True, nocontinuum=True) for i in range(len(meta)): z = meta['REDSHIFT'][i] ii = (4854 * (1 + z) < wave) & (wave < 4868 * (1 + z)) hbetaflux = 1e-17 * np.sum(flux[i, ii] * np.gradient(wave[ii])) self.assertAlmostEqual(hbetaflux, meta['HBETAFLUX'][i], 2)
def main(): seed = 123 ngal = 100 npergal = 50 # Read the mock catalog. cat = h5py.File('galaxy_catalogue_0.hdf5') gr = cat['Data']['g_r'][:ngal] mag = cat['Data']['app_mag'][:ngal] z = cat['Data']['z_obs'][:ngal] zmin, zmax = np.min(z), np.max(z) # Read the basis templates and initialize the output metadata table. baseflux, basewave, basemeta = read_basis_templates('BGS') meta = empty_metatable(objtype='BGS', nmodel=ngal) bgs = BGS(minwave=3000, maxwave=11000.0) for igal in range(ngal): flux, wave, meta = bgs.make_templates(npergal, zrange=(zmin, zmax), nocolorcuts=True) pdb.set_trace()
def __init__(self, wavemin=None, wavemax=None, dw=0.2, nproc=1, rand=None, verbose=False): from desimodel.io import load_throughput self.tree = TemplateKDTree(nproc=nproc) # Build a default (buffered) wavelength vector. if wavemin is None: wavemin = load_throughput('b').wavemin - 10.0 if wavemax is None: wavemax = load_throughput('z').wavemax + 10.0 self.wavemin = wavemin self.wavemax = wavemax self.dw = dw self.wave = np.arange(round(wavemin, 1), wavemax, dw) self.rand = rand self.verbose = verbose #self.__normfilter = 'decam2014-r' # default normalization filter # Initialize the templates once: from desisim.templates import BGS, ELG, LRG, QSO, STAR, WD self.bgs_templates = BGS(wave=self.wave, normfilter='sdss2010-r') # Need to generalize this! self.elg_templates = ELG(wave=self.wave, normfilter='decam2014-r') self.lrg_templates = LRG(wave=self.wave, normfilter='decam2014-z') self.qso_templates = QSO(wave=self.wave, normfilter='decam2014-g') self.lya_templates = QSO(wave=self.wave, normfilter='decam2014-g') self.star_templates = STAR(wave=self.wave, normfilter='decam2014-r') self.wd_da_templates = WD(wave=self.wave, normfilter='decam2014-g', subtype='DA') self.wd_db_templates = WD(wave=self.wave, normfilter='decam2014-g', subtype='DB')
def sim_lenssource_spectra(BGSmags, fratios, seed=None, exptime=1000., nperchunk=500, infofile='lenssource-truth.fits', debug=False): """Build the (noisy) lens+source spectra. No redshift-fitting. """ from astropy.io import fits from desisim.templates import BGS, ELG from desisim.scripts.quickspectra import sim_spectra from desisim.io import read_basis_templates from desispec.io import read_spectra rand = np.random.RandomState(seed) nsim = len(BGSmags) assert(nsim == len(fratios)) if nperchunk > 500: raise ValueError('nperchunk={} exceeds the maximum number allowed by redrock'.format(nperchunk)) nchunk = np.ceil(nsim / nperchunk).astype(int) # [1] Build the noise-less lens (BGS) spectra. # Read one healpix of the Buzzard mocks for redshift distribution. mockfile = os.path.join(os.getenv('DESI_ROOT'), 'mocks', 'buzzard', 'buzzard_v1.6_desicut', '8', '0', '0', 'Buzzard_v1.6_lensed-8-0.fits') print('Reading {}'.format(mockfile)) mock_BGS = Table(fitsio.read(mockfile)) #columns='lmag z'.split() # From the BGS template library, select a reddish galaxy tflux, twave, tmeta_BGS = read_basis_templates('BGS') i = np.argmin(np.abs(2.0 - tmeta_BGS['D4000'])) iredBGS = i redspecBGS = tflux[i, :] Itempl_BGS = np.array([iredBGS]) # LMAG: observed mag, DECam grizY mock_mag_r = mock_BGS['LMAG'][:, 1] # r-band dm = 0.01 zz_BGS = np.zeros_like(BGSmags) for ii, mag in enumerate(BGSmags): I = np.flatnonzero(np.abs(mock_mag_r - mag) <= dm) zz_BGS[ii] = mock_BGS['Z'][rand.choice(I, size=1, replace=False)] input_meta_BGS = Table() input_meta_BGS['TEMPLATEID'] = [Itempl_BGS]*nsim input_meta_BGS['SEED'] = np.arange(nsim) # [seed]*nsim # input_meta_BGS['REDSHIFT'] = zz_BGS input_meta_BGS['MAG'] = BGSmags input_meta_BGS['MAGFILTER'] = ['decam2014-r']*nsim BGSflux, BGSwave, BGSmeta, BGSobjmeta = BGS().make_templates( input_meta=input_meta_BGS, nocolorcuts=True, seed=seed) # [2] Build the noise-less source (ELG) spectra. #ELGmags = maggen(BGSmags[:, np.newaxis], fratios[np.newaxis, :]) ELGmags = maggen(BGSmags, fratios) # Select a single ELG template. tflux, twave, tmeta_ELG = read_basis_templates('ELG') i = np.argmin(np.abs(1.0 - tmeta_ELG['D4000'])) # MIGHT NEED TO ADJUST THIS LINE iblueELG = i bluespecELG = tflux[i, :] Itempl_ELG = np.array([iblueELG]) # uncorrelated redshifts zmin_ELG, zmax_ELG = 0.8, 1.4 zz_ELG = rand.uniform(zmin_ELG, zmax_ELG, nsim) input_meta_ELG = Table() input_meta_ELG['TEMPLATEID'] = [Itempl_ELG]*nsim input_meta_ELG['SEED'] = [3]*nsim # [seed]*nsim # np.arange(nsim) hack! input_meta_ELG['REDSHIFT'] = zz_ELG input_meta_ELG['MAG'] = ELGmags input_meta_ELG['MAGFILTER'] = ['decam2014-r']*nsim ELGflux, ELGwave, ELGmeta, ELGobjmeta = ELG().make_templates( input_meta=input_meta_ELG, nocolorcuts=True, seed=seed) assert(np.all(BGSwave == ELGwave)) # Pack the simulation info into a table, for convenience. siminfo = Table() siminfo['TARGETID'] = np.arange(nsim, dtype=np.int64) siminfo['LENS_Z'] = input_meta_BGS['REDSHIFT'].astype('f4') siminfo['LENS_MAG'] = input_meta_BGS['MAG'].astype('f4') siminfo['SOURCE_Z'] = input_meta_ELG['REDSHIFT'].astype('f4') siminfo['SOURCE_MAG'] = input_meta_ELG['MAG'].astype('f4') siminfo['FRATIO'] = fratios.astype('f4') siminfo['CHUNK'] = np.zeros(nsim, dtype=np.int32) # Generate simulated DESI spectra given real spectra and observing # conditions. Divide the sample into chunks with a fixed number of # spectra per chunk (but no more than 500). obscond = {'AIRMASS': 1.3, 'EXPTIME': exptime, 'SEEING': 1.1, 'MOONALT': -60, 'MOONFRAC': 0.0, 'MOONSEP': 180} simflux = BGSflux + ELGflux simwave = BGSwave for ichunk in np.arange(nchunk): specfile = 'lenssource-spectra-chunk{:03d}.fits'.format(ichunk) print('Writing chunk {}/{} to {}'.format(ichunk, nchunk-1, specfile)) i1 = ichunk * nperchunk i2 = (ichunk+1) * nperchunk siminfo['CHUNK'][i1:i2] = ichunk sim_spectra(simwave, simflux[i1:i2, :], 'dark', specfile, obsconditions=obscond, sourcetype='bgs', seed=seed, targetid=siminfo['TARGETID'][i1:i2], redshift=siminfo['LENS_Z'][i1:i2]) if debug: spectra = read_spectra(specfile) for igal in np.arange(spectra.num_targets()): qafile = 'lenssource-spectra-chunk{:03d}-{}.png'.format(ichunk, igal) fig, ax = plt.subplots() for band in spectra.bands: ax.plot(spectra.wave[band], spectra.flux[band][igal, :]) ax.plot(simwave, simflux[i1:i2, :][igal, :], color='k', lw=2) ax.set_ylim(np.median(simflux[i1:i2, :][igal, :]) + np.std(spectra.flux['r'][igal, :]) * np.array([-1.5, 3])) fig.savefig(qafile) plt.close() # write out and return hduflux = fits.PrimaryHDU(simflux) hduflux.header['EXTNAME'] = 'FLUX' hduflux.header['BUNIT'] = '10^(-17) erg/(s cm2 Angstrom)' hdubgs = fits.ImageHDU(BGSflux) hdubgs.header['EXTNAME'] = 'BGSFLUX' hduelg = fits.ImageHDU(ELGflux) hduelg.header['EXTNAME'] = 'ELGFLUX' hduwave = fits.ImageHDU(simwave) hduwave.header['EXTNAME'] = 'WAVE' hduwave.header['BUNIT'] = 'Angstrom' hduwave.header['AIRORVAC'] = ('vac', 'vacuum wavelengths') hdutable = fits.convenience.table_to_hdu(siminfo) hdutable.header['EXTNAME'] = 'METADATA' hx = fits.HDUList([hduflux, hdubgs, hduelg, hduwave, hdutable]) print('Writing {}'.format(infofile)) hx.writeto(infofile, overwrite=True) return siminfo
def get_targets(nspec, program, tileid=None, seed=None, specify_targets=dict(), specmin=0): """ Generates a set of targets for the requested program Args: nspec: (int) number of targets to generate program: (str) program name DARK, BRIGHT, GRAY, MWS, BGS, LRG, ELG, ... Options: * tileid: (int) tileid, used for setting RA,dec * seed: (int) random number seed * specify_targets: (dict of dicts) Define target properties like magnitude and redshift for each target class. Each objtype has its own key,value pair see simspec.templates.specify_galparams_dict() or simsepc.templates.specify_starparams_dict() * specmin: (int) first spectrum number (0-indexed) Returns: * fibermap * targets as tuple of (flux, wave, meta) """ if tileid is None: tile_ra, tile_dec = 0.0, 0.0 else: tile_ra, tile_dec = io.get_tile_radec(tileid) program = program.upper() log.debug('Using random seed {}'.format(seed)) np.random.seed(seed) #- Get distribution of target types true_objtype, target_objtype = sample_objtype(nspec, program) #- Get DESI wavelength coverage try: params = desimodel.io.load_desiparams() wavemin = params['ccd']['b']['wavemin'] wavemax = params['ccd']['z']['wavemax'] except KeyError: wavemin = desimodel.io.load_throughput('b').wavemin wavemax = desimodel.io.load_throughput('z').wavemax dw = 0.2 wave = np.arange(round(wavemin, 1), wavemax, dw) nwave = len(wave) flux = np.zeros( (nspec, len(wave)) ) meta, _ = empty_metatable(nmodel=nspec, objtype='SKY') objmeta = dict() fibermap = empty_fibermap(nspec) targetid = np.random.randint(sys.maxsize, size=nspec).astype(np.int64) meta['TARGETID'] = targetid fibermap['TARGETID'] = targetid for objtype in set(true_objtype): ii = np.where(true_objtype == objtype)[0] nobj = len(ii) fibermap['OBJTYPE'][ii] = target_objtype[ii] if objtype in specify_targets.keys(): obj_kwargs = specify_targets[objtype] else: obj_kwargs = dict() # Simulate spectra if objtype == 'SKY': fibermap['DESI_TARGET'][ii] = desi_mask.SKY continue elif objtype == 'ELG': from desisim.templates import ELG elg = ELG(wave=wave) simflux, wave1, meta1, objmeta1 = elg.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) fibermap['DESI_TARGET'][ii] = desi_mask.ELG elif objtype == 'LRG': from desisim.templates import LRG lrg = LRG(wave=wave) simflux, wave1, meta1, objmeta1 = lrg.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) fibermap['DESI_TARGET'][ii] = desi_mask.LRG elif objtype == 'BGS': from desisim.templates import BGS bgs = BGS(wave=wave) simflux, wave1, meta1, objmeta1 = bgs.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) fibermap['DESI_TARGET'][ii] = desi_mask.BGS_ANY fibermap['BGS_TARGET'][ii] = bgs_mask.BGS_BRIGHT elif objtype == 'QSO': from desisim.templates import QSO qso = QSO(wave=wave) simflux, wave1, meta1, objmeta1 = qso.make_templates(nmodel=nobj, seed=seed, lyaforest=False, **obj_kwargs) fibermap['DESI_TARGET'][ii] = desi_mask.QSO # For a "bad" QSO simulate a normal star without color cuts, which isn't # right. We need to apply the QSO color-cuts to the normal stars to pull # out the correct population of contaminating stars. # Note by @moustakas: we can now do this using desisim/#150, but we are # going to need 'noisy' photometry (because the QSO color-cuts # explicitly avoid the stellar locus). elif objtype == 'QSO_BAD': from desisim.templates import STAR #from desitarget.cuts import isQSO #star = STAR(wave=wave, colorcuts_function=isQSO) star = STAR(wave=wave) simflux, wave1, meta1, objmeta1 = star.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) fibermap['DESI_TARGET'][ii] = desi_mask.QSO elif objtype == 'STD': from desisim.templates import STD std = STD(wave=wave) simflux, wave1, meta1, objmeta1 = std.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) #- Loop options for forwards/backwards compatibility for name in ['STD_FAINT', 'STD_FSTAR', 'STD']: if name in desi_mask.names(): fibermap['DESI_TARGET'][ii] |= desi_mask[name] break elif objtype == 'MWS_STAR': from desisim.templates import MWS_STAR mwsstar = MWS_STAR(wave=wave) # TODO: mag ranges for different programs of STAR targets should be in desimodel if 'magrange' not in obj_kwargs.keys(): obj_kwargs['magrange'] = (15.0,20.0) simflux, wave1, meta1, objmeta1 = mwsstar.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) fibermap['DESI_TARGET'][ii] |= desi_mask.MWS_ANY #- MWS bit names changed after desitarget 0.6.0 so use number #- instead of name for now (bit 0 = mask 1 = MWS_MAIN currently) fibermap['MWS_TARGET'][ii] = 1 else: raise ValueError('Unable to simulate OBJTYPE={}'.format(objtype)) # Assign targetid meta1['TARGETID'] = targetid[ii] if hasattr(objmeta1, 'data'): # simqso.sqgrids.QsoSimPoints object objmeta1.data['TARGETID'] = targetid[ii] else: if len(objmeta1) > 0: objmeta1['TARGETID'] = targetid[ii] # We want the dict key tied to the "true" object type (e.g., STAR), # not, e.g., QSO_BAD. objmeta[meta1['OBJTYPE'][0]] = objmeta1 flux[ii] = simflux meta[ii] = meta1 for band in ['G', 'R', 'Z', 'W1', 'W2']: key = 'FLUX_'+band fibermap[key][ii] = meta[key][ii] #- TODO: FLUX_IVAR #- Load fiber -> positioner mapping and tile information fiberpos = desimodel.io.load_fiberpos() #- Where are these targets? Centered on positioners for now. x = fiberpos['X'][specmin:specmin+nspec] y = fiberpos['Y'][specmin:specmin+nspec] fp = FocalPlane(tile_ra, tile_dec) ra = np.zeros(nspec) dec = np.zeros(nspec) for i in range(nspec): ra[i], dec[i] = fp.xy2radec(x[i], y[i]) #- Fill in the rest of the fibermap structure fibermap['FIBER'] = np.arange(nspec, dtype='i4') fibermap['POSITIONER'] = fiberpos['POSITIONER'][specmin:specmin+nspec] fibermap['SPECTROID'] = fiberpos['SPECTROGRAPH'][specmin:specmin+nspec] fibermap['TARGETCAT'] = np.zeros(nspec, dtype=(str, 20)) fibermap['LAMBDA_REF'] = np.ones(nspec, dtype=np.float32)*5400 fibermap['TARGET_RA'] = ra fibermap['TARGET_DEC'] = dec fibermap['FIBERASSIGN_X'] = x fibermap['FIBERASSIGN_Y'] = y fibermap['FIBER_RA'] = fibermap['TARGET_RA'] fibermap['FIBER_DEC'] = fibermap['TARGET_DEC'] fibermap['BRICKNAME'] = brick.brickname(ra, dec) return fibermap, (flux, wave, meta, objmeta)
class BGStemplates(object): """Generate spectra. """ def __init__(self, wavemin=None, wavemax=None, dw=0.2, rand=None, verbose=False): from desimodel.io import load_throughput self.tree = BGStree() # Build a default (buffered) wavelength vector. if wavemin is None: wavemin = load_throughput('b').wavemin - 10.0 if wavemax is None: wavemax = load_throughput('z').wavemax + 10.0 self.wavemin = wavemin self.wavemax = wavemax self.dw = dw self.wave = np.arange(round(wavemin, 1), wavemax, dw) self.rand = rand self.verbose = verbose # Initialize the templates once: from desisim.templates import BGS self.bgs_templates = BGS( wave=self.wave ) #, normfilter='sdss2010-r') # Need to generalize this! self.bgs_templates.normline = None # no emission lines! def bgs(self, data, index=None, mockformat='durham_mxxl_hdf5'): """Generate spectra for BGS. Currently only the MXXL (durham_mxxl_hdf5) mock is supported. DATA needs to have Z, SDSS_absmag_r01, SDSS_01gr, VDISP, and SEED, which are assigned in mock.io.read_durham_mxxl_hdf5. See also BGSKDTree.bgs(). """ from desisim.io import empty_metatable objtype = 'BGS' if index is None: index = np.arange(len(data['Z'])) input_meta = empty_metatable(nmodel=len(index), objtype=objtype) for inkey, datakey in zip(('SEED', 'MAG', 'REDSHIFT', 'VDISP'), ('SEED', 'MAG', 'Z', 'VDISP')): input_meta[inkey] = data[datakey][index] if mockformat.lower() == 'durham_mxxl_hdf5': alldata = np.vstack( (data['Z'][index], data['SDSS_absmag_r01'][index], data['SDSS_01gr'][index])).T _, templateid = self.tree.query(objtype, alldata) else: raise ValueError('Unrecognized mockformat {}!'.format(mockformat)) input_meta['TEMPLATEID'] = templateid flux, _, meta = self.bgs_templates.make_templates( input_meta=input_meta, nocolorcuts=True, novdisp=False, verbose=self.verbose) return flux, meta
class MockSpectra(object): """Generate spectra for each type of mock. Currently just choose the closest template; we can get fancier later. ToDo (@moustakas): apply Galactic extinction. """ def __init__(self, wavemin=None, wavemax=None, dw=0.2, nproc=1, rand=None, verbose=False): from desimodel.io import load_throughput self.tree = TemplateKDTree(nproc=nproc) # Build a default (buffered) wavelength vector. if wavemin is None: wavemin = load_throughput('b').wavemin - 10.0 if wavemax is None: wavemax = load_throughput('z').wavemax + 10.0 self.wavemin = wavemin self.wavemax = wavemax self.dw = dw self.wave = np.arange(round(wavemin, 1), wavemax, dw) self.rand = rand self.verbose = verbose #self.__normfilter = 'decam2014-r' # default normalization filter # Initialize the templates once: from desisim.templates import BGS, ELG, LRG, QSO, STAR, WD self.bgs_templates = BGS(wave=self.wave, normfilter='sdss2010-r') # Need to generalize this! self.elg_templates = ELG(wave=self.wave, normfilter='decam2014-r') self.lrg_templates = LRG(wave=self.wave, normfilter='decam2014-z') self.qso_templates = QSO(wave=self.wave, normfilter='decam2014-g') self.lya_templates = QSO(wave=self.wave, normfilter='decam2014-g') self.star_templates = STAR(wave=self.wave, normfilter='decam2014-r') self.wd_da_templates = WD(wave=self.wave, normfilter='decam2014-g', subtype='DA') self.wd_db_templates = WD(wave=self.wave, normfilter='decam2014-g', subtype='DB') def bgs(self, data, index=None, mockformat='durham_mxxl_hdf5'): """Generate spectra for BGS. Currently only the MXXL (durham_mxxl_hdf5) mock is supported. DATA needs to have Z, SDSS_absmag_r01, SDSS_01gr, VDISP, and SEED, which are assigned in mock.io.read_durham_mxxl_hdf5. See also TemplateKDTree.bgs(). """ objtype = 'BGS' if index is None: index = np.arange(len(data['Z'])) input_meta = empty_metatable(nmodel=len(index), objtype=objtype) for inkey, datakey in zip(('SEED', 'MAG', 'REDSHIFT', 'VDISP'), ('SEED', 'MAG', 'Z', 'VDISP')): input_meta[inkey] = data[datakey][index] if mockformat.lower() == 'durham_mxxl_hdf5': alldata = np.vstack((data['Z'][index], data['SDSS_absmag_r01'][index], data['SDSS_01gr'][index])).T _, templateid = self.tree.query(objtype, alldata) else: raise ValueError('Unrecognized mockformat {}!'.format(mockformat)) input_meta['TEMPLATEID'] = templateid flux, _, meta = self.bgs_templates.make_templates(input_meta=input_meta, nocolorcuts=True, novdisp=False, verbose=self.verbose) return flux, meta def elg(self, data, index=None, mockformat='gaussianfield'): """Generate spectra for the ELG sample. Currently only the GaussianField mock sample is supported. DATA needs to have Z, GR, RZ, VDISP, and SEED, which are assigned in mock.io.read_gaussianfield. See also TemplateKDTree.elg(). """ objtype = 'ELG' if index is None: index = np.arange(len(data['Z'])) input_meta = empty_metatable(nmodel=len(index), objtype=objtype) for inkey, datakey in zip(('SEED', 'MAG', 'REDSHIFT', 'VDISP'), ('SEED', 'MAG', 'Z', 'VDISP')): input_meta[inkey] = data[datakey][index] if mockformat.lower() == 'gaussianfield': alldata = np.vstack((data['Z'][index], data['GR'][index], data['RZ'][index])).T _, templateid = self.tree.query(objtype, alldata) else: raise ValueError('Unrecognized mockformat {}!'.format(mockformat)) if False: import matplotlib.pyplot as plt def elg_colorbox(ax): """Draw the ELG selection box.""" from matplotlib.patches import Polygon grlim = ax.get_ylim() coeff0, coeff1 = (1.15, -0.15), (-1.2, 1.6) rzmin, rzpivot = 0.3, (coeff1[1] - coeff0[1]) / (coeff0[0] - coeff1[0]) verts = [(rzmin, grlim[0]), (rzmin, np.polyval(coeff0, rzmin)), (rzpivot, np.polyval(coeff1, rzpivot)), ((grlim[0] - 0.1 - coeff1[1]) / coeff1[0], grlim[0] - 0.1) ] ax.add_patch(Polygon(verts, fill=False, ls='--', color='k')) fig, ax = plt.subplots() ax.scatter(data['RZ'][index], data['GR'][index]) ax.set_xlim(-0.5, 2) ; plt.ylim(-0.5, 2) elg_colorbox(ax) plt.show() import pdb ; pdb.set_trace() input_meta['TEMPLATEID'] = templateid flux, _, meta = self.elg_templates.make_templates(input_meta=input_meta, nocolorcuts=True, novdisp=False, verbose=self.verbose) return flux, meta def elg_test(self, data, index=None, mockformat='gaussianfield'): """Test script -- generate spectra for the ELG sample. Currently only the GaussianField mock sample is supported. DATA needs to have Z, GR, RZ, VDISP, and SEED, which are assigned in mock.io.read_gaussianfield. See also TemplateKDTree.elg(). """ objtype = 'ELG' if index is None: index = np.arange(len(data['Z'])) input_meta = empty_metatable(nmodel=len(index), objtype=objtype) for inkey, datakey in zip(('SEED', 'MAG', 'REDSHIFT', 'VDISP'), ('SEED', 'MAG', 'Z', 'VDISP')): input_meta[inkey] = data[datakey][index] if mockformat.lower() == 'gaussianfield': alldata = np.vstack((data['Z'][index], data['GR'][index], data['RZ'][index])).T _, templateid = self.tree.query(objtype, alldata) else: raise ValueError('Unrecognized mockformat {}!'.format(mockformat)) import matplotlib.pyplot as plt from scipy.interpolate import interp1d f1 = interp1d(np.squeeze(self.tree.elg_kcorr['REDSHIFT']), np.squeeze(self.tree.elg_kcorr['GR']), axis=0) gr = f1(data['Z'][index]) plt.plot(np.squeeze(self.tree.elg_kcorr['REDSHIFT']), np.squeeze(self.tree.elg_kcorr['GR'])[:, 500]) plt.scatter(data['Z'][index], gr[:, 500], marker='x', color='red', s=15) plt.show() def elg_colorbox(ax): """Draw the ELG selection box.""" from matplotlib.patches import Polygon grlim = ax.get_ylim() coeff0, coeff1 = (1.15, -0.15), (-1.2, 1.6) rzmin, rzpivot = 0.3, (coeff1[1] - coeff0[1]) / (coeff0[0] - coeff1[0]) verts = [(rzmin, grlim[0]), (rzmin, np.polyval(coeff0, rzmin)), (rzpivot, np.polyval(coeff1, rzpivot)), ((grlim[0] - 0.1 - coeff1[1]) / coeff1[0], grlim[0] - 0.1) ] ax.add_patch(Polygon(verts, fill=False, ls='--', color='k')) fig, ax = plt.subplots() ax.scatter(data['RZ'][index], data['GR'][index]) ax.set_xlim(-0.5, 2) ; plt.ylim(-0.5, 2) elg_colorbox(ax) plt.show() import pdb ; pdb.set_trace() input_meta['TEMPLATEID'] = templateid flux, _, meta = self.elg_templates.make_templates(input_meta=input_meta, nocolorcuts=True, novdisp=False, verbose=self.verbose) return flux, meta def lrg(self, data, index=None, mockformat='gaussianfield'): """Generate spectra for the LRG sample. Currently only the GaussianField mock sample is supported. DATA needs to have Z, GR, RZ, VDISP, and SEED, which are assigned in mock.io.read_gaussianfield. See also TemplateKDTree.lrg(). """ objtype = 'LRG' if index is None: index = np.arange(len(data['Z'])) nobj = len(index) input_meta = empty_metatable(nmodel=len(index), objtype=objtype) for inkey, datakey in zip(('SEED', 'MAG', 'REDSHIFT', 'VDISP'), ('SEED', 'MAG', 'Z', 'VDISP')): input_meta[inkey] = data[datakey][index] if mockformat.lower() == 'gaussianfield': # This is wrong: choose a template with equal probability. templateid = self.rand.choice(self.tree.lrg_meta['TEMPLATEID'], len(index)) else: raise ValueError('Unrecognized mockformat {}!'.format(mockformat)) input_meta['TEMPLATEID'] = templateid flux, _, meta = self.lrg_templates.make_templates(input_meta=input_meta, nocolorcuts=True, novdisp=False, verbose=self.verbose) return flux, meta def mws(self, data, index=None, mockformat='galaxia'): """Generate spectra for the MWS_NEARBY and MWS_MAIN samples. """ objtype = 'STAR' if index is None: index = np.arange(len(data['Z'])) input_meta = empty_metatable(nmodel=len(index), objtype=objtype) for inkey, datakey in zip(('SEED', 'MAG', 'REDSHIFT', 'TEFF', 'LOGG', 'FEH'), ('SEED', 'MAG', 'Z', 'TEFF', 'LOGG', 'FEH')): input_meta[inkey] = data[datakey][index] if mockformat.lower() == '100pc': alldata = np.vstack((data['TEFF'][index], data['LOGG'][index], data['FEH'][index])).T _, templateid = self.tree.query(objtype, alldata) elif mockformat.lower() == 'galaxia': alldata = np.vstack((data['TEFF'][index], data['LOGG'][index], data['FEH'][index])).T _, templateid = self.tree.query(objtype, alldata) else: raise ValueError('Unrecognized mockformat {}!'.format(mockformat)) input_meta['TEMPLATEID'] = templateid flux, _, meta = self.star_templates.make_templates(input_meta=input_meta, verbose=self.verbose) # Note! No colorcuts. return flux, meta def mws_nearby(self, data, index=None, mockformat='100pc'): """Generate spectra for the MWS_NEARBY sample. """ flux, meta = self.mws(data, index=index, mockformat=mockformat) return flux, meta def mws_main(self, data, index=None, mockformat='galaxia'): """Generate spectra for the MWS_MAIN sample. """ flux, meta = self.mws(data, index=index, mockformat=mockformat) return flux, meta def faintstar(self, data, index=None, mockformat='galaxia'): """Generate spectra for the FAINTSTAR (faint stellar) sample. """ flux, meta = self.mws(data, index=index, mockformat=mockformat) return flux, meta def mws_wd(self, data, index=None, mockformat='wd'): """Generate spectra for the MWS_WD sample. Deal with DA vs DB white dwarfs separately. """ objtype = 'WD' if index is None: index = np.arange(len(data['Z'])) nobj = len(index) input_meta = empty_metatable(nmodel=nobj, objtype=objtype) for inkey, datakey in zip(('SEED', 'MAG', 'REDSHIFT', 'TEFF', 'LOGG', 'SUBTYPE'), ('SEED', 'MAG', 'Z', 'TEFF', 'LOGG', 'TEMPLATESUBTYPE')): input_meta[inkey] = data[datakey][index] if mockformat.lower() == 'wd': meta = empty_metatable(nmodel=nobj, objtype=objtype) flux = np.zeros([nobj, len(self.wave)], dtype='f4') for subtype in ('DA', 'DB'): these = np.where(input_meta['SUBTYPE'] == subtype)[0] if len(these) > 0: alldata = np.vstack((data['TEFF'][index][these], data['LOGG'][index][these])).T _, templateid = self.tree.query(objtype, alldata, subtype=subtype) input_meta['TEMPLATEID'][these] = templateid template_function = 'wd_{}_templates'.format(subtype.lower()) flux1, _, meta1 = getattr(self, template_function).make_templates(input_meta=input_meta[these], verbose=self.verbose) meta[these] = meta1 flux[these, :] = flux1 else: raise ValueError('Unrecognized mockformat {}!'.format(mockformat)) return flux, meta def qso(self, data, index=None, mockformat='gaussianfield'): """Generate spectra for the QSO or QSO/LYA samples. Note: We need to make sure NORMFILTER matches! """ from desisim.lya_spectra import get_spectra objtype = 'QSO' if index is None: index = np.arange(len(data['Z'])) nobj = len(index) if mockformat.lower() == 'gaussianfield': input_meta = empty_metatable(nmodel=nobj, objtype=objtype) for inkey, datakey in zip(('SEED', 'MAG', 'REDSHIFT'), ('SEED', 'MAG', 'Z')): input_meta[inkey] = data[datakey][index] # Build the tracer and Lya forest QSO spectra separately. meta = empty_metatable(nmodel=nobj, objtype=objtype) flux = np.zeros([nobj, len(self.wave)], dtype='f4') lya = np.where( data['TEMPLATESUBTYPE'][index] == 'LYA' )[0] tracer = np.where( data['TEMPLATESUBTYPE'][index] == '' )[0] if len(tracer) > 0: flux1, _, meta1 = self.qso_templates.make_templates(input_meta=input_meta[tracer], lyaforest=False, nocolorcuts=True, verbose=self.verbose) meta[tracer] = meta1 flux[tracer, :] = flux1 if len(lya) > 0: alllyafile = data['LYAFILES'][index][lya] alllyahdu = data['LYAHDU'][index][lya] for lyafile in sorted(set(alllyafile)): these = np.where( lyafile == alllyafile )[0] templateid = alllyahdu[these] - 1 # templateid is 0-indexed flux1, _, meta1 = get_spectra(lyafile, templateid=templateid, normfilter=data['FILTERNAME'], rand=self.rand, qso=self.lya_templates, nocolorcuts=True) meta1['SUBTYPE'] = 'LYA' meta[lya[these]] = meta1 flux[lya[these], :] = flux1 elif mockformat.lower() == 'lya': # Build spectra for Lyman-alpha QSOs. Deprecated! from desisim.lya_spectra import get_spectra from desitarget.mock.io import decode_rownum_filenum meta = empty_metatable(nmodel=nobj, objtype=objtype) flux = np.zeros([nobj, len(self.wave)], dtype='f4') rowindx, fileindx = decode_rownum_filenum(data['MOCKID'][index]) for indx1 in set(fileindx): lyafile = data['FILES'][indx1] these = np.where(indx1 == fileindx)[0] templateid = rowindx[these].astype('int') flux1, _, meta1 = get_spectra(lyafile, templateid=templateid, normfilter=data['FILTERNAME'], rand=self.rand, qso=self.lya_templates) meta[these] = meta1 flux[these, :] = flux1 else: raise ValueError('Unrecognized mockformat {}!'.format(mockformat)) return flux, meta def sky(self, data, index=None, mockformat=None): """Generate spectra for SKY. """ objtype = 'SKY' if index is None: index = np.arange(len(data['Z'])) nobj = len(index) meta = empty_metatable(nmodel=nobj, objtype=objtype) for inkey, datakey in zip(('SEED', 'REDSHIFT'), ('SEED', 'Z')): meta[inkey] = data[datakey][index] flux = np.zeros((nobj, len(self.wave)), dtype='i1') return flux, meta
def combspec(ELGmag, BGSmag, ELGseed, BGSseed, ELGrShifts=None, BGSrShifts=None, nrShifts=None, returnmeta=False, sepflux=False): BGSmags = [] ELGmags = [] i = 0 if ELGrShifts is not None and BGSrShifts is not None: while i < len(BGSrShifts): BGSmags.append(BGSmag) ELGmags.append(ELGmag) i += 1 makeBGS = LRG() makeELG = ELG() fluxBGS, waveBGS, metaBGS, objmetaBGS = makeBGS.make_templates(seed=BGSseed, nmodel=len(BGSrShifts), redshift=BGSrShifts, mag=BGSmags, nocolorcuts=True) fluxELG, waveELG, metaELG, objmetaELG = makeELG.make_templates(seed=ELGseed, nmodel=len(ELGrShifts), redshift=ELGrShifts, mag=ELGmags, nocolorcuts=True) wave = waveBGS flux = fluxBGS + fluxELG if returnmeta == True and sepflux == True: return wave, flux, metaBGS, metaELG, fluxBGS, fluxELG elif returnmeta == True: return wave, flux, metaBGS, metaELG elif sepflux == True: return wave, flux, fluxBGS, fluxELG else: return wave, flux if nrShifts is not None: while i < nrShifts: BGSmags.append(BGSmag) ELGmags.append(ELGmag) i += 1 makeBGS = BGS() makeELG = ELG() fluxBGS, waveBGS, metaBGS, objmetaBGS = makeBGS.make_templates(seed=BGSseed, nmodel=nrShifts, mag=BGSmags, nocolorcuts=True) fluxELG, waveELG, metaELG, objmetaELG = makeELG.make_templates(seed=ELGseed, nmodel=nrShifts, mag=ELGmags, nocolorcuts=True) wave = waveBGS flux = fluxBGS + fluxELG if returnmeta == True and sepflux == True: return wave, flux, metaBGS, metaELG, fluxBGS, fluxELG elif returnmeta == True: return wave, flux, metaBGS, metaELG elif sepflux == True: return wave, flux, fluxBGS, fluxELG else: return wave, flux
def main(args=None): log = get_logger() if isinstance(args, (list, tuple, type(None))): args = parse(args) # Save simulation output. rng = np.random.RandomState(args.seed) simdata = bgs_write_simdata(args) obs = simdata2obsconditions(args) # Generate list of HEALPix pixels to randomly sample from the mocks. healpixels = _get_healpixels_in_footprint(nside=args.nside) npix = np.minimum(10 * args.nsim, len(healpixels)) pixels = rng.choice(healpixels, size=npix, replace=False) ipix = iter(pixels) # Set up the template generator. maker = BGSMaker(seed=args.seed) maker.template_maker = BGS(add_SNeIa=args.addsnia, add_SNeIIp=args.addsniip, wave=_default_wave()) for j in range(args.nsim): # Loop until finding a non-empty healpixel (one with mock galaxies). tdata = [] while len(tdata) == 0: pixel = next(ipix) tdata = maker.read(healpixels=pixel, nside=args.nside) # Add SN generation options. if args.addsnia or args.addsniip: tdata['SNE_FLUXRATIORANGE'] = (args.snrmin, args.snrmax) tdata['SNE_FILTER'] = 'decam2014-r' # Generate nspec spectral templates and write them to "truth" files. wave = None flux, targ, truth, obj = [], [], [], [] # Generate templates until we have enough to pass brightness cuts. ntosim = np.min((args.nspec, len(tdata['RA']))) ngood = 0 while ngood < args.nspec: idx = rng.choice(len(tdata['RA']), ntosim) tflux, twave, ttarg, ttruth, tobj = \ maker.make_spectra(tdata, indx=idx) # Apply color cuts. is_bright = isBGS_colors(gflux=ttruth['FLUX_G'], rflux=ttruth['FLUX_R'], zflux=ttruth['FLUX_Z'], w1flux=ttruth['FLUX_W1'], w2flux=ttruth['FLUX_W2'], targtype='bright') is_faint = isBGS_colors(gflux=ttruth['FLUX_G'], rflux=ttruth['FLUX_R'], zflux=ttruth['FLUX_Z'], w1flux=ttruth['FLUX_W1'], w2flux=ttruth['FLUX_W2'], targtype='faint') is_wise = isBGS_colors(gflux=ttruth['FLUX_G'], rflux=ttruth['FLUX_R'], zflux=ttruth['FLUX_Z'], w1flux=ttruth['FLUX_W1'], w2flux=ttruth['FLUX_W2'], targtype='wise') keep = np.logical_or(np.logical_or(is_bright, is_faint), is_wise) _ngood = np.count_nonzero(keep) if _ngood > 0: ngood += _ngood flux.append(tflux[keep, :]) targ.append(ttarg[keep]) truth.append(ttruth[keep]) obj.append(tobj[keep]) wave = maker.wave flux = np.vstack(flux)[:args.nspec, :] targ = vstack(targ)[:args.nspec] truth = vstack(truth)[:args.nspec] obj = vstack(obj)[:args.nspec] if args.addsnia or args.addsniip: # TARGETID in truth table is split in two; deal with it here. truth['TARGETID'] = truth['TARGETID_1'] # Set up and verify the TARGETID across all truth tables. n = len(truth) new_id = 10000000 * pixel + 100000 * j + np.arange(1, n + 1) truth['TARGETID'][:] = new_id targ['TARGETID'][:] = new_id obj['TARGETID'][:] = new_id assert (len(truth) == args.nspec) assert (np.all(targ['TARGETID'] == truth['TARGETID'])) assert (len(truth) == len(np.unique(truth['TARGETID']))) assert (len(targ) == len(np.unique(targ['TARGETID']))) assert (len(obj) == len(np.unique(obj['TARGETID']))) truthfile = os.path.join( args.simdir, 'bgs_{}_{:03}_truth.fits'.format(args.simid, j)) write_templates(truthfile, flux, wave, targ, truth, obj) # Generate simulated spectra, given observing conditions. specfile = os.path.join( args.simdir, 'bgs_{}_{:03}_spectra.fits'.format(args.simid, j)) sim_spectra(wave, flux, 'bgs', specfile, obsconditions=obs, sourcetype='bgs', targetid=truth['TARGETID'], redshift=truth['TRUEZ'], seed=args.seed, expid=j)
def get_targets(nspec, program, tileid=None, seed=None, specify_targets=dict(), specmin=0): """ Generates a set of targets for the requested program Args: nspec: (int) number of targets to generate program: (str) program name DARK, BRIGHT, GRAY, MWS, BGS, LRG, ELG, ... Options: * tileid: (int) tileid, used for setting RA,dec * seed: (int) random number seed * specify_targets: (dict of dicts) Define target properties like magnitude and redshift for each target class. Each objtype has its own key,value pair see simspec.templates.specify_galparams_dict() or simsepc.templates.specify_starparams_dict() * specmin: (int) first spectrum number (0-indexed) Returns: * fibermap * targets as tuple of (flux, wave, meta) """ if tileid is None: tile_ra, tile_dec = 0.0, 0.0 else: tile_ra, tile_dec = io.get_tile_radec(tileid) program = program.upper() log.debug('Using random seed {}'.format(seed)) np.random.seed(seed) #- Get distribution of target types true_objtype, target_objtype = sample_objtype(nspec, program) #- Get DESI wavelength coverage wavemin = desimodel.io.load_throughput('b').wavemin wavemax = desimodel.io.load_throughput('z').wavemax dw = 0.2 wave = np.arange(round(wavemin, 1), wavemax, dw) nwave = len(wave) flux = np.zeros((nspec, len(wave))) meta = empty_metatable(nmodel=nspec, objtype='SKY') fibermap = empty_fibermap(nspec) for objtype in set(true_objtype): ii = np.where(true_objtype == objtype)[0] nobj = len(ii) fibermap['OBJTYPE'][ii] = target_objtype[ii] if objtype in specify_targets.keys(): obj_kwargs = specify_targets[objtype] else: obj_kwargs = dict() # Simulate spectra if objtype == 'SKY': fibermap['DESI_TARGET'][ii] = desi_mask.SKY continue elif objtype == 'ELG': from desisim.templates import ELG elg = ELG(wave=wave) simflux, wave1, meta1 = elg.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) fibermap['DESI_TARGET'][ii] = desi_mask.ELG elif objtype == 'LRG': from desisim.templates import LRG lrg = LRG(wave=wave) simflux, wave1, meta1 = lrg.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) fibermap['DESI_TARGET'][ii] = desi_mask.LRG elif objtype == 'BGS': from desisim.templates import BGS bgs = BGS(wave=wave) simflux, wave1, meta1 = bgs.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) fibermap['DESI_TARGET'][ii] = desi_mask.BGS_ANY fibermap['BGS_TARGET'][ii] = bgs_mask.BGS_BRIGHT elif objtype == 'QSO': from desisim.templates import QSO qso = QSO(wave=wave) simflux, wave1, meta1 = qso.make_templates(nmodel=nobj, seed=seed, lyaforest=False, **obj_kwargs) fibermap['DESI_TARGET'][ii] = desi_mask.QSO # For a "bad" QSO simulate a normal star without color cuts, which isn't # right. We need to apply the QSO color-cuts to the normal stars to pull # out the correct population of contaminating stars. # Note by @moustakas: we can now do this using desisim/#150, but we are # going to need 'noisy' photometry (because the QSO color-cuts # explicitly avoid the stellar locus). elif objtype == 'QSO_BAD': from desisim.templates import STAR #from desitarget.cuts import isQSO #star = STAR(wave=wave, colorcuts_function=isQSO) star = STAR(wave=wave) simflux, wave1, meta1 = star.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) fibermap['DESI_TARGET'][ii] = desi_mask.QSO elif objtype == 'STD': from desisim.templates import FSTD fstd = FSTD(wave=wave) simflux, wave1, meta1 = fstd.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) fibermap['DESI_TARGET'][ii] = desi_mask.STD_FSTAR elif objtype == 'MWS_STAR': from desisim.templates import MWS_STAR mwsstar = MWS_STAR(wave=wave) # todo: mag ranges for different programs of STAR targets should be in desimodel if 'rmagrange' not in obj_kwargs.keys(): obj_kwargs['rmagrange'] = (15.0, 20.0) simflux, wave1, meta1 = mwsstar.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) fibermap['DESI_TARGET'][ii] = desi_mask.MWS_ANY #- MWS bit names changed after desitarget 0.6.0 so use number #- instead of name for now (bit 0 = mask 1 = MWS_MAIN currently) fibermap['MWS_TARGET'][ii] = 1 else: raise ValueError('Unable to simulate OBJTYPE={}'.format(objtype)) flux[ii] = simflux meta[ii] = meta1 fibermap['FILTER'][ii, :6] = [ 'DECAM_G', 'DECAM_R', 'DECAM_Z', 'WISE_W1', 'WISE_W2' ] fibermap['MAG'][ii, 0] = 22.5 - 2.5 * np.log10(meta['FLUX_G'][ii]) fibermap['MAG'][ii, 1] = 22.5 - 2.5 * np.log10(meta['FLUX_R'][ii]) fibermap['MAG'][ii, 2] = 22.5 - 2.5 * np.log10(meta['FLUX_Z'][ii]) fibermap['MAG'][ii, 3] = 22.5 - 2.5 * np.log10(meta['FLUX_W1'][ii]) fibermap['MAG'][ii, 4] = 22.5 - 2.5 * np.log10(meta['FLUX_W2'][ii]) #- Load fiber -> positioner mapping and tile information fiberpos = desimodel.io.load_fiberpos() #- Where are these targets? Centered on positioners for now. x = fiberpos['X'][specmin:specmin + nspec] y = fiberpos['Y'][specmin:specmin + nspec] fp = FocalPlane(tile_ra, tile_dec) ra = np.zeros(nspec) dec = np.zeros(nspec) for i in range(nspec): ra[i], dec[i] = fp.xy2radec(x[i], y[i]) #- Fill in the rest of the fibermap structure fibermap['FIBER'] = np.arange(nspec, dtype='i4') fibermap['POSITIONER'] = fiberpos['POSITIONER'][specmin:specmin + nspec] fibermap['SPECTROID'] = fiberpos['SPECTROGRAPH'][specmin:specmin + nspec] fibermap['TARGETID'] = np.random.randint(sys.maxsize, size=nspec) fibermap['TARGETCAT'] = np.zeros(nspec, dtype=(str, 20)) fibermap['LAMBDAREF'] = np.ones(nspec, dtype=np.float32) * 5400 fibermap['RA_TARGET'] = ra fibermap['DEC_TARGET'] = dec fibermap['X_TARGET'] = x fibermap['Y_TARGET'] = y fibermap['X_FVCOBS'] = fibermap['X_TARGET'] fibermap['Y_FVCOBS'] = fibermap['Y_TARGET'] fibermap['X_FVCERR'] = np.zeros(nspec, dtype=np.float32) fibermap['Y_FVCERR'] = np.zeros(nspec, dtype=np.float32) fibermap['RA_OBS'] = fibermap['RA_TARGET'] fibermap['DEC_OBS'] = fibermap['DEC_TARGET'] fibermap['BRICKNAME'] = brick.brickname(ra, dec) return fibermap, (flux, wave, meta)
class MockSpectra(object): """Generate spectra for each type of mock. Currently just choose the closest template; we can get fancier later. ToDo (@moustakas): apply Galactic extinction. """ def __init__(self, wavemin=None, wavemax=None, dw=0.2, nproc=1, rand=None, verbose=False): from lvmmodel.io import load_throughput self.tree = TemplateKDTree(nproc=nproc) # Build a default (buffered) wavelength vector. if wavemin is None: wavemin = load_throughput('b').wavemin - 10.0 if wavemax is None: wavemax = load_throughput('z').wavemax + 10.0 self.wavemin = wavemin self.wavemax = wavemax self.dw = dw self.wave = np.arange(round(wavemin, 1), wavemax, dw) self.rand = rand self.verbose = verbose #self.__normfilter = 'decam2014-r' # default normalization filter # Initialize the templates once: from desisim.templates import BGS, ELG, LRG, QSO, STAR, WD self.bgs_templates = BGS(wave=self.wave, normfilter='sdss2010-r') # Need to generalize this! self.elg_templates = ELG(wave=self.wave, normfilter='decam2014-r') self.lrg_templates = LRG(wave=self.wave, normfilter='decam2014-z') self.qso_templates = QSO(wave=self.wave, normfilter='decam2014-g') self.lya_templates = QSO(wave=self.wave, normfilter='decam2014-g') self.star_templates = STAR(wave=self.wave, normfilter='decam2014-r') self.wd_da_templates = WD(wave=self.wave, normfilter='decam2014-g', subtype='DA') self.wd_db_templates = WD(wave=self.wave, normfilter='decam2014-g', subtype='DB') def bgs(self, data, index=None, mockformat='durham_mxxl_hdf5'): """Generate spectra for BGS. Currently only the MXXL (durham_mxxl_hdf5) mock is supported. DATA needs to have Z, SDSS_absmag_r01, SDSS_01gr, VDISP, and SEED, which are assigned in mock.io.read_durham_mxxl_hdf5. See also TemplateKDTree.bgs(). """ objtype = 'BGS' if index is None: index = np.arange(len(data['Z'])) input_meta = empty_metatable(nmodel=len(index), objtype=objtype) for inkey, datakey in zip(('SEED', 'MAG', 'REDSHIFT', 'VDISP'), ('SEED', 'MAG', 'Z', 'VDISP')): input_meta[inkey] = data[datakey][index] if mockformat.lower() == 'durham_mxxl_hdf5': alldata = np.vstack((data['Z'][index], data['SDSS_absmag_r01'][index], data['SDSS_01gr'][index])).T _, templateid = self.tree.query(objtype, alldata) else: raise ValueError('Unrecognized mockformat {}!'.format(mockformat)) input_meta['TEMPLATEID'] = templateid flux, _, meta = self.bgs_templates.make_templates(input_meta=input_meta, nocolorcuts=True, novdisp=False, verbose=self.verbose) return flux, meta def elg(self, data, index=None, mockformat='gaussianfield'): """Generate spectra for the ELG sample. Currently only the GaussianField mock sample is supported. DATA needs to have Z, GR, RZ, VDISP, and SEED, which are assigned in mock.io.read_gaussianfield. See also TemplateKDTree.elg(). """ objtype = 'ELG' if index is None: index = np.arange(len(data['Z'])) input_meta = empty_metatable(nmodel=len(index), objtype=objtype) for inkey, datakey in zip(('SEED', 'MAG', 'REDSHIFT', 'VDISP'), ('SEED', 'MAG', 'Z', 'VDISP')): input_meta[inkey] = data[datakey][index] if mockformat.lower() == 'gaussianfield': alldata = np.vstack((data['Z'][index], data['GR'][index], data['RZ'][index])).T _, templateid = self.tree.query(objtype, alldata) else: raise ValueError('Unrecognized mockformat {}!'.format(mockformat)) if False: import matplotlib.pyplot as plt def elg_colorbox(ax): """Draw the ELG selection box.""" from matplotlib.patches import Polygon grlim = ax.get_ylim() coeff0, coeff1 = (1.15, -0.15), (-1.2, 1.6) rzmin, rzpivot = 0.3, (coeff1[1] - coeff0[1]) / (coeff0[0] - coeff1[0]) verts = [(rzmin, grlim[0]), (rzmin, np.polyval(coeff0, rzmin)), (rzpivot, np.polyval(coeff1, rzpivot)), ((grlim[0] - 0.1 - coeff1[1]) / coeff1[0], grlim[0] - 0.1) ] ax.add_patch(Polygon(verts, fill=False, ls='--', color='k')) fig, ax = plt.subplots() ax.scatter(data['RZ'][index], data['GR'][index]) ax.set_xlim(-0.5, 2) ; plt.ylim(-0.5, 2) elg_colorbox(ax) plt.show() import pdb ; pdb.set_trace() input_meta['TEMPLATEID'] = templateid flux, _, meta = self.elg_templates.make_templates(input_meta=input_meta, nocolorcuts=True, novdisp=False, verbose=self.verbose) return flux, meta def elg_test(self, data, index=None, mockformat='gaussianfield'): """Test script -- generate spectra for the ELG sample. Currently only the GaussianField mock sample is supported. DATA needs to have Z, GR, RZ, VDISP, and SEED, which are assigned in mock.io.read_gaussianfield. See also TemplateKDTree.elg(). """ objtype = 'ELG' if index is None: index = np.arange(len(data['Z'])) input_meta = empty_metatable(nmodel=len(index), objtype=objtype) for inkey, datakey in zip(('SEED', 'MAG', 'REDSHIFT', 'VDISP'), ('SEED', 'MAG', 'Z', 'VDISP')): input_meta[inkey] = data[datakey][index] if mockformat.lower() == 'gaussianfield': alldata = np.vstack((data['Z'][index], data['GR'][index], data['RZ'][index])).T _, templateid = self.tree.query(objtype, alldata) else: raise ValueError('Unrecognized mockformat {}!'.format(mockformat)) import matplotlib.pyplot as plt from scipy.interpolate import interp1d f1 = interp1d(np.squeeze(self.tree.elg_kcorr['REDSHIFT']), np.squeeze(self.tree.elg_kcorr['GR']), axis=0) gr = f1(data['Z'][index]) plt.plot(np.squeeze(self.tree.elg_kcorr['REDSHIFT']), np.squeeze(self.tree.elg_kcorr['GR'])[:, 500]) plt.scatter(data['Z'][index], gr[:, 500], marker='x', color='red', s=15) plt.show() def elg_colorbox(ax): """Draw the ELG selection box.""" from matplotlib.patches import Polygon grlim = ax.get_ylim() coeff0, coeff1 = (1.15, -0.15), (-1.2, 1.6) rzmin, rzpivot = 0.3, (coeff1[1] - coeff0[1]) / (coeff0[0] - coeff1[0]) verts = [(rzmin, grlim[0]), (rzmin, np.polyval(coeff0, rzmin)), (rzpivot, np.polyval(coeff1, rzpivot)), ((grlim[0] - 0.1 - coeff1[1]) / coeff1[0], grlim[0] - 0.1) ] ax.add_patch(Polygon(verts, fill=False, ls='--', color='k')) fig, ax = plt.subplots() ax.scatter(data['RZ'][index], data['GR'][index]) ax.set_xlim(-0.5, 2) ; plt.ylim(-0.5, 2) elg_colorbox(ax) plt.show() import pdb ; pdb.set_trace() input_meta['TEMPLATEID'] = templateid flux, _, meta = self.elg_templates.make_templates(input_meta=input_meta, nocolorcuts=True, novdisp=False, verbose=self.verbose) return flux, meta def lrg(self, data, index=None, mockformat='gaussianfield'): """Generate spectra for the LRG sample. Currently only the GaussianField mock sample is supported. DATA needs to have Z, GR, RZ, VDISP, and SEED, which are assigned in mock.io.read_gaussianfield. See also TemplateKDTree.lrg(). """ objtype = 'LRG' if index is None: index = np.arange(len(data['Z'])) nobj = len(index) input_meta = empty_metatable(nmodel=len(index), objtype=objtype) for inkey, datakey in zip(('SEED', 'MAG', 'REDSHIFT', 'VDISP'), ('SEED', 'MAG', 'Z', 'VDISP')): input_meta[inkey] = data[datakey][index] if mockformat.lower() == 'gaussianfield': # This is wrong: choose a template with equal probability. templateid = self.rand.choice(self.tree.lrg_meta['TEMPLATEID'], len(index)) else: raise ValueError('Unrecognized mockformat {}!'.format(mockformat)) input_meta['TEMPLATEID'] = templateid flux, _, meta = self.lrg_templates.make_templates(input_meta=input_meta, nocolorcuts=True, novdisp=False, verbose=self.verbose) return flux, meta def mws(self, data, index=None, mockformat='galaxia'): """Generate spectra for the MWS_NEARBY and MWS_MAIN samples. """ objtype = 'STAR' if index is None: index = np.arange(len(data['Z'])) input_meta = empty_metatable(nmodel=len(index), objtype=objtype) for inkey, datakey in zip(('SEED', 'MAG', 'REDSHIFT', 'TEFF', 'LOGG', 'FEH'), ('SEED', 'MAG', 'Z', 'TEFF', 'LOGG', 'FEH')): input_meta[inkey] = data[datakey][index] if mockformat.lower() == '100pc': alldata = np.vstack((data['TEFF'][index], data['LOGG'][index], data['FEH'][index])).T _, templateid = self.tree.query(objtype, alldata) elif mockformat.lower() == 'galaxia': alldata = np.vstack((data['TEFF'][index], data['LOGG'][index], data['FEH'][index])).T _, templateid = self.tree.query(objtype, alldata) else: raise ValueError('Unrecognized mockformat {}!'.format(mockformat)) input_meta['TEMPLATEID'] = templateid flux, _, meta = self.star_templates.make_templates(input_meta=input_meta, verbose=self.verbose) # Note! No colorcuts. return flux, meta def mws_nearby(self, data, index=None, mockformat='100pc'): """Generate spectra for the MWS_NEARBY sample. """ flux, meta = self.mws(data, index=index, mockformat=mockformat) return flux, meta def mws_main(self, data, index=None, mockformat='galaxia'): """Generate spectra for the MWS_MAIN sample. """ flux, meta = self.mws(data, index=index, mockformat=mockformat) return flux, meta def faintstar(self, data, index=None, mockformat='galaxia'): """Generate spectra for the FAINTSTAR (faint stellar) sample. """ flux, meta = self.mws(data, index=index, mockformat=mockformat) return flux, meta def mws_wd(self, data, index=None, mockformat='wd'): """Generate spectra for the MWS_WD sample. Deal with DA vs DB white dwarfs separately. """ objtype = 'WD' if index is None: index = np.arange(len(data['Z'])) nobj = len(index) input_meta = empty_metatable(nmodel=nobj, objtype=objtype) for inkey, datakey in zip(('SEED', 'MAG', 'REDSHIFT', 'TEFF', 'LOGG', 'SUBTYPE'), ('SEED', 'MAG', 'Z', 'TEFF', 'LOGG', 'TEMPLATESUBTYPE')): input_meta[inkey] = data[datakey][index] if mockformat.lower() == 'wd': meta = empty_metatable(nmodel=nobj, objtype=objtype) flux = np.zeros([nobj, len(self.wave)], dtype='f4') for subtype in ('DA', 'DB'): these = np.where(input_meta['SUBTYPE'] == subtype)[0] if len(these) > 0: alldata = np.vstack((data['TEFF'][index][these], data['LOGG'][index][these])).T _, templateid = self.tree.query(objtype, alldata, subtype=subtype) input_meta['TEMPLATEID'][these] = templateid template_function = 'wd_{}_templates'.format(subtype.lower()) flux1, _, meta1 = getattr(self, template_function).make_templates(input_meta=input_meta[these], verbose=self.verbose) meta[these] = meta1 flux[these, :] = flux1 else: raise ValueError('Unrecognized mockformat {}!'.format(mockformat)) return flux, meta def qso(self, data, index=None, mockformat='gaussianfield'): """Generate spectra for the QSO or QSO/LYA samples. Note: We need to make sure NORMFILTER matches! """ from desisim.lya_spectra import get_spectra from desisim.lya_spectra import read_lya_skewers,apply_lya_transmission import fitsio log = get_logger() objtype = 'QSO' if index is None: index = np.arange(len(data['Z'])) nobj = len(index) if mockformat.lower() == 'gaussianfield': input_meta = empty_metatable(nmodel=nobj, objtype=objtype) for inkey, datakey in zip(('SEED', 'MAG', 'REDSHIFT'), ('SEED', 'MAG', 'Z')): input_meta[inkey] = data[datakey][index] # Build the tracer and Lya forest QSO spectra separately. meta = empty_metatable(nmodel=nobj, objtype=objtype) flux = np.zeros([nobj, len(self.wave)], dtype='f4') lya = np.where( data['TEMPLATESUBTYPE'][index] == 'LYA' )[0] tracer = np.where( data['TEMPLATESUBTYPE'][index] == '' )[0] if len(tracer) > 0: flux1, _, meta1 = self.qso_templates.make_templates(input_meta=input_meta[tracer], lyaforest=False, nocolorcuts=True, verbose=self.verbose) meta[tracer] = meta1 flux[tracer, :] = flux1 if len(lya) > 0: ilya=index[lya].astype(int) nqso=ilya.size log.info("Generating spectra of %d lya QSOs"%nqso) if 'LYAHDU' in data : # this is the old format with one HDU per spectrum alllyafile = data['LYAFILES'][ilya] alllyahdu = data['LYAHDU'][ilya] for lyafile in sorted(set(alllyafile)): these = np.where( lyafile == alllyafile )[0] templateid = alllyahdu[these] - 1 # templateid is 0-indexed flux1, _, meta1 = get_spectra(lyafile, templateid=templateid, normfilter=data['FILTERNAME'], rand=self.rand, qso=self.lya_templates, nocolorcuts=True) meta1['SUBTYPE'] = 'LYA' meta[lya[these]] = meta1 flux[lya[these], :] = flux1 else : # new format # read skewers skewer_wave=None skewer_trans=None skewer_meta=None # all the files that contain at least one QSO skewer alllyafile = data['LYAFILES'][ilya] uniquelyafiles = sorted(set(alllyafile)) for lyafile in uniquelyafiles : these = np.where( alllyafile == lyafile )[0] objid_in_data=data['OBJID'][ilya][these] objid_in_mock=(fitsio.read(lyafile, columns=['MOCKID'],upper=True,ext=1).astype(float)).astype(int) o2i=dict() for i,o in enumerate(objid_in_mock) : o2i[o]=i indices_in_mock_healpix=np.zeros(objid_in_data.size).astype(int) for i,o in enumerate(objid_in_data) : if not o in o2i : log.error("No MOCKID={} in {}. It's a bug, should never happen".format(o,lyafile)) raise(KeyError("No MOCKID={} in {}. It's a bug, should never happen".format(o,lyafile))) indices_in_mock_healpix[i]=o2i[o] tmp_wave,tmp_trans,tmp_meta = read_lya_skewers(lyafile,indices=indices_in_mock_healpix) if skewer_wave is None : skewer_wave=tmp_wave dw=skewer_wave[1]-skewer_wave[0] # this is just to check same wavelength skewer_trans=np.zeros((nqso,skewer_wave.size)) # allocate skewer_array skewer_meta=dict() for k in tmp_meta.dtype.names : skewer_meta[k]=np.zeros(nqso).astype(tmp_meta[k].dtype) else : # check wavelength is the same for all skewers assert(np.max(np.abs(wave-tmp_wave))<0.001*dw) skewer_trans[these] = tmp_trans for k in skewer_meta.keys() : skewer_meta[k][these]=tmp_meta[k] # check we matched things correctly assert(np.max(np.abs(skewer_meta["Z"]-data['Z'][ilya]))<0.000001) assert(np.max(np.abs(skewer_meta["RA"]-data['RA'][ilya]))<0.000001) assert(np.max(np.abs(skewer_meta["DEC"]-data['DEC'][ilya]))<0.000001) # now we create a series of QSO spectra all at once # this is faster than calling each one at a time # we use the provided QSO template class seed = self.rand.randint(2**32) qso = self.lya_templates qso_flux, qso_wave, qso_meta = qso.make_templates(nmodel=nqso, redshift=data['Z'][ilya], mag=data['MAG'][ilya], seed=seed, lyaforest=False, nocolorcuts=True) # apply transmission to QSOs qso_flux = apply_lya_transmission(qso_wave,qso_flux,skewer_wave,skewer_trans) # save this qso_meta['SUBTYPE'] = 'LYA' meta[lya] = qso_meta flux[lya, :] = qso_flux else: raise ValueError('Unrecognized mockformat {}!'.format(mockformat)) return flux, meta def sky(self, data, index=None, mockformat=None): """Generate spectra for SKY. """ objtype = 'SKY' if index is None: index = np.arange(len(data['Z'])) nobj = len(index) meta = empty_metatable(nmodel=nobj, objtype=objtype) for inkey, datakey in zip(('SEED', 'REDSHIFT'), ('SEED', 'Z')): meta[inkey] = data[datakey][index] flux = np.zeros((nobj, len(self.wave)), dtype='i1') return flux, meta
def get_targets(nspec, program, tileid=None, seed=None, specify_targets=dict(), specmin=0): """ Generates a set of targets for the requested program Args: nspec: (int) number of targets to generate program: (str) program name DARK, BRIGHT, GRAY, MWS, BGS, LRG, ELG, ... Options: * tileid: (int) tileid, used for setting RA,dec * seed: (int) random number seed * specify_targets: (dict of dicts) Define target properties like magnitude and redshift for each target class. Each objtype has its own key,value pair see simspec.templates.specify_galparams_dict() or simsepc.templates.specify_starparams_dict() * specmin: (int) first spectrum number (0-indexed) Returns: * fibermap * targets as tuple of (flux, wave, meta) """ if tileid is None: tile_ra, tile_dec = 0.0, 0.0 else: tile_ra, tile_dec = io.get_tile_radec(tileid) program = program.upper() log.debug('Using random seed {}'.format(seed)) np.random.seed(seed) #- Get distribution of target types true_objtype, target_objtype = sample_objtype(nspec, program) #- Get DESI wavelength coverage try: params = desimodel.io.load_desiparams() wavemin = params['ccd']['b']['wavemin'] wavemax = params['ccd']['z']['wavemax'] except KeyError: wavemin = desimodel.io.load_throughput('b').wavemin wavemax = desimodel.io.load_throughput('z').wavemax dw = 0.2 wave = np.arange(round(wavemin, 1), wavemax, dw) nwave = len(wave) flux = np.zeros( (nspec, len(wave)) ) meta, _ = empty_metatable(nmodel=nspec, objtype='SKY') objmeta = dict() fibermap = empty_fibermap(nspec) targetid = np.random.randint(sys.maxsize, size=nspec).astype(np.int64) meta['TARGETID'] = targetid fibermap['TARGETID'] = targetid for objtype in set(true_objtype): ii = np.where(true_objtype == objtype)[0] nobj = len(ii) fibermap['OBJTYPE'][ii] = target_objtype[ii] if objtype in specify_targets.keys(): obj_kwargs = specify_targets[objtype] else: obj_kwargs = dict() # Simulate spectra if objtype == 'SKY': fibermap['DESI_TARGET'][ii] = desi_mask.SKY continue elif objtype == 'ELG': from desisim.templates import ELG elg = ELG(wave=wave) simflux, wave1, meta1, objmeta1 = elg.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) fibermap['DESI_TARGET'][ii] = desi_mask.ELG elif objtype == 'LRG': from desisim.templates import LRG lrg = LRG(wave=wave) simflux, wave1, meta1, objmeta1 = lrg.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) fibermap['DESI_TARGET'][ii] = desi_mask.LRG elif objtype == 'BGS': from desisim.templates import BGS bgs = BGS(wave=wave) simflux, wave1, meta1, objmeta1 = bgs.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) fibermap['DESI_TARGET'][ii] = desi_mask.BGS_ANY fibermap['BGS_TARGET'][ii] = bgs_mask.BGS_BRIGHT elif objtype == 'QSO': from desisim.templates import QSO qso = QSO(wave=wave) simflux, wave1, meta1, objmeta1 = qso.make_templates(nmodel=nobj, seed=seed, lyaforest=False, **obj_kwargs) fibermap['DESI_TARGET'][ii] = desi_mask.QSO # For a "bad" QSO simulate a normal star without color cuts, which isn't # right. We need to apply the QSO color-cuts to the normal stars to pull # out the correct population of contaminating stars. # Note by @moustakas: we can now do this using desisim/#150, but we are # going to need 'noisy' photometry (because the QSO color-cuts # explicitly avoid the stellar locus). elif objtype == 'QSO_BAD': from desisim.templates import STAR #from desitarget.cuts import isQSO #star = STAR(wave=wave, colorcuts_function=isQSO) star = STAR(wave=wave) simflux, wave1, meta1, objmeta1 = star.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) fibermap['DESI_TARGET'][ii] = desi_mask.QSO elif objtype == 'STD': from desisim.templates import STD std = STD(wave=wave) simflux, wave1, meta1, objmeta1 = std.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) #- Loop options for forwards/backwards compatibility for name in ['STD_FAINT', 'STD_FSTAR', 'STD']: if name in desi_mask.names(): fibermap['DESI_TARGET'][ii] |= desi_mask[name] break elif objtype == 'MWS_STAR': from desisim.templates import MWS_STAR mwsstar = MWS_STAR(wave=wave) # TODO: mag ranges for different programs of STAR targets should be in desimodel if 'magrange' not in obj_kwargs.keys(): obj_kwargs['magrange'] = (15.0,20.0) simflux, wave1, meta1, objmeta1 = mwsstar.make_templates(nmodel=nobj, seed=seed, **obj_kwargs) fibermap['DESI_TARGET'][ii] |= desi_mask.MWS_ANY #- MWS bit names changed after desitarget 0.6.0 so use number #- instead of name for now (bit 0 = mask 1 = MWS_MAIN currently) fibermap['MWS_TARGET'][ii] = 1 else: raise ValueError('Unable to simulate OBJTYPE={}'.format(objtype)) # Assign targetid meta1['TARGETID'] = targetid[ii] if hasattr(objmeta1, 'data'): # simqso.sqgrids.QsoSimPoints object objmeta1.data['TARGETID'] = targetid[ii] else: if len(objmeta1) > 0: objmeta1['TARGETID'] = targetid[ii] # We want the dict key tied to the "true" object type (e.g., STAR), # not, e.g., QSO_BAD. objmeta[meta1['OBJTYPE'][0]] = objmeta1 flux[ii] = simflux meta[ii] = meta1 for band in ['G', 'R', 'Z', 'W1', 'W2']: key = 'FLUX_'+band fibermap[key][ii] = meta[key][ii] #- TODO: FLUX_IVAR #- Load fiber -> positioner mapping and tile information fiberpos = desimodel.io.load_fiberpos() #- Where are these targets? Centered on positioners for now. x = fiberpos['X'][specmin:specmin+nspec] y = fiberpos['Y'][specmin:specmin+nspec] fp = FocalPlane(tile_ra, tile_dec) ra = np.zeros(nspec) dec = np.zeros(nspec) for i in range(nspec): ra[i], dec[i] = fp.xy2radec(x[i], y[i]) #- Fill in the rest of the fibermap structure fibermap['FIBER'] = np.arange(nspec, dtype='i4') fibermap['POSITIONER'] = fiberpos['POSITIONER'][specmin:specmin+nspec] fibermap['SPECTROID'] = fiberpos['SPECTROGRAPH'][specmin:specmin+nspec] fibermap['TARGETCAT'] = np.zeros(nspec, dtype=(str, 20)) fibermap['LAMBDA_REF'] = np.ones(nspec, dtype=np.float32)*5400 fibermap['TARGET_RA'] = ra fibermap['TARGET_DEC'] = dec fibermap['DESIGN_X'] = x fibermap['DESIGN_Y'] = y fibermap['FIBER_RA'] = fibermap['TARGET_RA'] fibermap['FIBER_DEC'] = fibermap['TARGET_DEC'] fibermap['BRICKNAME'] = brick.brickname(ra, dec) return fibermap, (flux, wave, meta, objmeta)