Exemple #1
0
def update_obslog(obstype='science', program='DARK', expid=None, dateobs=None,
    tileid=-1, ra=None, dec=None):
    """
    Update obslog with a new exposure

    obstype : 'arc', 'flat', 'bias', 'test', 'science', ...
    program : 'DARK', 'GRAY', 'BRIGHT', 'CALIB'
    expid   : integer exposure ID, default from get_next_expid()
    dateobs : time.struct_time tuple; default time.localtime()
    tileid  : integer TileID, default -1, i.e. not a DESI tile
    ra, dec : float (ra, dec) coordinates, default tile ra,dec or (0,0)

    returns tuple (expid, dateobs)

    TODO: normalize obstype vs. program; see desisim issue #97
    """
    #- Connect to sqlite database file and create DB if needed
    dbdir = io.simdir() + '/etc'
    if not os.path.exists(dbdir):
        os.makedirs(dbdir)

    dbfile = dbdir+'/obslog.sqlite'
    with sqlite3.connect(dbfile, isolation_level="EXCLUSIVE") as db:
        db.execute("""\
        CREATE TABLE IF NOT EXISTS obslog (
            expid INTEGER PRIMARY KEY,
            dateobs DATETIME,                   -- seconds since Unix Epoch (1970)
            night TEXT,                         -- YEARMMDD
            obstype TEXT DEFAULT "science",
            program TEXT DEFAULT "DARK",
            tileid INTEGER DEFAULT -1,
            ra REAL DEFAULT 0.0,
            dec REAL DEFAULT 0.0
        )
        """)

        #- Fill in defaults
        if expid is None:
            expid = get_next_expid()

        if dateobs is None:
            dateobs = time.localtime()

        if ra is None:
            assert (dec is None)
            if tileid < 0:
                ra, dec = (0.0, 0.0)
            else:
                ra, dec = io.get_tile_radec(tileid)

        night = get_night(utc=dateobs)

        insert = """\
        INSERT OR REPLACE INTO obslog(expid,dateobs,night,obstype,program,tileid,ra,dec)
        VALUES (?,?,?,?,?,?,?,?)
        """
        db.execute(insert, (int(expid), time.mktime(dateobs), str(night), str(obstype.upper()), str(program.upper()), int(tileid), float(ra), float(dec)))
        db.commit()

    return expid, dateobs
Exemple #2
0
def update_obslog(obstype='science', program='DARK', expid=None, dateobs=None,
    tileid=-1, ra=None, dec=None):
    """
    Update obslog with a new exposure

    obstype : 'arc', 'flat', 'bias', 'test', 'science', ...
    program : 'DARK', 'GRAY', 'BRIGHT', 'CALIB'
    expid   : integer exposure ID, default from get_next_expid()
    dateobs : time.struct_time tuple; default time.localtime()
    tileid  : integer TileID, default -1, i.e. not a DESI tile
    ra, dec : float (ra, dec) coordinates, default tile ra,dec or (0,0)

    returns tuple (expid, dateobs)

    TODO: normalize obstype vs. program; see desisim issue #97
    """
    #- Connect to sqlite database file and create DB if needed
    dbdir = io.simdir() + '/etc'
    if not os.path.exists(dbdir):
        os.makedirs(dbdir)

    dbfile = dbdir+'/obslog.sqlite'
    with sqlite3.connect(dbfile, isolation_level="EXCLUSIVE") as db:
        db.execute("""\
        CREATE TABLE IF NOT EXISTS obslog (
            expid INTEGER PRIMARY KEY,
            dateobs DATETIME,                   -- seconds since Unix Epoch (1970)
            night TEXT,                         -- YEARMMDD
            obstype TEXT DEFAULT "science",
            program TEXT DEFAULT "DARK",
            tileid INTEGER DEFAULT -1,
            ra REAL DEFAULT 0.0,
            dec REAL DEFAULT 0.0
        )
        """)

        #- Fill in defaults
        if expid is None:
            expid = get_next_expid()

        if dateobs is None:
            dateobs = time.localtime()

        if ra is None:
            assert (dec is None)
            if tileid < 0:
                ra, dec = (0.0, 0.0)
            else:
                ra, dec = io.get_tile_radec(tileid)

        night = get_night(utc=dateobs)

        insert = """\
        INSERT OR REPLACE INTO obslog(expid,dateobs,night,obstype,program,tileid,ra,dec)
        VALUES (?,?,?,?,?,?,?,?)
        """
        db.execute(insert, (int(expid), time.mktime(dateobs), str(night), str(obstype.upper()), str(program.upper()), int(tileid), float(ra), float(dec)))
        db.commit()

    return expid, dateobs
Exemple #3
0
def update_obslog(obstype='science', expid=None, dateobs=None,
    tileid=-1, ra=None, dec=None):
    """
    Update obslog with a new exposure
    
    obstype : 'science', 'arc', 'flat', 'bias', 'dark', or 'test'
    expid   : integer exposure ID, default from get_next_expid()
    dateobs : time.struct_time tuple; default time.localtime()
    tileid  : integer TileID, default -1, i.e. not a DESI tile
    ra, dec : float (ra, dec) coordinates, default tile ra,dec or (0,0)
    
    returns tuple (expid, dateobs)
    """
    #- Connect to sqlite database file and create DB if needed
    dbdir = io.simdir() + '/etc'
    if not os.path.exists(dbdir):
        os.makedirs(dbdir)
        
    dbfile = dbdir+'/obslog.sqlite'
    db = sqlite3.connect(dbfile)
    db.execute("""\
    CREATE TABLE IF NOT EXISTS obslog (
        expid INTEGER PRIMARY KEY,
        dateobs DATETIME,                   -- seconds since Unix Epoch (1970)
        night TEXT,                         -- YEARMMDD
        obstype TEXT DEFAULT "science",
        tileid INTEGER DEFAULT -1,
        ra REAL DEFAULT 0.0,
        dec REAL DEFAULT 0.0
    )
    """)
    
    #- Fill in defaults
    if expid is None:
        expid = get_next_expid()
    
    if dateobs is None:
        dateobs = time.localtime()

    if ra is None:
        assert (dec is None)
        if tileid < 0:
            ra, dec = (0.0, 0.0)
        else:
            ra, dec = io.get_tile_radec(tileid)
            
    night = get_night(utc=dateobs)
        
    insert = """\
    INSERT OR REPLACE INTO obslog(expid,dateobs,night,obstype,tileid,ra,dec)
    VALUES (?,?,?,?,?,?,?)
    """
    db.execute(insert, (expid, time.mktime(dateobs), night, obstype, tileid, ra, dec))
    db.commit()
    
    return expid, dateobs
Exemple #4
0
def update_obslog(obstype='science',
                  expid=None,
                  dateobs=None,
                  tileid=-1,
                  ra=None,
                  dec=None):
    """
    Update obslog with a new exposure
    
    obstype : 'science', 'arc', 'flat', 'bias', 'dark', or 'test'
    expid   : integer exposure ID, default from get_next_expid()
    dateobs : time.struct_time tuple; default time.localtime()
    tileid  : integer TileID, default -1, i.e. not a DESI tile
    ra, dec : float (ra, dec) coordinates, default tile ra,dec or (0,0)
    
    returns tuple (expid, dateobs)
    """
    #- Connect to sqlite database file and create DB if needed
    dbdir = io.simdir() + '/etc'
    if not os.path.exists(dbdir):
        os.makedirs(dbdir)

    dbfile = dbdir + '/obslog.sqlite'
    db = sqlite3.connect(dbfile)
    db.execute("""\
    CREATE TABLE IF NOT EXISTS obslog (
        expid INTEGER PRIMARY KEY,
        dateobs DATETIME,                   -- seconds since Unix Epoch (1970)
        night TEXT,                         -- YEARMMDD
        obstype TEXT DEFAULT "science",
        tileid INTEGER DEFAULT -1,
        ra REAL DEFAULT 0.0,
        dec REAL DEFAULT 0.0
    )
    """)

    #- Fill in defaults
    if expid is None:
        expid = get_next_expid()

    if dateobs is None:
        dateobs = time.localtime()

    if ra is None:
        assert (dec is None)
        if tileid < 0:
            ra, dec = (0.0, 0.0)
        else:
            ra, dec = io.get_tile_radec(tileid)

    night = get_night(utc=dateobs)

    insert = """\
    INSERT OR REPLACE INTO obslog(expid,dateobs,night,obstype,tileid,ra,dec)
    VALUES (?,?,?,?,?,?,?)
    """
    db.execute(insert,
               (expid, time.mktime(dateobs), night, obstype, tileid, ra, dec))
    db.commit()

    return expid, dateobs
Exemple #5
0
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
Exemple #6
0
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
Exemple #7
0
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
Exemple #8
0
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)
Exemple #9
0
def get_targets(nspec, tileid=None):
    """
    Returns:
        fibermap
        truth table
        
    TODO: document this better
    """
    if tileid is None:
        tile_ra, tile_dec = 0.0, 0.0
    else:
        tile_ra, tile_dec = io.get_tile_radec(tileid)
    
    #- Get distribution of target types
    true_objtype, target_objtype = sample_objtype(nspec)
    
    #- 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)
    
    truth = dict()
    truth['FLUX'] = np.zeros( (nspec, len(wave)) )
    truth['REDSHIFT'] = np.zeros(nspec, dtype='f4')
    truth['TEMPLATEID'] = np.zeros(nspec, dtype='i4')
    truth['O2FLUX'] = np.zeros(nspec, dtype='f4')
    truth['OBJTYPE'] = np.zeros(nspec, dtype='S10')
    #- Note: unlike other elements, first index of WAVE isn't spectrum index
    truth['WAVE'] = wave
    
    fibermap = empty_fibermap(nspec)
    
    for objtype in set(true_objtype):
        ii = np.where(true_objtype == objtype)[0]
        fibermap['OBJTYPE'][ii] = target_objtype[ii]
        truth['OBJTYPE'][ii] = true_objtype[ii]

        if objtype == 'SKY':
            continue
                    
        try:
            simflux, meta = io.read_templates(wave, objtype, len(ii))
        except ValueError, err:
            print err
            continue
            
        truth['FLUX'][ii] = simflux
        
        #- STD don't have redshift Z; others do
        #- In principle we should also have redshifts (radial velocities)
        #- for standards as well.
        if 'Z' in meta.dtype.names:
            truth['REDSHIFT'][ii] = meta['Z']
        elif objtype != 'STD':
            print "No redshifts for", objtype, len(ii)

        #- Only ELGs have [OII] flux
        if objtype == 'ELG':
            truth['O2FLUX'][ii] = meta['OII_3727']
        
        #- Everyone had a templateid
        truth['TEMPLATEID'][ii] = meta['TEMPLATEID']
        
        #- Extract magnitudes from colors
        #- TODO: make this more consistent at the input level
        
        #- Standard Stars have SDSS magnitudes
        if objtype == 'STD':
            magr = meta['SDSS_R']
            magi = magr - meta['SDSS_RI']
            magz = magi - meta['SDSS_IZ']
            magg = magr - meta['SDSS_GR']  #- R-G, not G-R ?
            magu = magg - meta['SDSS_UG']

            mags = np.vstack( [magu, magg, magr, magi, magz] ).T
            filters = ['SDSS_U', 'SDSS_G', 'SDSS_R', 'SDSS_I', 'SDSS_Z']

            fibermap['MAG'][ii] = mags
            fibermap['FILTER'][ii] = filters
        #- LRGs
        elif objtype == 'LRG':
            magz = meta['DECAM_Z']
            magr = magz - meta['DECAM_RZ']
            magw = magr - meta['DECAM_RW1']
            
            fibermap['MAG'][ii, 0:3] = np.vstack( [magr, magz, magw] ).T
            fibermap['FILTER'][ii, 0:3] = ['DECAM_R', 'DECAM_Z', 'WISE_W1']
            
        #- ELGs
        elif objtype == 'ELG':
            magr = meta['DECAM_R']
            magg = magr - meta['DECAM_GR']
            magz = magr - meta['DECAM_RZ']
            fibermap['MAG'][ii, 0:3] = np.vstack( [magg, magr, magz] ).T
            fibermap['FILTER'][ii, 0:3] = ['DECAM_G', 'DECAM_R', 'DECAM_Z']
        
        elif objtype == 'QSO':
            #- QSO templates don't have magnitudes yet
            pass
Exemple #10
0
def get_targets(nspec, tileid=None):
    """
    Returns:
        fibermap
        truth table

    TODO (@moustakas): Deal with the random seed correctly.

    TODO: document this better
    """
    if tileid is None:
        tile_ra, tile_dec = 0.0, 0.0
    else:
        tile_ra, tile_dec = io.get_tile_radec(tileid)

    #- Get distribution of target types
    true_objtype, target_objtype = sample_objtype(nspec)

    #- 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)

    truth = dict()
    truth['FLUX'] = np.zeros((nspec, len(wave)))
    truth['REDSHIFT'] = np.zeros(nspec, dtype='f4')
    truth['TEMPLATEID'] = np.zeros(nspec, dtype='i4')
    truth['OIIFLUX'] = np.zeros(nspec, dtype='f4')
    truth['D4000'] = np.zeros(nspec, dtype='f4')
    truth['VDISP'] = np.zeros(nspec, dtype='f4')
    truth['OBJTYPE'] = np.zeros(nspec, dtype='S10')
    #- Note: unlike other elements, first index of WAVE isn't spectrum index
    truth['WAVE'] = wave

    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]
        truth['OBJTYPE'][ii] = true_objtype[ii]

        # Simulate spectra
        if objtype == 'SKY':
            continue

        elif objtype == 'ELG':
            from desisim.templates import ELG
            elg = ELG(wave=wave)
            simflux, wave1, meta = elg.make_templates(nmodel=nobj)

        elif objtype == 'LRG':
            from desisim.templates import LRG
            lrg = LRG(wave=wave)
            simflux, wave1, meta = lrg.make_templates(nmodel=nobj)

        elif objtype == 'QSO':
            from desisim.templates import QSO
            qso = QSO(wave=wave)
            simflux, wave1, meta = qso.make_templates(nmodel=nobj)

        # 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.
        elif objtype == 'QSO_BAD':
            from desisim.templates import STAR
            star = STAR(wave=wave)
            simflux, wave1, meta = star.make_templates(nmodel=nobj)

        elif objtype == 'STD':
            from desisim.templates import STAR
            star = STAR(wave=wave, FSTD=True)
            simflux, wave1, meta = star.make_templates(nmodel=nobj)

        truth['FLUX'][ii] = 1e17 * simflux
        truth['UNITS'] = '1e-17 erg/s/cm2/A'
        truth['TEMPLATEID'][ii] = meta['TEMPLATEID']
        truth['REDSHIFT'][ii] = meta['REDSHIFT']

        # Pack in the photometry.  TODO: Include WISE.
        magg = meta['GMAG']
        magr = meta['RMAG']
        magz = meta['ZMAG']
        fibermap['MAG'][ii, 0:3] = np.vstack([magg, magr, magz]).T
        fibermap['FILTER'][ii, 0:3] = ['DECAM_G', 'DECAM_R', 'DECAM_Z']

        if objtype == 'ELG':
            truth['OIIFLUX'][ii] = meta['OIIFLUX']
            truth['D4000'][ii] = meta['D4000']
            truth['VDISP'][ii] = meta['VDISP']

        if objtype == 'LRG':
            truth['D4000'][ii] = meta['D4000']
            truth['VDISP'][ii] = meta['VDISP']

    #- Load fiber -> positioner mapping and tile information
    fiberpos = desimodel.io.load_fiberpos()

    #- Where are these targets?  Centered on positioners for now.
    x = fiberpos['X'][0:nspec]
    y = fiberpos['Y'][0: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'][0:nspec]
    fibermap['SPECTROID'] = fiberpos['SPECTROGRAPH'][0:nspec]
    fibermap['TARGETID'] = np.random.randint(sys.maxint, size=nspec)
    fibermap['TARGETCAT'] = np.zeros(nspec, dtype='|S20')
    fibermap['LAMBDAREF'] = np.ones(nspec, dtype=np.float32) * 5400
    fibermap['TARGET_MASK0'] = np.zeros(nspec, dtype='i8')
    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, truth
Exemple #11
0
def get_targets(nspec, tileid=None):
    """
    Returns:
        fibermap
        truth table

    TODO (@moustakas): Deal with the random seed correctly. 
    
    TODO: document this better
    """
    if tileid is None:
        tile_ra, tile_dec = 0.0, 0.0
    else:
        tile_ra, tile_dec = io.get_tile_radec(tileid)

    # - Get distribution of target types
    true_objtype, target_objtype = sample_objtype(nspec)

    # - 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)

    truth = dict()
    truth["FLUX"] = np.zeros((nspec, len(wave)))
    truth["REDSHIFT"] = np.zeros(nspec, dtype="f4")
    truth["TEMPLATEID"] = np.zeros(nspec, dtype="i4")
    truth["OIIFLUX"] = np.zeros(nspec, dtype="f4")
    truth["D4000"] = np.zeros(nspec, dtype="f4")
    truth["OBJTYPE"] = np.zeros(nspec, dtype="S10")
    # - Note: unlike other elements, first index of WAVE isn't spectrum index
    truth["WAVE"] = wave

    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]
        truth["OBJTYPE"][ii] = true_objtype[ii]

        # Simulate spectra
        if objtype == "SKY":
            continue

        elif objtype == "ELG":
            from desisim.templates import ELG

            elg = ELG(nmodel=nobj, wave=wave)
            simflux, wave1, meta = elg.make_templates()

        elif objtype == "LRG":
            from desisim.templates import LRG

            lrg = LRG(nmodel=nobj, wave=wave)
            simflux, wave1, meta = lrg.make_templates()

        elif objtype == "QSO":
            from desisim.templates import QSO

            qso = QSO(nmodel=nobj, wave=wave)
            simflux, wave1, meta = qso.make_templates()

        # 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.
        elif objtype == "QSO_BAD":
            from desisim.templates import STAR

            star = STAR(nmodel=nobj, wave=wave)
            simflux, wave1, meta = star.make_templates()

        elif objtype == "STD":
            from desisim.templates import STAR

            star = STAR(nmodel=nobj, wave=wave, FSTD=True)
            simflux, wave1, meta = star.make_templates()

        truth["FLUX"][ii] = simflux
        truth["TEMPLATEID"][ii] = meta["TEMPLATEID"]
        truth["REDSHIFT"][ii] = meta["REDSHIFT"]

        # Pack in the photometry.  TODO: Include WISE.
        magg = meta["GMAG"]
        magr = meta["RMAG"]
        magz = meta["ZMAG"]
        fibermap["MAG"][ii, 0:3] = np.vstack([magg, magr, magz]).T
        fibermap["FILTER"][ii, 0:3] = ["DECAM_G", "DECAM_R", "DECAM_Z"]

        if objtype == "ELG":
            truth["OIIFLUX"][ii] = meta["OIIFLUX"]
            truth["D4000"][ii] = meta["D4000"]

        if objtype == "LRG":
            truth["D4000"][ii] = meta["D4000"]

    # - Load fiber -> positioner mapping and tile information
    fiberpos = desimodel.io.load_fiberpos()

    # - Where are these targets?  Centered on positioners for now.
    x = fiberpos["X"][0:nspec]
    y = fiberpos["Y"][0: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"][0:nspec]
    fibermap["SPECTROID"] = fiberpos["SPECTROGRAPH"][0:nspec]
    fibermap["TARGETID"] = np.random.randint(sys.maxint, size=nspec)
    fibermap["TARGETCAT"] = np.zeros(nspec, dtype="|S20")
    fibermap["LAMBDAREF"] = np.ones(nspec, dtype=np.float32) * 5400
    fibermap["TARGET_MASK0"] = np.zeros(nspec, dtype="i8")
    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, truth
Exemple #12
0
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)
Exemple #13
0
def get_targets(nspec, tileid=None):
    """
    Returns:
        fibermap
        truth table
        
    TODO: document this better
    """
    if tileid is None:
        tile_ra, tile_dec = 0.0, 0.0
    else:
        tile_ra, tile_dec = io.get_tile_radec(tileid)

    #- Get distribution of target types
    true_objtype, target_objtype = sample_objtype(nspec)

    #- 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)

    truth = dict()
    truth['FLUX'] = np.zeros((nspec, len(wave)))
    truth['REDSHIFT'] = np.zeros(nspec, dtype='f4')
    truth['TEMPLATEID'] = np.zeros(nspec, dtype='i4')
    truth['O2FLUX'] = np.zeros(nspec, dtype='f4')
    truth['OBJTYPE'] = np.zeros(nspec, dtype='S10')
    #- Note: unlike other elements, first index of WAVE isn't spectrum index
    truth['WAVE'] = wave

    fibermap = empty_fibermap(nspec)

    for objtype in set(true_objtype):
        ii = np.where(true_objtype == objtype)[0]
        fibermap['OBJTYPE'][ii] = target_objtype[ii]
        truth['OBJTYPE'][ii] = true_objtype[ii]

        if objtype == 'SKY':
            continue

        try:
            simflux, meta = io.read_templates(wave, objtype, len(ii))
        except ValueError, err:
            print err
            continue

        truth['FLUX'][ii] = simflux

        #- STD don't have redshift Z; others do
        #- In principle we should also have redshifts (radial velocities)
        #- for standards as well.
        if 'Z' in meta.dtype.names:
            truth['REDSHIFT'][ii] = meta['Z']
        elif objtype != 'STD':
            print "No redshifts for", objtype, len(ii)

        #- Only ELGs have [OII] flux
        if objtype == 'ELG':
            truth['O2FLUX'][ii] = meta['OII_3727']

        #- Everyone had a templateid
        truth['TEMPLATEID'][ii] = meta['TEMPLATEID']

        #- Extract magnitudes from colors
        #- TODO: make this more consistent at the input level

        #- Standard Stars have SDSS magnitudes
        if objtype == 'STD':
            magr = meta['SDSS_R']
            magi = magr - meta['SDSS_RI']
            magz = magi - meta['SDSS_IZ']
            magg = magr - meta['SDSS_GR']  #- R-G, not G-R ?
            magu = magg - meta['SDSS_UG']

            mags = np.vstack([magu, magg, magr, magi, magz]).T
            filters = ['SDSS_U', 'SDSS_G', 'SDSS_R', 'SDSS_I', 'SDSS_Z']

            fibermap['MAG'][ii] = mags
            fibermap['FILTER'][ii] = filters
        #- LRGs
        elif objtype == 'LRG':
            magz = meta['DECAM_Z']
            magr = magz - meta['DECAM_RZ']
            magw = magr - meta['DECAM_RW1']

            fibermap['MAG'][ii, 0:3] = np.vstack([magr, magz, magw]).T
            fibermap['FILTER'][ii, 0:3] = ['DECAM_R', 'DECAM_Z', 'WISE_W1']

        #- ELGs
        elif objtype == 'ELG':
            magr = meta['DECAM_R']
            magg = magr - meta['DECAM_GR']
            magz = magr - meta['DECAM_RZ']
            fibermap['MAG'][ii, 0:3] = np.vstack([magg, magr, magz]).T
            fibermap['FILTER'][ii, 0:3] = ['DECAM_G', 'DECAM_R', 'DECAM_Z']

        elif objtype == 'QSO':
            #- QSO templates don't have magnitudes yet
            pass
Exemple #14
0
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)
Exemple #15
0
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