def new_exposure(flavor, nspec=5000, night=None, expid=None, tileid=None, \ airmass=1.0, exptime=None): """ Create a new exposure and output input simulation files. Does not generate pixel-level simulations or noisy spectra. Args: nspec (optional): integer number of spectra to simulate night (optional): YEARMMDD string expid (optional): positive integer exposure ID tileid (optional): tile ID airmass (optional): airmass, default 1.0 Writes: $DESI_SPECTRO_SIM/$PIXPROD/{night}/fibermap-{expid}.fits $DESI_SPECTRO_SIM/$PIXPROD/{night}/simspec-{expid}.fits Returns: fibermap numpy structured array truth dictionary """ if expid is None: expid = get_next_expid() if tileid is None: tileid = get_next_tileid() if night is None: #- simulation obs time = now, even if sun is up dateobs = time.gmtime() night = get_night(utc=dateobs) else: #- 10pm on night YEARMMDD dateobs = time.strptime(night + ':22', '%Y%m%d:%H') params = desimodel.io.load_desiparams() if flavor == 'arc': infile = os.getenv( 'DESI_ROOT' ) + '/spectro/templates/calib/v0.2/arc-lines-average.fits' d = fits.getdata(infile, 1) wave = d['AIRWAVE'] phot = d['ELECTRONS'] truth = dict(WAVE=wave) meta = None fibermap = desispec.io.fibermap.empty_fibermap(nspec) for channel in ('B', 'R', 'Z'): thru = desimodel.io.load_throughput(channel) ii = np.where((thru.wavemin <= wave) & (wave <= thru.wavemax))[0] truth['WAVE_' + channel] = wave[ii] truth['PHOT_' + channel] = np.tile(phot[ii], nspec).reshape(nspec, len(ii)) elif flavor == 'flat': infile = os.getenv( 'DESI_ROOT' ) + '/spectro/templates/calib/v0.2/flat-3100K-quartz-iodine.fits' flux = fits.getdata(infile, 0) hdr = fits.getheader(infile, 0) wave = desispec.io.util.header2wave(hdr) #- resample to 0.2 A grid dw = 0.2 ww = np.arange(wave[0], wave[-1] + dw / 2, dw) flux = resample_flux(ww, wave, flux) wave = ww #- Convert to 2D for projection flux = np.tile(flux, nspec).reshape(nspec, len(wave)) truth = dict(WAVE=wave, FLUX=flux) meta = None fibermap = desispec.io.fibermap.empty_fibermap(nspec) for channel in ('B', 'R', 'Z'): thru = desimodel.io.load_throughput(channel) ii = (thru.wavemin <= wave) & (wave <= thru.wavemax) phot = thru.photons(wave[ii], flux[:, ii], units=hdr['BUNIT'], objtype='CALIB', exptime=10) truth['WAVE_' + channel] = wave[ii] truth['PHOT_' + channel] = phot elif flavor == 'science': fibermap, truth = get_targets(nspec, tileid=tileid) flux = truth['FLUX'] wave = truth['WAVE'] nwave = len(wave) if exptime is None: exptime = params['exptime'] #- Load sky [Magic knowledge of units 1e-17 erg/s/cm2/A/arcsec2] skyfile = os.getenv('DESIMODEL') + '/data/spectra/spec-sky.dat' skywave, skyflux = np.loadtxt(skyfile, unpack=True) skyflux = np.interp(wave, skywave, skyflux) truth['SKYFLUX'] = skyflux for channel in ('B', 'R', 'Z'): thru = desimodel.io.load_throughput(channel) ii = np.where((thru.wavemin <= wave) & (wave <= thru.wavemax))[0] #- Project flux to photons phot = thru.photons(wave[ii], flux[:, ii], units=truth['UNITS'], objtype=truth['OBJTYPE'], exptime=exptime, airmass=airmass) truth['PHOT_' + channel] = phot truth['WAVE_' + channel] = wave[ii] #- Project sky flux to photons skyphot = thru.photons(wave[ii], skyflux[ii] * airmass, units='1e-17 erg/s/cm2/A/arcsec2', objtype='SKY', exptime=exptime, airmass=airmass) #- 2D version ### truth['SKYPHOT_'+channel] = np.tile(skyphot, nspec).reshape((nspec, len(ii))) #- 1D version truth['SKYPHOT_' + channel] = skyphot.astype(np.float32) #- NOTE: someday skyflux and skyphot may be 2D instead of 1D #- Extract the metadata part of the truth dictionary into a table columns = ( 'OBJTYPE', 'REDSHIFT', 'TEMPLATEID', 'D4000', 'OIIFLUX', 'VDISP', ) meta = {key: truth[key] for key in columns} #- (end indentation for arc/flat/science flavors) #- Override $DESI_SPECTRO_DATA in order to write to simulation area datadir_orig = os.getenv('DESI_SPECTRO_DATA') simbase = os.path.join(os.getenv('DESI_SPECTRO_SIM'), os.getenv('PIXPROD')) os.environ['DESI_SPECTRO_DATA'] = simbase #- Write fibermap telera, teledec = io.get_tile_radec(tileid) hdr = dict( NIGHT=(night, 'Night of observation YEARMMDD'), EXPID=(expid, 'DESI exposure ID'), TILEID=(tileid, 'DESI tile ID'), FLAVOR=(flavor, 'Flavor [arc, flat, science, ...]'), TELRA=(telera, 'Telescope pointing RA [degrees]'), TELDEC=(teledec, 'Telescope pointing dec [degrees]'), ) #- ISO 8601 DATE-OBS year-mm-ddThh:mm:ss fiberfile = desispec.io.findfile('fibermap', night, expid) desispec.io.write_fibermap(fiberfile, fibermap, header=hdr) print fiberfile #- Write simspec; expand fibermap header hdr['AIRMASS'] = (airmass, 'Airmass at middle of exposure') hdr['EXPTIME'] = (exptime, 'Exposure time [sec]') hdr['DATE-OBS'] = (time.strftime('%FT%T', dateobs), 'Start of exposure') simfile = io.write_simspec(meta, truth, expid, night, header=hdr) print(simfile) #- Update obslog that we succeeded with this exposure update_obslog(flavor, expid, dateobs, tileid) #- Restore $DESI_SPECTRO_DATA if datadir_orig is not None: os.environ['DESI_SPECTRO_DATA'] = datadir_orig else: del os.environ['DESI_SPECTRO_DATA'] return fibermap, truth
def new_exposure(program, nspec=5000, night=None, expid=None, tileid=None, nproc=None, seed=None, obsconditions=None, specify_targets=dict(), testslit=False, exptime=None, arc_lines_filename=None, flat_spectrum_filename=None, outdir=None, config='desi', telescope=None, overwrite=False): """ Create a new exposure and output input simulation files. Does not generate pixel-level simulations or noisy spectra. Args: program (str): 'arc', 'flat', 'bright', 'dark', 'bgs', 'mws', ... nspec (int, optional): number of spectra to simulate night (str, optional): YEARMMDD string expid (int, optional): positive integer exposure ID tileid (int, optional): integer tile ID nproc (object, optional): What does this do? seed (int, optional): random seed obsconditions (str or dict-like, optional): see options below specify_targets (dict of dicts, optional): 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() testslit (bool, optional): simulate test slit if True, default False; only for arc/flat exptime (float, optional): exposure time [seconds], overrides obsconditions['EXPTIME'] arc_lines_filename (str, optional): use alternate arc lines filename (used if program="arc") flat_spectrum_filename (str, optional): use alternate flat spectrum filename (used if program="flat") outdir (str, optional): output directory config (str, optional): the yaml configuration to load telescope (str, optional): the telescope used (i.e. 1m, 160mm) overwrite (bool, optional): optionally clobber existing files Returns: science: sim, fibermap, meta, obsconditions, objmeta Writes to outdir or $DESI_SPECTRO_SIM/$PIXPROD/{night}/ * fibermap-{expid}.fits * simspec-{expid}.fits input obsconditions can be a string 'dark', 'gray', 'bright', or dict-like observation metadata with keys SEEING (arcsec), EXPTIME (sec), AIRMASS, MOONFRAC (0-1), MOONALT (deg), MOONSEP (deg). Output obsconditions is is expanded dict-like structure. program is used to pick the sky brightness, and is propagated to desisim.targets.sample_objtype() to get the correct distribution of targets for a given program, e.g. ELGs, LRGs, QSOs for program='dark'. if program is 'arc' or 'flat', then `sim` is truth table with keys FLUX and WAVE; and meta=None and obsconditions=None. Also see simexp.simarc(), .simflat(), and .simscience(), the last of which simulates a science exposure given surveysim obsconditions input, fiber assignments, and pre-generated mock target spectra. """ if expid is None: expid = get_next_expid() if tileid is None: tileid = get_next_tileid() if night is None: #- simulation obs time = now, even if sun is up dateobs = time.gmtime() night = get_night(utc=dateobs) else: #- 10pm on night YEARMMDD night = str(night) #- just in case we got an integer instead of string dateobs = time.strptime(night + ':22', '%Y%m%d:%H') outsimspec = desisim.io.findfile('simspec', night, expid) outfibermap = desisim.io.findfile('simfibermap', night, expid) if outdir is not None: outsimspec = os.path.join(outdir, os.path.basename(outsimspec)) outfibermap = os.path.join(outdir, os.path.basename(outfibermap)) program = program.lower() log.debug('Generating {} targets'.format(nspec)) header = dict(NIGHT=night, EXPID=expid, PROGRAM=program) if program in ('arc', 'flat'): header['FLAVOR'] = program else: header['FLAVOR'] = 'science' #- ISO 8601 DATE-OBS year-mm-ddThh:mm:ss header['DATE-OBS'] = time.strftime('%FT%T', dateobs) if program == 'arc': if arc_lines_filename is None: infile = os.getenv( 'DESI_ROOT' ) + '/spectro/templates/calib/v0.4/arc-lines-average-in-vacuum-from-winlight-20170118.fits' else: infile = arc_lines_filename arcdata = fits.getdata(infile, 1) if exptime is None: exptime = 5 wave, phot, fibermap = desisim.simexp.simarc(arcdata, nspec=nspec, testslit=testslit) header['EXPTIME'] = exptime desisim.io.write_simspec_arc(outsimspec, wave, phot, header, fibermap=fibermap, overwrite=overwrite) fibermap.meta['NIGHT'] = night fibermap.meta['EXPID'] = expid desispec.io.write_fibermap(outfibermap, fibermap) truth = dict(WAVE=wave, PHOT=phot, UNITS='photon') return truth, fibermap, None, None, None elif program == 'flat': if flat_spectrum_filename is None: infile = os.getenv( 'DESI_ROOT' ) + '/spectro/templates/calib/v0.4/flat-3100K-quartz-iodine.fits' else: infile = flat_spectrum_filename if exptime is None: exptime = 10 sim, fibermap = desisim.simexp.simflat(infile, nspec=nspec, exptime=exptime, testslit=testslit, psfconvolve=False) header['EXPTIME'] = exptime header['FLAVOR'] = 'flat' desisim.io.write_simspec(sim, truth=None, fibermap=fibermap, obs=None, expid=expid, night=night, header=header, filename=outsimspec, overwrite=overwrite) fibermap.meta['NIGHT'] = night fibermap.meta['EXPID'] = expid desispec.io.write_fibermap(outfibermap, fibermap) # fluxunits = 1e-17 * u.erg / (u.s * u.cm**2 * u.Angstrom) fluxunits = '1e-17 erg/(s * cm2 * Angstrom)' flux = sim.simulated['source_flux'].to(fluxunits) wave = sim.simulated['wavelength'].to('Angstrom') truth = dict(WAVE=wave, FLUX=flux, UNITS=str(fluxunits)) return truth, fibermap, None, None, None #- all other programs fibermap, (flux, wave, meta, objmeta) = get_targets_parallel(nspec, program, tileid=tileid, nproc=nproc, seed=seed, specify_targets=specify_targets, config=config, telescope=telescope) if obsconditions is None: if program in ['dark', 'lrg', 'qso']: obsconditions = desisim.simexp.reference_conditions['DARK'] elif program in ['elg', 'gray', 'grey']: obsconditions = desisim.simexp.reference_conditions['GRAY'] elif program in ['mws', 'bgs', 'bright']: obsconditions = desisim.simexp.reference_conditions['BRIGHT'] else: raise ValueError('unknown program {}'.format(program)) elif isinstance(obsconditions, str): try: obsconditions = desisim.simexp.reference_conditions[ obsconditions.upper()] except KeyError: raise ValueError('obsconditions {} not in {}'.format( obsconditions.upper(), list(desisim.simexp.reference_conditions.keys()))) if exptime is not None: obsconditions['EXPTIME'] = exptime desiparams = load_desiparams(config=config, telescope=telescope) sim = simulate_spectra(wave, flux, fibermap=fibermap, obsconditions=obsconditions, psfconvolve=False, specsim_config_file=config, params=desiparams) #- Write fibermap telera, teledec = io.get_tile_radec(tileid) hdr = dict( NIGHT=(night, 'Night of observation YEARMMDD'), EXPID=(expid, 'DESI exposure ID'), TILEID=(tileid, 'DESI tile ID'), PROGRAM=(program, 'program [dark, bright, ...]'), FLAVOR=('science', 'Flavor [arc, flat, science, zero, ...]'), TELRA=(telera, 'Telescope pointing RA [degrees]'), TELDEC=(teledec, 'Telescope pointing dec [degrees]'), AIRMASS=(obsconditions['AIRMASS'], 'Airmass at middle of exposure'), EXPTIME=(obsconditions['EXPTIME'], 'Exposure time [sec]'), SEEING=(obsconditions['SEEING'], 'Seeing FWHM [arcsec]'), MOONFRAC=(obsconditions['MOONFRAC'], 'Moon illumination fraction 0-1; 1=full'), MOONALT=(obsconditions['MOONALT'], 'Moon altitude [degrees]'), MOONSEP=(obsconditions['MOONSEP'], 'Moon:tile separation angle [degrees]'), ) hdr['DATE-OBS'] = (time.strftime('%FT%T', dateobs), 'Start of exposure') simfile = io.write_simspec(sim, meta, fibermap, obsconditions, expid, night, objmeta=objmeta, header=hdr, filename=outsimspec, overwrite=overwrite) if not isinstance(fibermap, table.Table): fibermap = table.Table(fibermap) fibermap.meta.update(hdr) desispec.io.write_fibermap(outfibermap, fibermap) log.info('Wrote ' + outfibermap) update_obslog(obstype='science', program=program, expid=expid, dateobs=dateobs, tileid=tileid) return sim, fibermap, meta, obsconditions, objmeta
def new_exposure(flavor, nspec=5000, night=None, expid=None, tileid=None, airmass=1.0, \ exptime=None): """ Create a new exposure and output input simulation files. Does not generate pixel-level simulations or noisy spectra. Args: nspec (optional): integer number of spectra to simulate night (optional): YEARMMDD string expid (optional): positive integer exposure ID tileid (optional): tile ID airmass (optional): airmass, default 1.0 Writes: $DESI_SPECTRO_SIM/$PIXPROD/{night}/fibermap-{expid}.fits $DESI_SPECTRO_SIM/$PIXPROD/{night}/simspec-{expid}.fits Returns: fibermap numpy structured array truth dictionary """ if expid is None: expid = get_next_expid() if tileid is None: tileid = get_next_tileid() if night is None: #- simulation obs time = now, even if sun is up dateobs = time.gmtime() night = get_night(utc=dateobs) else: #- 10pm on night YEARMMDD dateobs = time.strptime(night+':22', '%Y%m%d:%H') params = desimodel.io.load_desiparams() if flavor == 'arc': infile = os.getenv('DESI_ROOT')+'/spectro/templates/calib/v0.1/arc-lines-average.fits' d = fits.getdata(infile, 1) wave = d['AIRWAVE'] phot = d['ELECTRONS'] truth = dict(WAVE=wave) meta = None fibermap = desispec.io.fibermap.empty_fibermap(nspec) for channel in ('B', 'R', 'Z'): thru = desimodel.io.load_throughput(channel) ii = np.where( (thru.wavemin <= wave) & (wave <= thru.wavemax) )[0] truth['WAVE_'+channel] = wave[ii] truth['PHOT_'+channel] = np.tile(phot[ii], nspec).reshape(nspec, len(ii)) elif flavor == 'flat': infile = os.getenv('DESI_ROOT')+'/spectro/templates/calib/v0.1/flat-3100K-quartz-iodine.fits' flux = fits.getdata(infile, 0) hdr = fits.getheader(infile, 0) wave = desispec.io.util.header2wave(hdr) #- resample to 0.2 A grid dw = 0.2 ww = np.arange(wave[0], wave[-1]+dw/2, dw) flux = resample_flux(ww, wave, flux) wave = ww #- Convert to 2D for projection flux = np.tile(flux, nspec).reshape(nspec, len(wave)) truth = dict(WAVE=wave, FLUX=flux) meta = None fibermap = desispec.io.fibermap.empty_fibermap(nspec) for channel in ('B', 'R', 'Z'): psf = desimodel.io.load_psf(channel) thru = desimodel.io.load_throughput(channel) ii = (psf.wmin <= wave) & (wave <= psf.wmax) phot = thru.photons(wave[ii], flux[:,ii], units=hdr['BUNIT'], objtype='CALIB') truth['WAVE_'+channel] = wave[ii] truth['PHOT_'+channel] = phot elif flavor == 'science': fibermap, truth = get_targets(nspec, tileid=tileid) flux = truth['FLUX'] wave = truth['WAVE'] nwave = len(wave) if exptime is None: exptime = params['exptime'] #- Load sky [Magic knowledge of units 1e-17 erg/s/cm2/A/arcsec2] skyfile = os.getenv('DESIMODEL')+'/data/spectra/spec-sky.dat' skywave, skyflux = np.loadtxt(skyfile, unpack=True) skyflux = np.interp(wave, skywave, skyflux) truth['SKYFLUX'] = skyflux for channel in ('B', 'R', 'Z'): thru = desimodel.io.load_throughput(channel) ii = np.where( (thru.wavemin <= wave) & (wave <= thru.wavemax) )[0] #- Project flux to photons phot = thru.photons(wave[ii], flux[:,ii], units='1e-17 erg/s/cm2/A', objtype=truth['OBJTYPE'], exptime=exptime, airmass=airmass) truth['PHOT_'+channel] = phot truth['WAVE_'+channel] = wave[ii] #- Project sky flux to photons skyphot = thru.photons(wave[ii], skyflux[ii]*airmass, units='1e-17 erg/s/cm2/A/arcsec2', objtype='SKY', exptime=exptime, airmass=airmass) #- 2D version ### truth['SKYPHOT_'+channel] = np.tile(skyphot, nspec).reshape((nspec, len(ii))) #- 1D version truth['SKYPHOT_'+channel] = skyphot.astype(np.float32) #- NOTE: someday skyflux and skyphot may be 2D instead of 1D #- Extract the metadata part of the truth dictionary into a table columns = ( 'OBJTYPE', 'REDSHIFT', 'TEMPLATEID', 'O2FLUX', ) meta = _dict2ndarray(truth, columns) #- (end indentation for arc/flat/science flavors) #- Write fibermap telera, teledec = io.get_tile_radec(tileid) hdr = dict( NIGHT = (night, 'Night of observation YEARMMDD'), EXPID = (expid, 'DESI exposure ID'), TILEID = (tileid, 'DESI tile ID'), FLAVOR = (flavor, 'Flavor [arc, flat, science, ...]'), TELERA = (telera, 'Telescope pointing RA [degrees]'), TELEDEC = (teledec, 'Telescope pointing dec [degrees]'), ) fiberfile = desispec.io.findfile('fibermap', night, expid) desispec.io.write_fibermap(fiberfile, fibermap, header=hdr) print fiberfile #- Write simfile hdr = dict( AIRMASS=(airmass, 'Airmass at middle of exposure'), EXPTIME=(exptime, 'Exposure time [sec]'), FLAVOR=(flavor, 'exposure flavor [arc, flat, science]'), ) simfile = io.write_simspec(meta, truth, expid, night, header=hdr) print simfile #- Update obslog that we succeeded with this exposure update_obslog(flavor, expid, dateobs, tileid) return fibermap, truth
def new_exposure(program, nspec=5000, night=None, expid=None, tileid=None, nproc=None, seed=None, obsconditions=None, specify_targets=dict(), testslit=False, exptime=None, arc_lines_filename=None, flat_spectrum_filename=None, outdir=None, overwrite=False): """ Create a new exposure and output input simulation files. Does not generate pixel-level simulations or noisy spectra. Args: program (str): 'arc', 'flat', 'bright', 'dark', 'bgs', 'mws', ... nspec (int, optional): number of spectra to simulate night (str, optional): YEARMMDD string expid (int, optional): positive integer exposure ID tileid (int, optional): integer tile ID nproc (object, optional): What does this do? seed (int, optional): random seed obsconditions (str or dict-like, optional): see options below specify_targets (dict of dicts, optional): 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() testslit (bool, optional): simulate test slit if True, default False; only for arc/flat exptime (float, optional): exposure time [seconds], overrides obsconditions['EXPTIME'] arc_lines_filename (str, optional): use alternate arc lines filename (used if program="arc") flat_spectrum_filename (str, optional): use alternate flat spectrum filename (used if program="flat") outdir (str, optional): output directory overwrite (bool, optional): optionally clobber existing files Returns: science: sim, fibermap, meta, obsconditions, objmeta Writes to outdir or $DESI_SPECTRO_SIM/$PIXPROD/{night}/ * fibermap-{expid}.fits * simspec-{expid}.fits input obsconditions can be a string 'dark', 'gray', 'bright', or dict-like observation metadata with keys SEEING (arcsec), EXPTIME (sec), AIRMASS, MOONFRAC (0-1), MOONALT (deg), MOONSEP (deg). Output obsconditions is is expanded dict-like structure. program is used to pick the sky brightness, and is propagated to desisim.targets.sample_objtype() to get the correct distribution of targets for a given program, e.g. ELGs, LRGs, QSOs for program='dark'. if program is 'arc' or 'flat', then `sim` is truth table with keys FLUX and WAVE; and meta=None and obsconditions=None. Also see simexp.simarc(), .simflat(), and .simscience(), the last of which simulates a science exposure given surveysim obsconditions input, fiber assignments, and pre-generated mock target spectra. """ if expid is None: expid = get_next_expid() if tileid is None: tileid = get_next_tileid() if night is None: #- simulation obs time = now, even if sun is up dateobs = time.gmtime() night = get_night(utc=dateobs) else: #- 10pm on night YEARMMDD night = str(night) #- just in case we got an integer instead of string dateobs = time.strptime(night+':22', '%Y%m%d:%H') outsimspec = desisim.io.findfile('simspec', night, expid) outfibermap = desisim.io.findfile('simfibermap', night, expid) if outdir is not None: outsimspec = os.path.join(outdir, os.path.basename(outsimspec)) outfibermap = os.path.join(outdir, os.path.basename(outfibermap)) program = program.lower() log.debug('Generating {} targets'.format(nspec)) header = dict(NIGHT=night, EXPID=expid, PROGRAM=program) if program in ('arc', 'flat'): header['FLAVOR'] = program else: header['FLAVOR'] = 'science' #- ISO 8601 DATE-OBS year-mm-ddThh:mm:ss header['DATE-OBS'] = time.strftime('%FT%T', dateobs) if program == 'arc': if arc_lines_filename is None : infile = os.getenv('DESI_ROOT')+'/spectro/templates/calib/v0.4/arc-lines-average-in-vacuum-from-winlight-20170118.fits' else : infile = arc_lines_filename arcdata = fits.getdata(infile, 1) if exptime is None: exptime = 5 wave, phot, fibermap = desisim.simexp.simarc(arcdata, nspec=nspec, testslit=testslit) header['EXPTIME'] = exptime desisim.io.write_simspec_arc(outsimspec, wave, phot, header, fibermap=fibermap, overwrite=overwrite) fibermap.meta['NIGHT'] = night fibermap.meta['EXPID'] = expid desispec.io.write_fibermap(outfibermap, fibermap) truth = dict(WAVE=wave, PHOT=phot, UNITS='photon') return truth, fibermap, None, None, None elif program == 'flat': if flat_spectrum_filename is None : infile = os.getenv('DESI_ROOT')+'/spectro/templates/calib/v0.4/flat-3100K-quartz-iodine.fits' else : infile = flat_spectrum_filename if exptime is None: exptime = 10 sim, fibermap = desisim.simexp.simflat(infile, nspec=nspec, exptime=exptime, testslit=testslit, psfconvolve=False) header['EXPTIME'] = exptime header['FLAVOR'] = 'flat' desisim.io.write_simspec(sim, truth=None, fibermap=fibermap, obs=None, expid=expid, night=night, header=header, filename=outsimspec, overwrite=overwrite) fibermap.meta['NIGHT'] = night fibermap.meta['EXPID'] = expid desispec.io.write_fibermap(outfibermap, fibermap) # fluxunits = 1e-17 * u.erg / (u.s * u.cm**2 * u.Angstrom) fluxunits = '1e-17 erg/(s * cm2 * Angstrom)' flux = sim.simulated['source_flux'].to(fluxunits) wave = sim.simulated['wavelength'].to('Angstrom') truth = dict(WAVE=wave, FLUX=flux, UNITS=str(fluxunits)) return truth, fibermap, None, None, None #- all other programs fibermap, (flux, wave, meta, objmeta) = get_targets_parallel(nspec, program, tileid=tileid, nproc=nproc, seed=seed, specify_targets=specify_targets) if obsconditions is None: if program in ['dark', 'lrg', 'qso']: obsconditions = desisim.simexp.reference_conditions['DARK'] elif program in ['elg', 'gray', 'grey']: obsconditions = desisim.simexp.reference_conditions['GRAY'] elif program in ['mws', 'bgs', 'bright']: obsconditions = desisim.simexp.reference_conditions['BRIGHT'] else: raise ValueError('unknown program {}'.format(program)) elif isinstance(obsconditions, str): try: obsconditions = desisim.simexp.reference_conditions[obsconditions.upper()] except KeyError: raise ValueError('obsconditions {} not in {}'.format( obsconditions.upper(), list(desisim.simexp.reference_conditions.keys()))) if exptime is not None: obsconditions['EXPTIME'] = exptime sim = simulate_spectra(wave, flux, fibermap=fibermap, obsconditions=obsconditions, psfconvolve=False) #- Write fibermap telera, teledec = io.get_tile_radec(tileid) hdr = dict( NIGHT = (night, 'Night of observation YEARMMDD'), EXPID = (expid, 'DESI exposure ID'), TILEID = (tileid, 'DESI tile ID'), PROGRAM = (program, 'program [dark, bright, ...]'), FLAVOR = ('science', 'Flavor [arc, flat, science, zero, ...]'), TELRA = (telera, 'Telescope pointing RA [degrees]'), TELDEC = (teledec, 'Telescope pointing dec [degrees]'), AIRMASS = (obsconditions['AIRMASS'], 'Airmass at middle of exposure'), EXPTIME = (obsconditions['EXPTIME'], 'Exposure time [sec]'), SEEING = (obsconditions['SEEING'], 'Seeing FWHM [arcsec]'), MOONFRAC = (obsconditions['MOONFRAC'], 'Moon illumination fraction 0-1; 1=full'), MOONALT = (obsconditions['MOONALT'], 'Moon altitude [degrees]'), MOONSEP = (obsconditions['MOONSEP'], 'Moon:tile separation angle [degrees]'), ) hdr['DATE-OBS'] = (time.strftime('%FT%T', dateobs), 'Start of exposure') simfile = io.write_simspec(sim, meta, fibermap, obsconditions, expid, night, objmeta=objmeta, header=hdr, filename=outsimspec, overwrite=overwrite) if not isinstance(fibermap, table.Table): fibermap = table.Table(fibermap) fibermap.meta.update(hdr) desispec.io.write_fibermap(outfibermap, fibermap) log.info('Wrote '+outfibermap) update_obslog(obstype='science', program=program, expid=expid, dateobs=dateobs, tileid=tileid) return sim, fibermap, meta, obsconditions, objmeta