Ejemplo n.º 1
0
def write_templates(outfile,
                    flux,
                    wave,
                    meta,
                    objtype=None,
                    comments=None,
                    units=None):
    """Write out simulated galaxy templates.  (Incomplete documentation...)

    Args:
        outfile (str): Output file name.
    """
    from astropy.io import fits
    from desispec.io.util import fitsheader, write_bintable, makepath

    # Create the path to OUTFILE if necessary.
    outfile = makepath(outfile)

    header = dict(OBJTYPE=(objtype, 'Object type'),
                  CUNIT=('Angstrom', 'units of wavelength array'),
                  CRPIX1=(1, 'reference pixel number'),
                  CRVAL1=(wave[0], 'Starting wavelength [Angstrom]'),
                  CDELT1=(wave[1] - wave[0], 'Wavelength step [Angstrom]'),
                  LOGLAM=(0, 'linear wavelength steps, not log10'),
                  AIRORVAC=('vac', 'wavelengths in vacuum (vac) or air'),
                  BUNIT=('1e-17 erg/(s cm2 Angstrom)', 'spectrum flux units'))
    hdr = fitsheader(header)

    fits.writeto(outfile, flux.astype(np.float32), header=hdr, clobber=True)
    write_bintable(outfile,
                   meta,
                   header=hdr,
                   comments=comments,
                   units=units,
                   extname='METADATA')
Ejemplo n.º 2
0
def main(args):

    log = get_logger()

    for filename in args.infile:

        log.info("reading %s" % filename)
        frame = io.read_frame(filename)

        flux_per_angstrom = None
        if args.flux_per_angstrom:
            flux_per_angstrom = True
        elif args.flux_per_pixel:
            flux_per_angstrom = False
        else:
            flux_per_angstrom = None

        scores, comments = compute_and_append_frame_scores(
            frame,
            suffix=args.suffix,
            flux_per_angstrom=flux_per_angstrom,
            overwrite=args.overwrite)
        log.info("Adding or replacing SCORES extention with {} in {}".format(
            scores.keys(), filename))
        write_bintable(filename,
                       data=scores,
                       comments=comments,
                       extname="SCORES",
                       clobber=True)
Ejemplo n.º 3
0
def write_fibermap(outfile, fibermap, header=None):
    """Write fibermap binary table to outfile.

    Args:
        outfile (str): output filename
        fibermap: astropy Table of fibermap data
        header: header data to include in same HDU as fibermap

    Returns:
        write_fibermap (str): full path to filename of fibermap file written.
    """
    outfile = makepath(outfile)

    #- astropy.io.fits incorrectly generates warning about 2D arrays of strings
    #- Temporarily turn off warnings to avoid this; desispec.test.test_io will
    #- catch it if the arrays actually are written incorrectly.
    if header is not None:
        hdr = fitsheader(header)
    else:
        hdr = fitsheader(fibermap.meta)

    add_dependencies(hdr)

    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        write_bintable(outfile,
                       fibermap,
                       hdr,
                       comments=fibermap_comments,
                       extname="FIBERMAP",
                       clobber=True)

    return outfile
Ejemplo n.º 4
0
def write_fibermap(outfile, fibermap, header=None, clobber=True, extname='FIBERMAP'):
    """Write fibermap binary table to outfile.

    Args:
        outfile (str): output filename
        fibermap: astropy Table of fibermap data
        header: header data to include in same HDU as fibermap
        clobber (bool, optional): overwrite outfile if it exists
        extname (str, optional): set the extension name.

    Returns:
        write_fibermap (str): full path to filename of fibermap file written.
    """
    outfile = makepath(outfile)

    #- astropy.io.fits incorrectly generates warning about 2D arrays of strings
    #- Temporarily turn off warnings to avoid this; desispec.test.test_io will
    #- catch it if the arrays actually are written incorrectly.
    if header is not None:
        hdr = fitsheader(header)
    else:
        hdr = fitsheader(fibermap.meta)

    add_dependencies(hdr)

    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        write_bintable(outfile, fibermap, hdr, comments=fibermap_comments,
                       extname=extname, clobber=clobber)

    return outfile
Ejemplo n.º 5
0
def write_fibermap(outfile, fibermap, header=None):
    """Write fibermap binary table to outfile.

    Args:
        outfile (str): output filename
        fibermap: ndarray with named columns of fibermap data
        header: header data to include in same HDU as fibermap

    Returns:
        write_fibermap (str): full path to filename of fibermap file written.
    """
    outfile = makepath(outfile)

    #- astropy.io.fits incorrectly generates warning about 2D arrays of strings
    #- Temporarily turn off warnings to avoid this; desispec.test.test_io will
    #- catch it if the arrays actually are written incorrectly.
    hdr = fitsheader(header)
    add_dependencies(hdr)
    
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        write_bintable(outfile, fibermap, hdr, comments=fibermap_comments,
            extname="FIBERMAP", clobber=True)

    return outfile
Ejemplo n.º 6
0
def write_templates(outfile, flux, wave, meta, objtype=None,
                    comments=None, units=None):
    """Write out simulated galaxy templates.  (Incomplete documentation...)

        Args:
          outfile (str): Output file name.
    
        Returns:
    
        Raises

    """
    from astropy.io import fits
    from desispec.io.util import fitsheader, write_bintable, makepath

    # Create the path to OUTFILE if necessary.
    outfile = makepath(outfile)
    
    header = dict(
        OBJTYPE = (objtype, 'Object type'),
        CUNIT = ('Angstrom', 'units of wavelength array'),
        CRPIX1 = (1, 'reference pixel number'),
        CRVAL1 = (wave[0], 'Starting wavelength [Angstrom]'),
        CDELT1 = (wave[1]-wave[0], 'Wavelength step [Angstrom]'),
        LOGLAM = (0, 'linear wavelength steps, not log10'),
        AIRORVAC = ('vac', 'wavelengths in vacuum (vac) or air'),
        BUNIT = ('erg/s/cm2/A', 'spectrum flux units')
        )
    hdr = fitsheader(header)

    fits.writeto(outfile,flux.astype(np.float32),header=hdr,clobber=True)
    write_bintable(outfile, meta, header=hdr, comments=comments,
                   units=units, extname='METADATA')
Ejemplo n.º 7
0
def bgs_write_simdata(sim, obs_conds, simdir, obsrand, overwrite=False):
    """Build and write a metadata table with the simulation inputs.  
    Currently, the only quantities that can be varied are moonfrac, 
    moonsep, and exptime, but more choices can be added as needed.

    """
    from desispec.io.util import makepath
    simdatafile = os.path.join(simdir, sim['suffix'],
                               'bgs-{}-simdata.fits'.format(sim['suffix']))
    makepath(simdatafile)

    cols = [('SEED', 'S20'), ('NSPEC', 'i4'), ('EXPTIME', 'f4'),
            ('AIRMASS', 'f4'), ('SEEING', 'f4'), ('MOONFRAC', 'f4'),
            ('MOONSEP', 'f4'), ('MOONALT', 'f4')]
    simdata = Table(np.zeros(sim['nsim'], dtype=cols))

    simdata['EXPTIME'].unit = 's'
    simdata['SEEING'].unit = 'arcsec'
    simdata['MOONSEP'].unit = 'deg'
    simdata['MOONALT'].unit = 'deg'

    simdata['SEED'] = sim['seed']
    simdata['NSPEC'] = sim['nspec']
    simdata['AIRMASS'] = obs_conds['AIRMASS']
    simdata['SEEING'] = obs_conds['SEEING']
    simdata['MOONALT'] = obs_conds['MOONALT']

    if 'moonfracmin' in obs_conds.keys():
        simdata['MOONFRAC'] = obsrand.uniform(obs_conds['moonfracmin'],
                                              obs_conds['moonfracmax'],
                                              sim['nsim'])
    else:
        simdata['MOONFRAC'] = obs_conds['MOONFRAC']

    if 'moonsepmin' in obs_conds.keys():
        simdata['MOONSEP'] = obsrand.uniform(obs_conds['moonsepmin'],
                                             obs_conds['moonsepmax'],
                                             sim['nsim'])
    else:
        simdata['MOONSEP'] = obs_conds['MOONSEP']

    if 'exptimemin' in obs_conds.keys():
        simdata['EXPTIME'] = obsrand.uniform(obs_conds['exptimemin'],
                                             obs_conds['exptimemax'],
                                             sim['nsim'])
    else:
        simdata['EXPTIME'] = obs_conds['EXPTIME']

    if overwrite or not os.path.isfile(simdatafile):
        print('Writing {}'.format(simdatafile))
        write_bintable(simdatafile,
                       simdata,
                       extname='SIMDATA',
                       clobber=overwrite)

    return simdata
Ejemplo n.º 8
0
def bgs_write_simdata(sim, overwrite=False):
    """Create a metadata table with simulation inputs.

    Parameters
    ----------
    sim : dict
        Simulation parameters from command line.
    overwrite : bool
        Overwrite simulation data file.

    Returns
    -------
    simdata : Table
        Data table written to disk.
    """
    from desispec.io.util import makepath
    from desispec.io.util import write_bintable

    simdatafile = os.path.join(sim.simdir,
                               'bgs_{}_simdata.fits'.format(sim.simid))
    makepath(simdatafile)

    cols = [('SEED', 'S20'), ('NSPEC', 'i4'), ('EXPTIME', 'f4'),
            ('AIRMASS', 'f4'), ('SEEING', 'f4'), ('MOONFRAC', 'f4'),
            ('MOONSEP', 'f4'), ('MOONALT', 'f4')]

    simdata = Table(np.zeros(sim.nsim, dtype=cols))
    simdata['EXPTIME'].unit = 's'
    simdata['SEEING'].unit = 'arcsec'
    simdata['MOONSEP'].unit = 'deg'
    simdata['MOONALT'].unit = 'deg'

    simdata['SEED'] = sim.seed
    simdata['NSPEC'] = sim.nspec
    simdata['AIRMASS'] = sim.airmass
    simdata['SEEING'] = sim.seeing
    simdata['MOONALT'] = sim.moonalt
    simdata['MOONSEP'] = sim.moonsep
    simdata['MOONFRAC'] = sim.moonfrac
    simdata['EXPTIME'] = sim.exptime

    if overwrite or not os.path.isfile(simdatafile):
        print('Writing {}'.format(simdatafile))
        write_bintable(simdatafile, simdata, extname='SIMDATA', clobber=True)

    return simdata
Ejemplo n.º 9
0
def write_fibermap(outfile,
                   fibermap,
                   header=None,
                   clobber=True,
                   extname='FIBERMAP'):
    """Write fibermap binary table to outfile.

    Args:
        outfile (str): output filename
        fibermap: astropy Table of fibermap data
        header: header data to include in same HDU as fibermap
        clobber (bool, optional): overwrite outfile if it exists
        extname (str, optional): set the extension name.

    Returns:
        write_fibermap (str): full path to filename of fibermap file written.
    """
    log = get_logger()
    outfile = makepath(outfile)

    #- astropy.io.fits incorrectly generates warning about 2D arrays of strings
    #- Temporarily turn off warnings to avoid this; desispec.test.test_io will
    #- catch it if the arrays actually are written incorrectly.
    if header is not None:
        hdr = fitsheader(header)
    else:
        hdr = fitsheader(fibermap.meta)

    add_dependencies(hdr)

    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        t0 = time.time()
        write_bintable(outfile,
                       fibermap,
                       hdr,
                       comments=fibermap_comments,
                       extname=extname,
                       clobber=clobber)
        duration = time.time() - t0

    log.info(iotime.format('write', outfile, duration))

    return outfile
Ejemplo n.º 10
0
def main(args) :

    log = get_logger()

    for filename in args.infile :
        
        log.info("reading %s"%filename)
        frame=io.read_frame(filename)

        flux_per_angstrom=None
        if args.flux_per_angstrom :
            flux_per_angstrom=True
        elif args.flux_per_pixel :
            flux_per_angstrom=False
        else :
            flux_per_angstrom=None
        
        scores,comments=compute_and_append_frame_scores(frame,suffix=args.suffix,flux_per_angstrom=flux_per_angstrom,overwrite=args.overwrite)
        log.info("Adding or replacing SCORES extention with {} in {}".format(scores.keys(),filename))
        write_bintable(filename,data=scores,comments=comments,extname="SCORES",clobber=True)        
Ejemplo n.º 11
0
def write_simspec(meta, truth, expid, night, header=None, outfile=None):
    """
    Write $DESI_SPECTRO_SIM/$PIXPROD/{night}/simspec-{expid}.fits

    Args:
        meta : metadata table to write to "METADATA" HDU
        truth : dictionary with keys:
            FLUX - 2D array [nspec, nwave] in erg/s/cm2/A
            WAVE - 1D array of vacuum wavelengths [Angstroms]
            SKYFLUX - array of sky flux [erg/s/cm2/A/arcsec],
                      either 1D [nwave] or 2D [nspec, nwave]
            PHOT_{B,R,Z} - 2D array [nspec, nwave] of object photons/bin
            SKYPHOT_{B,R,Z} - 1D or 2D array of sky photons/bin
        expid : integer exposure ID
        night : string YEARMMDD
        header : optional dictionary of header items to add to output
        outfile : optional filename to write (otherwise auto-derived)

    Returns:
        full file path of output file written

    """
    #- Where should this go?
    if outfile is None:
        outdir = simdir(night, mkdir=True)
        outfile = '{}/simspec-{:08d}.fits'.format(outdir, expid)

    #- Primary HDU is just a header from the input
    hx = fits.HDUList()
    hx.append(fits.PrimaryHDU(None,
                              header=desispec.io.util.fitsheader(header)))

    #- Object flux HDU (might not exist, e.g. for an arc)
    if 'FLUX' in truth:
        x = fits.ImageHDU(truth['WAVE'], name='WAVE')
        x.header['BUNIT'] = ('Angstrom', 'Wavelength units')
        x.header['AIRORVAC'] = ('vac', 'Vacuum wavelengths')
        hx.append(x)

        x = fits.ImageHDU(truth['FLUX'].astype(np.float32), name='FLUX')
        x.header['BUNIT'] = '1e-17 erg/s/cm2/A'
        hx.append(x)

    #- Sky flux HDU
    if 'SKYFLUX' in truth:
        x = fits.ImageHDU(truth['SKYFLUX'].astype(np.float32), name='SKYFLUX')
        x.header['BUNIT'] = '1e-17 erg/s/cm2/A/arcsec2'
        hx.append(x)

    #- Write object photon and sky photons for each channel
    for channel in ['B', 'R', 'Z']:
        x = fits.ImageHDU(truth['WAVE_' + channel], name='WAVE_' + channel)
        x.header['BUNIT'] = ('Angstrom', 'Wavelength units')
        x.header['AIRORVAC'] = ('vac', 'Vacuum wavelengths')
        hx.append(x)

        extname = 'PHOT_' + channel
        x = fits.ImageHDU(truth[extname].astype(np.float32), name=extname)
        x.header['EXTNAME'] = (extname,
                               channel + ' channel object photons per bin')
        hx.append(x)

        extname = 'SKYPHOT_' + channel
        if extname in truth:
            x = fits.ImageHDU(truth[extname].astype(np.float32), name=extname)
            x.header['EXTNAME'] = (extname,
                                   channel + ' channel sky photons per bin')
            hx.append(x)

    #- Write the file
    hx.writeto(outfile, clobber=True)

    #- Add Metadata table HDU; use write_bintable to get units and comments
    if meta is not None:
        comments = dict(OBJTYPE='Object type (ELG, LRG, QSO, STD, STAR)',
                        REDSHIFT='true object redshift',
                        TEMPLATEID='input template ID',
                        OIIFLUX='[OII] flux [erg/s/cm2]',
                        D4000='4000-A break')

        units = dict(
            # OBJTYPE     = 'Object type (ELG, LRG, QSO, STD, STAR)',
            # REDSHIFT    = 'true object redshift',
            # TEMPLATEID  = 'input template ID',
            OIIFLUX='erg/s/cm2', )

        write_bintable(outfile,
                       meta,
                       header=None,
                       extname="METADATA",
                       comments=comments,
                       units=units)

    return outfile
Ejemplo n.º 12
0
def bgs_gather_results(sim, simdir, overwrite=False):
    """Gather all the pieces so we can make plots.

    """
    from desispec.io.spectra import read_spectra
    import fitsio

    nspec = sim['nspec']
    nall = nspec * sim['nsim']

    resultfile = os.path.join(simdir, sim['suffix'],
                              'bgs-{}-results.fits'.format(sim['suffix']))
    if not os.path.isfile(resultfile) or overwrite:
        pass
    else:
        log.info('File {} exists...skipping.'.format(resultfile))
        return

    cols = [('EXPTIME', 'f4'), ('AIRMASS', 'f4'), ('MOONFRAC', 'f4'),
            ('MOONSEP', 'f4'), ('MOONALT', 'f4'), ('SNR_B', 'f4'),
            ('SNR_R', 'f4'), ('SNR_Z', 'f4'), ('TARGETID', 'i8'),
            ('TEMPLATEID', 'i4'), ('RMAG', 'f4'), ('GR', 'f4'),
            ('D4000', 'f4'), ('EWHBETA', 'f4'), ('ZTRUE', 'f4'), ('Z', 'f4'),
            ('ZERR', 'f4'), ('ZWARN', 'f4')]
    result = Table(np.zeros(nall, dtype=cols))

    result['EXPTIME'].unit = 's'
    result['MOONSEP'].unit = 'deg'
    result['MOONALT'].unit = 'deg'

    # Read the simulation parameters data table.
    simdatafile = os.path.join(simdir, sim['suffix'],
                               'bgs-{}-simdata.fits'.format(sim['suffix']))
    simdata = Table.read(simdatafile)

    for ii, simdata1 in enumerate(simdata):
        # Copy over some data.
        result['EXPTIME'][nspec * ii:nspec * (ii + 1)] = simdata1['EXPTIME']
        result['AIRMASS'][nspec * ii:nspec * (ii + 1)] = simdata1['AIRMASS']
        result['MOONFRAC'][nspec * ii:nspec * (ii + 1)] = simdata1['MOONFRAC']
        result['MOONSEP'][nspec * ii:nspec * (ii + 1)] = simdata1['MOONSEP']
        result['MOONALT'][nspec * ii:nspec * (ii + 1)] = simdata1['MOONALT']

        # Read the metadata table.
        truefile = os.path.join(
            simdir, sim['suffix'],
            'bgs-{}-{:03}-true.fits'.format(sim['suffix'], ii))
        if os.path.isfile(truefile):
            log.info('Reading {}'.format(truefile))
            meta = Table.read(truefile)

            #result['TARGETID'][nspec*ib:nspec*(ii+1)] = truth['TARGETID']
            result['TEMPLATEID'][nspec * ii:nspec *
                                 (ii + 1)] = meta['TEMPLATEID']
            result['RMAG'][nspec * ii:nspec *
                           (ii + 1)] = 22.5 - 2.5 * np.log10(meta['FLUX_R'])
            result['GR'][nspec * ii:nspec * (ii + 1)] = -2.5 * np.log10(
                meta['FLUX_G'] / meta['FLUX_R'])
            result['D4000'][nspec * ii:nspec * (ii + 1)] = meta['D4000']
            result['EWHBETA'][nspec * ii:nspec * (ii + 1)] = meta['EWHBETA']
            result['ZTRUE'][nspec * ii:nspec * (ii + 1)] = meta['REDSHIFT']

        # Read the zbest file.
        zbestfile = os.path.join(
            simdir, sim['suffix'],
            'bgs-{}-{:03}-zbest.fits'.format(sim['suffix'], ii))
        if os.path.isfile(zbestfile):
            log.info('Reading {}'.format(zbestfile))
            #zbest = fitsio.read(zbestfile, 'ZBEST')
            #from astropy.table import Table
            zbest = Table.read(zbestfile, 'ZBEST')
            # Assume the tables are row-ordered!
            result['Z'][nspec * ii:nspec * (ii + 1)] = zbest['Z']
            result['ZERR'][nspec * ii:nspec * (ii + 1)] = zbest['ZERR']
            result['ZWARN'][nspec * ii:nspec * (ii + 1)] = zbest['ZWARN']

        # Finally, read the spectra to get the S/N.
        spectrafile = os.path.join(
            simdir, sim['suffix'],
            'bgs-{}-{:03}.fits'.format(sim['suffix'], ii))
        if os.path.isfile(spectrafile):
            log.info('Reading {}'.format(spectrafile))
            spec = read_spectra(spectrafile)
            for band in ('b', 'r', 'z'):
                for iobj in range(nspec):
                    these = np.where(
                        (spec.wave[band] > np.mean(spec.wave[band]) - 50) *
                        (spec.wave[band] < np.mean(spec.wave[band]) + 50) *
                        (spec.flux[band][iobj, :] > 0))[0]
                    result['SNR_{}'.format(
                        band.upper())][nspec * ii + iobj] = (np.median(
                            spec.flux[band][iobj, these] *
                            np.sqrt(spec.ivar[band][iobj, these])))

    log.info('Writing {}'.format(resultfile))
    write_bintable(resultfile, result, extname='RESULTS', clobber=True)
Ejemplo n.º 13
0
def main(args):

    # Set up the logger.
    if args.verbose:
        log = get_logger(DEBUG)
    else:
        log = get_logger()

    objtype = args.objtype.upper()

    log.debug('Using OBJTYPE {}'.format(objtype))
    log.debug('Simulating {:g} bricks each with {:g} spectra'.format(
        args.nexp, args.nspec))

    # Draw priors uniformly given the input ranges.
    rand = np.random.RandomState(args.seed)
    exptime = rand.uniform(args.exptime_range[0], args.exptime_range[1],
                           args.nexp)
    airmass = rand.uniform(args.airmass_range[0], args.airmass_range[1],
                           args.nexp)
    moonphase = rand.uniform(args.moon_phase_range[0],
                             args.moon_phase_range[1], args.nexp)
    moonangle = rand.uniform(args.moon_angle_range[0],
                             args.moon_angle_range[1], args.nexp)
    moonzenith = rand.uniform(args.moon_zenith_range[0],
                              args.moon_zenith_range[1], args.nexp)
    maglimits = args.rmagrange - bgs
    zrange = args.zrange - bgs
    # Build a metadata table with the simulation inputs.
    metafile = makepath(
        os.path.join(args.outdir, '{}-input.fits'.format(args.brickname)))
    metacols = [('BRICKNAME', 'S20'), ('SEED', 'S20'), ('EXPTIME', 'f4'),
                ('AIRMASS', 'f4'), ('MOONPHASE', 'f4'), ('MOONANGLE', 'f4'),
                ('MOONZENITH', 'f4')]
    meta = Table(np.zeros(args.nexp, dtype=metacols))
    meta['EXPTIME'].unit = 's'
    meta['MOONANGLE'].unit = 'deg'
    meta['MOONZENITH'].unit = 'deg'

    meta['BRICKNAME'] = [
        '{}-{:03d}'.format(args.nexp, ii) for ii in range(args.nexp)
    ]
    meta['EXPTIME'] = exptime
    meta['AIRMASS'] = airmass
    meta['MOONPHASE'] = moonphase
    meta['MOONANGLE'] = moonangle
    meta['MOONZENITH'] = moonzenith

    log.debug('Writing {}'.format(metafile))
    write_bintable(metafile, meta, extname='METADATA', clobber=True)

    # Generate each brick in turn.
    for ii in range(args.nexp):
        thisbrick = meta['BRICKNAME'][ii]
        log.debug('Building brick {}'.format(thisbrick))

        brickargs = [
            '--brickname', thisbrick, '--objtype', args.objtype, '--nspec',
            '{}'.format(args.nspec), '--outdir',
            os.path.join(args.brickdir, thisbrick), '--outdir-truth',
            os.path.join(args.brickdir,
                         thisbrick), '--exptime', '{}'.format(exptime[ii]),
            '--airmass', '{}'.format(airmass[ii]), '--moon-phase', '{}'.format(
                moonphase[ii]), '--moon-angle', '{}'.format(moonangle[ii]),
            '--moon-zenith', '{}'.format(moonzenith[ii]), '--zrange-bgs',
            '{}'.format(args.zrange_bgs[0]), '{}'.format(args.zrange_bgs[1]),
            '--rmagrange-bgs', '{}'.format(args.rmagrange_bgs[0]),
            '{}'.format(args.rmagrange_bgs[1])
        ]
        if args.seed is not None:
            brickargs.append('--seed')
            brickargs.append('{}'.format(args.seed))

        quickargs = quickbrick.parse(brickargs)
        if args.verbose:
            quickargs.verbose = True
        quickbrick.main(quickargs)
Ejemplo n.º 14
0
def write_simspec(meta, truth, expid, night, header=None, outfile=None):
    """
    Write $DESI_SPECTRO_SIM/$PIXPROD/{night}/simspec-{expid}.fits
    
    Args:
        meta : metadata table to write to "METADATA" HDU
        truth : dictionary with keys:
            FLUX - 2D array [nspec, nwave] in erg/s/cm2/A
            WAVE - 1D array of vacuum wavelengths [Angstroms]
            SKYFLUX - array of sky flux [erg/s/cm2/A/arcsec],
                      either 1D [nwave] or 2D [nspec, nwave]
            PHOT_{B,R,Z} - 2D array [nspec, nwave] of object photons/bin
            SKYPHOT_{B,R,Z} - 1D or 2D array of sky photons/bin
        expid : integer exposure ID
        night : string YEARMMDD
        header : optional dictionary of header items to add to output
        outfile : optional filename to write (otherwise auto-derived)
        
    Returns:
        full file path of output file written
        
    """
    #- Where should this go?
    if outfile is None:
        outdir = simdir(night, mkdir=True)      
        outfile = '{}/simspec-{:08d}.fits'.format(outdir, expid)

    #- Primary HDU is just a header from the input
    hx = fits.HDUList()
    hx.append(fits.PrimaryHDU(None, header=desispec.io.util.fitsheader(header)))

    #- Object flux HDU (might not exist, e.g. for an arc)
    if 'FLUX' in truth:
        x = fits.ImageHDU(truth['WAVE'], name='WAVE')
        x.header['BUNIT']  = ('Angstrom', 'Wavelength units')
        x.header['AIRORVAC']  = ('vac', 'Vacuum wavelengths')
        hx.append(x)

        x = fits.ImageHDU(truth['FLUX'].astype(np.float32), name='FLUX')
        x.header['BUNIT'] = '1e-17 erg/s/cm2/A'
        hx.append(x)
    
    #- Sky flux HDU
    if 'SKYFLUX' in truth:
        x = fits.ImageHDU(truth['SKYFLUX'].astype(np.float32), name='SKYFLUX')
        x.header['BUNIT'] = '1e-17 erg/s/cm2/A/arcsec2'
        hx.append(x)
    
    #- Write object photon and sky photons for each channel
    for channel in ['B', 'R', 'Z']:
        x = fits.ImageHDU(truth['WAVE_'+channel], name='WAVE_'+channel)
        x.header['BUNIT']  = ('Angstrom', 'Wavelength units')
        x.header['AIRORVAC']  = ('vac', 'Vacuum wavelengths')
        hx.append(x)

        extname = 'PHOT_'+channel
        x = fits.ImageHDU(truth[extname].astype(np.float32), name=extname)
        x.header['EXTNAME'] = (extname, channel+' channel object photons per bin')
        hx.append(x)

        extname = 'SKYPHOT_'+channel
        if extname in truth:
            x = fits.ImageHDU(truth[extname].astype(np.float32), name=extname)
            x.header['EXTNAME'] = (extname, channel+' channel sky photons per bin')
            hx.append(x)

    #- Write the file
    hx.writeto(outfile, clobber=True)

    #- Add Metadata table HDU; use write_bintable to get units and comments
    if meta is not None:
        comments = dict(
            OBJTYPE     = 'Object type (ELG, LRG, QSO, STD, STAR)',
            REDSHIFT    = 'true object redshift',
            TEMPLATEID  = 'input template ID',
            OIIFLUX     = '[OII] flux [erg/s/cm2]',
            D4000       = '4000-A break'
        )
    
        units = dict(
            # OBJTYPE     = 'Object type (ELG, LRG, QSO, STD, STAR)',
            # REDSHIFT    = 'true object redshift',
            # TEMPLATEID  = 'input template ID',
            OIIFLUX      = 'erg/s/cm2',
        )
    
        write_bintable(outfile, meta, header=None, extname="METADATA",
            comments=comments, units=units)

    return outfile
Ejemplo n.º 15
0
def main(args):

    # Set up the logger.
    if args.verbose:
        log = get_logger(DEBUG)
    else:
        log = get_logger()

    objtype = args.objtype.upper()

    log.debug('Using OBJTYPE {}'.format(objtype))
    log.debug('Simulating {:g} bricks each with {:g} spectra'.format(args.nbrick, args.nspec))

    # Draw priors uniformly given the input ranges.
    rand = np.random.RandomState(args.seed)
    exptime = rand.uniform(args.exptime_range[0], args.exptime_range[1], args.nbrick)
    airmass = rand.uniform(args.airmass_range[0], args.airmass_range[1], args.nbrick)
    moonphase = rand.uniform(args.moon_phase_range[0], args.moon_phase_range[1], args.nbrick)
    moonangle = rand.uniform(args.moon_angle_range[0], args.moon_angle_range[1], args.nbrick)
    moonzenith = rand.uniform(args.moon_zenith_range[0], args.moon_zenith_range[1], args.nbrick)

    # Build a metadata table with the simulation inputs.
    metafile = makepath(os.path.join(args.outdir, '{}-input.fits'.format(args.brickname)))
    metacols = [
        ('BRICKNAME', 'S20'),
        ('SEED', 'S20'),
        ('EXPTIME', 'f4'),
        ('AIRMASS', 'f4'),
        ('MOONPHASE', 'f4'),
        ('MOONANGLE', 'f4'),
        ('MOONZENITH', 'f4')]
    meta = Table(np.zeros(args.nbrick, dtype=metacols))
    meta['EXPTIME'].unit = 's'
    meta['MOONANGLE'].unit = 'deg'
    meta['MOONZENITH'].unit = 'deg'

    meta['BRICKNAME'] = ['{}-{:03d}'.format(args.brickname, ii) for ii in range(args.nbrick)]
    meta['EXPTIME'] = exptime
    meta['AIRMASS'] = airmass
    meta['MOONPHASE'] = moonphase
    meta['MOONANGLE'] = moonangle
    meta['MOONZENITH'] = moonzenith

    log.debug('Writing {}'.format(metafile))
    write_bintable(metafile, meta, extname='METADATA', clobber=True)

    # Generate each brick in turn.
    for ii in range(args.nbrick):
        thisbrick = meta['BRICKNAME'][ii]
        log.debug('Building brick {}'.format(thisbrick))

        brickargs = ['--brickname', thisbrick,
                     '--objtype', args.objtype,
                     '--nspec', '{}'.format(args.nspec),
                     '--outdir', os.path.join(args.brickdir, thisbrick),
                     '--outdir-truth', os.path.join(args.brickdir, thisbrick),
                     '--exptime', '{}'.format(exptime[ii]),
                     '--airmass', '{}'.format(airmass[ii]),
                     '--moon-phase', '{}'.format(moonphase[ii]),
                     '--moon-angle', '{}'.format(moonangle[ii]),
                     '--moon-zenith', '{}'.format(moonzenith[ii]),
                     '--zrange-bgs', '{}'.format(args.zrange_bgs[0]), '{}'.format(args.zrange_bgs[1]),
                     '--rmagrange-bgs', '{}'.format(args.rmagrange_bgs[0]), '{}'.format(args.rmagrange_bgs[1])]
        if args.seed is not None:
            brickargs.append('--seed')
            brickargs.append('{}'.format(args.seed))

        quickargs = quickbrick.parse(brickargs)
        if args.verbose:
            quickargs.verbose = True
        quickbrick.main(quickargs)
Ejemplo n.º 16
0
Archivo: io.py Proyecto: forero/desisim
def write_simspec(meta, truth, expid, night, header=None, outfile=None):
    """
    Write $DESI_SPECTRO_SIM/$PIXPROD/{night}/simspec-{expid}.fits
    
    Args:
        meta : metadata table to write to "METADATA" HDU
        truth : dictionary with keys:
            FLUX - 2D array [nspec, nwave] in erg/s/cm2/A
            WAVE - 1D array of vacuum wavelengths [Angstroms]
            SKYFLUX - array of sky flux [erg/s/cm2/A/arcsec],
                      either 1D [nwave] or 2D [nspec, nwave]
            PHOT_{B,R,Z} - 2D array [nspec, nwave] of object photons/bin
            SKYPHOT_{B,R,Z} - 1D or 2D array of sky photons/bin
        expid : integer exposure ID
        night : string YEARMMDD
        header : optional dictionary of header items to add to output
        outfile : optional filename to write (otherwise auto-derived)
        
    Returns:
        full file path of output file written
        
    """
    #- Where should this go?
    if outfile is None:
        outdir = simdir(night, mkdir=True)      
        outfile = '{}/simspec-{:08d}.fits'.format(outdir, expid)

    #- Object flux HDU (which might be just a header, e.g. for an arc)
    hdr = desispec.io.util.fitsheader(header)
            
    wave = truth['WAVE']
    hdr['CRVAL1']    = (wave[0], 'Starting wavelength [Angstroms]')
    hdr['CDELT1']    = (wave[1]-wave[0], 'Wavelength step [Angstroms]')
    hdr['AIRORVAC']  = ('vac', 'Vacuum wavelengths')
    hdr['LOGLAM']    = (0, 'linear wavelength steps, not log10')
    if 'FLUX' in truth:
        hdr['EXTNAME']   = ('FLUX', 'Object flux [erg/s/cm2/A]')
        fits.writeto(outfile, truth['FLUX'].astype(np.float32), header=hdr, clobber=True)
    else:
        fits.writeto(outfile, np.zeros(0), header=hdr, clobber=True)
    
    #- Sky flux HDU
    if 'SKYFLUX' in truth:
        hdr['EXTNAME'] = ('SKYFLUX', 'Sky flux [erg/s/cm2/A/arcsec2]')
        hdu = fits.ImageHDU(truth['SKYFLUX'].astype(np.float32), header=hdr)
        fits.append(outfile, hdu.data, header=hdu.header)
    
    #- Metadata table HDU
    if meta is not None:
        comments = dict(
            OBJTYPE     = 'Object type (ELG, LRG, QSO, STD, STAR)',
            REDSHIFT    = 'true object redshift',
            TEMPLATEID  = 'input template ID',
            O2FLUX      = '[OII] flux [erg/s/cm2]',
        )
    
        units = dict(
            # OBJTYPE     = 'Object type (ELG, LRG, QSO, STD, STAR)',
            # REDSHIFT    = 'true object redshift',
            # TEMPLATEID  = 'input template ID',
            O2FLUX      = 'erg/s/cm2',
        )
    
        write_bintable(outfile, meta, header=None, extname="METADATA",
            comments=comments, units=units)

    #- Write object photon and sky photons for each channel
    for channel in ['B', 'R', 'Z']:
        hdr = fits.Header()
        wave = truth['WAVE_'+channel]
        hdr['CRVAL1']    = (wave[0], 'Starting wavelength [Angstroms]')
        hdr['CDELT1']    = (wave[1]-wave[0], 'Wavelength step [Angstroms]')
        hdr['AIRORVAC']  = ('vac', 'Vacuum wavelengths')
        hdr['LOGLAM']    = (0, 'linear wavelength steps, not log10')
        
        extname = 'PHOT_'+channel
        hdr['EXTNAME']   = (extname, channel+' channel object photons per bin')
        hdu = fits.ImageHDU(truth[extname].astype(np.float32), header=hdr)
        fits.append(outfile, hdu.data, header=hdu.header)

        extname = 'SKYPHOT_'+channel
        if extname in truth:
            hdr['EXTNAME']   = (extname, channel+' channel sky photons per bin')
            hdu = fits.ImageHDU(truth[extname].astype(np.float32), header=hdr)
            fits.append(outfile, hdu.data, header=hdu.header)
                            
    return outfile
Ejemplo n.º 17
0
    return vstack(dat), filemap


if __name__ == '__main__':
    import argparse

    _nproc = multiprocessing.cpu_count() // 2
    parser = argparse.ArgumentParser(usage="%(prog)s [options]")
    parser.add_argument("-i", "--indir", type=str, help="input data")
    parser.add_argument("-o", "--output", type=str, help="output file")
    parser.add_argument("--nproc",
                        type=int,
                        help="output file",
                        default=_nproc)
    args = parser.parse_args()

    if args.indir is None:
        args.indir = _lyapath()

    if args.output is None:
        args.output = 'metadata-simpleSpec.fits'

    log.info('Reading mocks from {}'.format(args.indir))
    data, filemap = read_lya(args.indir, nproc=args.nproc)

    log.info('Writing {}'.format(args.output))
    write_bintable(args.output, data, extname='METADATA', clobber=True)
    header = dict(MOCKDIR=os.path.abspath(args.indir))
    write_bintable(args.output, filemap, extname='FILEMAP', header=header)
Ejemplo n.º 18
0
def main():

    log = get_logger()

    key = 'DESI_ROOT'
    if key not in os.environ:
        log.fatal('Required ${} environment variable not set'.format(key))
        return 0
    desidir = os.getenv(key)
    simsdir = os.path.join(desidir, 'spectro', 'sim', 'bgs-sims1.0')
    brickdir = os.path.join(simsdir, 'bricks')

    parser = argparse.ArgumentParser()
    parser.add_argument('--sim', type=int, default=None, help='Simulation number (see documentation)')
    parser.add_argument('--nproc', type=int, default=1, help='Number of processors to use.')
    parser.add_argument('--simsdir', default=simsdir, help='Top-level simulation directory')
    parser.add_argument('--bricks', action='store_true', help='Generate the brick files.')
    parser.add_argument('--zfind', action='store_true', help='Fit for the redshifts.')
    parser.add_argument('--results', action='store_true', help='Merge all the relevant results.')
    parser.add_argument('--qaplots', action='store_true', help='Generate QAplots.')

    args = parser.parse_args()
    if args.sim is None:
        parser.print_help()
        sys.exit(1)

    # --------------------------------------------------
    # Initialize the parameters of each simulation here.

    if args.sim == 1:
        seed = 678245
        
        brickname = 'sim01'
        nbrick = 50
        nspec = 20

        phase = 0.25
        rmag = (19.5, 19.5)
        redshift = (0.1, 0.3)
        zenith = 30
        exptime = 300
        angle = (0, 150)

        simoptions = [
            '--exptime-range', '{}'.format(exptime), '{}'.format(exptime), 
            '--rmagrange-bgs', '{}'.format(rmag[0]), '{}'.format(rmag[1]), 
            '--zrange-bgs', '{}'.format(redshift[0]), '{}'.format(redshift[1]), 
            '--moon-zenith-range', '{}'.format(zenith), '{}'.format(zenith), 
            '--moon-phase-range', '{}'.format(phase), '{}'.format(phase), 
            '--moon-angle-range', '{}'.format(angle[0]), '{}'.format(angle[1])
            ]
    elif args.sim == 2:
        seed = 991274
        
        brickname = 'sim02'
        nbrick = 50
        nspec = 20

        phase = (0.0, 1.0)
        rmag = (19.5, 19.5)
        redshift = (0.1, 0.3)
        zenith = 30
        exptime = 300
        angle = 60

        simoptions = [
            '--exptime-range', '{}'.format(exptime), '{}'.format(exptime), 
            '--rmagrange-bgs', '{}'.format(rmag[0]), '{}'.format(rmag[1]), 
            '--zrange-bgs', '{}'.format(redshift[0]), '{}'.format(redshift[1]), 
            '--moon-zenith-range', '{}'.format(zenith), '{}'.format(zenith), 
            '--moon-phase-range', '{}'.format(phase[0]), '{}'.format(phase[1]), 
            '--moon-angle-range', '{}'.format(angle), '{}'.format(angle)
            ]
            
    elif args.sim == 3:
        seed = 471934
        
        brickname = 'sim03'
        nbrick = 50
        nspec = 20

        phase = (0.0, 1.0)
        rmag = (19.5, 19.5)
        redshift = (0.1, 0.3)
        zenith = 30
        exptime = 300
        angle = (0, 150)

        simoptions = [
            '--exptime-range', '{}'.format(exptime), '{}'.format(exptime), 
            '--rmagrange-bgs', '{}'.format(rmag[0]), '{}'.format(rmag[1]), 
            '--zrange-bgs', '{}'.format(redshift[0]), '{}'.format(redshift[1]), 
            '--moon-zenith-range', '{}'.format(zenith), '{}'.format(zenith), 
            '--moon-phase-range', '{}'.format(phase[0]), '{}'.format(phase[1]), 
            '--moon-angle-range', '{}'.format(angle[0]), '{}'.format(angle[1])
            ]

    elif args.sim == 4:
        seed = 971234
        
        brickname = 'sim04'
        nbrick = 100
        nspec = 50

        phase = (0.0, 1.0)
        rmag = (17.5, 20.0)
        redshift = (0.1, 0.3)
        zenith = 30
        exptime = 300
        angle = (0, 150)

        simoptions = [
            '--exptime-range', '{}'.format(exptime), '{}'.format(exptime), 
            '--rmagrange-bgs', '{}'.format(rmag[0]), '{}'.format(rmag[1]), 
            '--zrange-bgs', '{}'.format(redshift[0]), '{}'.format(redshift[1]), 
            '--moon-zenith-range', '{}'.format(zenith), '{}'.format(zenith), 
            '--moon-phase-range', '{}'.format(phase[0]), '{}'.format(phase[1]), 
            '--moon-angle-range', '{}'.format(angle[0]), '{}'.format(angle[1])
            ]
            
    nobj = nbrick*nspec
    rand = np.random.RandomState(seed)

    # --------------------------------------------------
    # Generate the brick and truth files.
    if args.bricks:
        brightoptions = [
            '--brickname', '{}'.format(brickname),
            '--nbrick', '{}'.format(nbrick),
            '--nspec', '{}'.format(nspec),
            '--outdir', '{}'.format(simsdir),
            '--brickdir', '{}'.format(brickdir),
            '--seed', '{}'.format(seed),
            '--objtype', 'BGS']

        brightargs = brightsims.parse(np.hstack((brightoptions, simoptions)))
        brightargs.verbose = True
        brightsims.main(brightargs)

    # --------------------------------------------------
    # Fit the redshifts
    if args.zfind:
        inputfile = os.path.join(simsdir, brickname+'-input.fits')
        log.info('Reading {}'.format(inputfile))
        cat = fits.getdata(inputfile, 1)

        log.info('Testing with just one brick!')
        #for ib in range(10, 11):
        for ib in range(nbrick):
            thisbrick = cat['BRICKNAME'][ib]
            brickfiles = [os.path.join(brickdir, 'brick-{}-{}.fits'.format(ch, thisbrick)) for ch in ['b', 'r', 'z']]
            redoptions = [
                '--brick', thisbrick,
                '--nproc', '{}'.format(args.nproc),
                '--specprod_dir', simsdir, 
                '--zrange-galaxy', '{}'.format(redshift[0]), '{}'.format(redshift[1]), 
                '--outfile', os.path.join(brickdir, thisbrick, 'zbest-{}.fits'.format(thisbrick)),
                '--objtype', 'ELG,LRG']
            redargs = zfind.parse(redoptions)
            zfind.main(redargs)

    # --------------------------------------------------
    # Parse and write out the simulation inputs, brick spectra, and redshifts
    if args.results:
        inputfile = os.path.join(simsdir, brickname+'-input.fits')
        log.info('Reading {}'.format(inputfile))
        cat = fits.getdata(inputfile, 1)

        # Build a results table.
        resultfile = makepath(os.path.join(simsdir, '{}-results.fits'.format(brickname)))
        resultcols = [
            ('EXPTIME', 'f4'),
            ('AIRMASS', 'f4'),
            ('MOONPHASE', 'f4'),
            ('MOONANGLE', 'f4'),
            ('MOONZENITH', 'f4'),
            ('SNR_B', 'f4'),
            ('SNR_R', 'f4'),
            ('SNR_Z', 'f4'),
            ('TARGETID', 'i8'),
            ('RMAG', 'f4'),
            ('D4000', 'f4'),
            ('EWHBETA', 'f4'), 
            ('ZTRUE', 'f4'), 
            ('Z', 'f4'), 
            ('ZERR', 'f4'), 
            ('ZWARNING', 'f4')]
        result = Table(np.zeros(nobj, dtype=resultcols))

        result['EXPTIME'].unit = 's'
        result['MOONANGLE'].unit = 'deg'
        result['MOONZENITH'].unit = 'deg'

        for ib in range(nbrick):
            # Copy over some data.
            thisbrick = cat['BRICKNAME'][ib]
            result['EXPTIME'][nspec*ib:nspec*(ib+1)] = cat['EXPTIME'][ib]
            result['AIRMASS'][nspec*ib:nspec*(ib+1)] = cat['AIRMASS'][ib]
            result['MOONPHASE'][nspec*ib:nspec*(ib+1)] = cat['MOONPHASE'][ib]
            result['MOONANGLE'][nspec*ib:nspec*(ib+1)] = cat['MOONANGLE'][ib]
            result['MOONZENITH'][nspec*ib:nspec*(ib+1)] = cat['MOONZENITH'][ib]

            # Read the truth file of the first channel to get the metadata.
            truthfile = os.path.join(brickdir, thisbrick, 'truth-brick-{}-{}.fits'.format('b', thisbrick))
            log.info('Reading {}'.format(truthfile))
            truth = io.Brick(truthfile).hdu_list[4].data

            result['TARGETID'][nspec*ib:nspec*(ib+1)] = truth['TARGETID']
            result['RMAG'][nspec*ib:nspec*(ib+1)] = 22.5-2.5*np.log10(truth['DECAM_FLUX'][:,2])
            result['D4000'][nspec*ib:nspec*(ib+1)] = truth['D4000']
            result['EWHBETA'][nspec*ib:nspec*(ib+1)] = truth['EWHBETA']
            result['ZTRUE'][nspec*ib:nspec*(ib+1)] = truth['TRUEZ']

            # Finally read the zbest file. 
            zbestfile = os.path.join(brickdir, thisbrick, 'zbest-{}.fits'.format(thisbrick))
            if os.path.isfile(zbestfile):
                log.info('Reading {}'.format(zbestfile))
                zbest = read_zbest(zbestfile)
                # There's gotta be a better way than looping here!
                for ii in range(nspec):
                    this = np.where(zbest.targetid[ii] == result['TARGETID'])[0]
                    result['Z'][this] = zbest.z[ii]
                    result['ZERR'][this] = zbest.zerr[ii]
                    result['ZWARNING'][this] = zbest.zwarn[ii]

            #pdb.set_trace()
                    
            # Finally, read the spectra and truth tables, one per channel.
            for channel in ('b','r','z'):
                brickfile = os.path.join(brickdir, thisbrick, 'brick-{}-{}.fits'.format(channel, thisbrick))

                log.info('Reading {}'.format(brickfile))
                brick = io.Brick(brickfile)
                wave = brick.get_wavelength_grid()

                for iobj in range(nspec):
                    flux = brick.hdu_list[0].data[iobj,:]
                    ivar = brick.hdu_list[1].data[iobj,:]
                    these = np.where((wave>np.mean(wave)-50)*(wave<np.mean(wave)+50)*(flux>0))[0]
                    result['SNR_'+channel.upper()][nspec*ib+iobj] = \
                      np.median(np.sqrt(flux[these]*ivar[these]))

        log.info('Writing {}'.format(resultfile))
        write_bintable(resultfile, result, extname='RESULTS', clobber=True)
        
    # --------------------------------------------------
    # Build QAplots
    if args.qaplots:
        phaserange = (-0.05, 1.05)
        snrrange = (0, 3)
        rmagrange = (17.5, 20)
        anglerange = (-5, 155)
        d4000range = (0.9, 2.2)
        snrinterval = 1.0

        cmap = mpl.colors.ListedColormap(sns.color_palette('muted'))
        
        resultfile = os.path.join(simsdir, '{}-results.fits'.format(brickname))
        log.info('Reading {}'.format(resultfile))
        res = fits.getdata(resultfile, 1)

        qafile = os.path.join(simsdir, 'qa-{}.pdf'.format(brickname))
        log.info('Writing {}'.format(qafile))

        # ------------------------------
        # Simulation 1
        if args.sim == 1:
            fig, ax0 = plt.subplots(1, 1, figsize=(6, 4.5))

            ax0.scatter(res['MOONANGLE']+rand.normal(0, 0.2, nobj), res['SNR_B'], label='b channel', c=col[1])
            ax0.scatter(res['MOONANGLE']+rand.normal(0, 0.2, nobj), res['SNR_R'], label='r channel', c=col[2])
            ax0.scatter(res['MOONANGLE']+rand.normal(0, 0.2, nobj), res['SNR_Z'], label='z channel', c=col[0])
            ax0.set_xlabel('Object-Moon Angle (deg)')
            ax0.set_ylabel(r'Signal-to-Noise Ratio (pixel$^{-1}$)')
            ax0.set_xlim(anglerange)
            ax0.set_ylim(snrrange)

            plt.legend(loc='upper left', labelspacing=0.25)
            plt.text(0.95, 0.7, 't = {:g} s\nr = {:g} mag\nRedshift = {:.2f}-{:.2f}'.format(exptime, rmag,
                                                                                            redshift[0], redshift[1])+\
                     '\nLunar Zenith Angle = {:g} deg\nLunar Phase = {:g}'.format(zenith, phase),
                     horizontalalignment='right', transform=ax0.transAxes,
                     fontsize=11)
    
            plt.subplots_adjust(bottom=0.2, right=0.95, left=0.15)
            plt.savefig(qafile)
            plt.close()

            #pdb.set_trace()

        # ------------------------------
        # Simulation 2
        if args.sim == 2:
            fig, ax0 = plt.subplots(1, 1, figsize=(6, 4.5))

            ax0.scatter(res['MOONPHASE']+rand.normal(0, 0.02, nobj), res['SNR_B'], label='b channel', c=col[1])
            ax0.scatter(res['MOONPHASE']+rand.normal(0, 0.02, nobj), res['SNR_R'], label='r channel', c=col[2])
            ax0.scatter(res['MOONPHASE']+rand.normal(0, 0.02, nobj), res['SNR_Z'], label='z channel', c=col[0])
            ax0.set_xlabel('Lunar Phase (0=Full, 1=New)')
            ax0.set_ylabel(r'Signal-to-Noise Ratio (pixel$^{-1}$)')
            ax0.set_xlim(phaserange)
            ax0.set_ylim(snrrange)

            plt.legend(loc='upper left', labelspacing=0.25)
            plt.text(0.95, 0.7, 't = {:g} s\nr = {:g} mag\nRedshift = {:.2f}-{:.2f}'.format(exptime, rmag,
                                                                                            redshift[0], redshift[1])+\
                     '\nLunar Zenith Angle = {:g} deg\nObject-Moon Angle = {:g} deg'.format(zenith, angle),
                     horizontalalignment='right', transform=ax0.transAxes,
                     fontsize=11)
    
            plt.subplots_adjust(bottom=0.2, right=0.95, left=0.15)
            plt.savefig(qafile)
            plt.close()

        # ------------------------------
        # Simulation 3
        if args.sim == 3:
            fig, ax0 = plt.subplots(1, 1, figsize=(6, 4))

            im = ax0.scatter(res['MOONANGLE']+rand.normal(0, 0.3, nobj), res['SNR_R'], c=res['MOONPHASE'], vmin=phaserange,
                             cmap=cmap)
            ax0.set_xlabel('Object-Moon Angle (deg)')
            ax0.set_ylabel(r'r channel Signal-to-Noise Ratio (pixel$^{-1}$)')
            ax0.set_xlim(anglerange)
            ax0.set_ylim(snrrange)
            ax0.yaxis.set_major_locator(mpl.ticker.MultipleLocator(snrinterval))

            plt.text(0.95, 0.7, 't = {:g} s\nr = {:g} mag\nRedshift = {:.2f}-{:.2f}'.format(exptime, rmag,
                                                                                            redshift[0], redshift[1])+\
                     '\nLunar Zenith Angle = {:g} deg'.format(zenith),
                     horizontalalignment='right', transform=ax0.transAxes,
                     fontsize=11)
    
            cbar = fig.colorbar(im)
            cbar.set_ticks([0, 0.5, 1])
            cbar.ax.set_yticklabels(['Full','Quarter','New'], rotation=90)
            cbar.ax.set_ylabel('Lunar Phase')

            plt.subplots_adjust(bottom=0.2, right=1.0)
            plt.savefig(qafile)
            plt.close()

        # ------------------------------
        # Simulation 4
        if args.sim == 4:
            bins = 30
            zgood = (np.abs(res['Z']-res['ZTRUE'])<5E-5)*(res['ZWARNING']==0)*1

            H, xedges, yedges = np.histogram2d(res['RMAG'], res['MOONPHASE'], bins=bins, weights=zgood)
            H2, _, _ = np.histogram2d(res['RMAG'], res['MOONPHASE'], bins=bins)
            extent = np.array((rmagrange, phaserange)).flatten()

            #pdb.set_trace()            

            fig, ax0 = plt.subplots(1, 1, figsize=(6, 4))
            im = ax0.imshow(H/H2, extent=extent, interpolation='nearest')#, cmap=cmap)
            ax0.set_xlabel('r (AB mag)')
            ax0.set_ylabel('Lunar Phase (0=Full, 1=New)')
            ax0.set_xlim(rmagrange)
            ax0.set_ylim(phaserange)

            #plt.text(0.95, 0.7, 't = {:g} s\nr = {:g} mag\nRedshift = {:.2f}-{:.2f}'.format(exptime, rmag,
            #                                                                                redshift[0], redshift[1])+\
            #         '\nLunar Zenith Angle = {:g} deg'.format(zenith),
            #         horizontalalignment='right', transform=ax0.transAxes,
            #         fontsize=11)
    
            cbar = fig.colorbar(im)
            #cbar.set_ticks([0, 0.5, 1])
            #cbar.ax.set_yticklabels(['Full','Quarter','New'], rotation=90)
            #cbar.ax.set_ylabel('Lunar Phase')

            plt.subplots_adjust(bottom=0.2, right=1.0)
            plt.savefig(qafile)
            plt.close()
        
        # ------------------------------
        # Simulation 10
        if args.sim == 10:
            zgood = (np.abs(res['Z']-res['ZTRUE'])<0.001)*(res['ZWARNING']==0)*1
            #pdb.set_trace()            
            
            fig, (ax0, ax1, ax2) = plt.subplots(3, 1, figsize=(6,6))

            # moon phase vs S/N(r)
            im = ax0.scatter(res['RMAG'], res['SNR_R'], c=res['MOONPHASE'], vmin=phaserange,
                             cmap=cmap)
            ax0.set_xlabel('r (AB mag)')
            ax0.set_ylabel('S/N (r channel)')
            ax0.set_xlim(rmagrange)
            ax0.set_ylim(snrrange)
            ax0.yaxis.set_major_locator(mpl.ticker.MultipleLocator(snrinterval))

            # object-moon angle vs S/N(r)
            im = ax1.scatter(res['MOONANGLE'], res['SNR_R'], c=res['MOONPHASE'], vmin=phaserange,
                             cmap=cmap)
            ax1.set_xlabel('Object-Moon Angle (deg)')
            ax1.set_ylabel('S/N (r channel)')
            ax1.set_xlim(anglerange)
            ax1.set_ylim(snrrange)
            ax1.yaxis.set_major_locator(mpl.ticker.MultipleLocator(snrinterval))

            # D(4000) vs S/N(r)
            im = ax2.scatter(res['D4000'], res['SNR_R'], c=res['MOONPHASE'], vmin=phaserange,
                             cmap=cmap)
            ax2.set_xlabel('$D_{n}(4000)$')
            ax2.set_ylabel('S/N (r channel)')
            ax2.set_xlim(d4000range)
            ax2.set_ylim(snrrange)
            ax2.yaxis.set_major_locator(mpl.ticker.MultipleLocator(snrinterval))

            # Shared colorbar
            cbarax = fig.add_axes([0.83, 0.15, 0.03, 0.8])
            cbar = fig.colorbar(im, cax=cbarax)
            ticks = ['Full','Quarter','New']
            cbar.set_ticks([0, 0.5, 1])
            cbar.ax.set_yticklabels(ticks, rotation=-45)
        
            plt.tight_layout(pad=0.5)#, h_pad=0.2, w_pad=0.3)
            plt.subplots_adjust(right=0.78)
            plt.savefig(qafile)
            plt.close()