Beispiel #1
0
def simarc(arcdata, nspec=5000, nonuniform=False, testslit=False):
    '''
    Simulates an arc lamp exposure (CCD pixel to wavelength calibration).

    Args:
        arcdata: Table with columns VACUUM_WAVE and ELECTRONS

    Options:
        nspec:      (int)  number of spectra to simulate
        nonuniform: (bool) include calibration screen non-uniformity

    Returns: (wave, phot, fibermap)
        wave: 1D[nwave] wavelengths in Angstroms
        phot: 2D[nspec, nwave] photons observed by CCD (i.e. electrons)
        fibermap: fibermap Table

    Note: this bypasses specsim since we don't have an arclamp model in
    surface brightness units; we only have electrons on the CCD.  But it
    does include the effect of varying fiber sizes.

    TODO:
        * add exptime support
        * update inputs to surface brightness and DESI lamp lines (DESI-2674)
    '''
    wave = arcdata['VACUUM_WAVE']
    phot = arcdata['ELECTRONS']

    if testslit:
        fibermap = astropy.table.Table(testslit_fibermap()[0:nspec])

    else:
        fibermap = astropy.table.Table(desispec.io.empty_fibermap(nspec))

    fibermap.meta['FLAVOR'] = 'arc'
    fibermap['OBJTYPE'] = 'ARC'

    x = fibermap['X_TARGET']
    y = fibermap['Y_TARGET']

    r = np.sqrt(x**2 + y**2)

    #- Determine ratio of fiber sizes relative to largest fiber
    fiber_area = fiber_area_arcsec2(fibermap['X_TARGET'], fibermap['Y_TARGET'])
    size_ratio = fiber_area / np.max(fiber_area)

    #- Correct photons for fiber size
    phot = np.tile(phot, nspec).reshape(nspec, len(wave))
    phot = (phot.T * size_ratio).T

    #- Apply calibration screen non-uniformity
    if nonuniform:
        ratio = _calib_screen_uniformity(radius=r)

        assert np.all(ratio <= 1) and np.all(ratio > 0.99)

        phot = (phot.T * ratio).T

    return wave, phot, fibermap
Beispiel #2
0
def exposure_fiberflat(channel, expid, metric, outfile=None):
    """ Generate an Exposure level plot of a FiberFlat metric
    Args:
        channel: str, e.g. 'b', 'r', 'z'
        expid: int
        metric: str,  allowed entires are: ['meanflux']

    Returns:

    """
    from desispec.io.meta import find_exposure_night, findfile
    from desispec.io.frame import read_meta_frame, read_frame
    from desispec.io.fiberflat import read_fiberflat
    from desimodel.focalplane import fiber_area_arcsec2
    log = get_logger()
    # Find exposure
    night = find_exposure_night(expid)
    # Search for frames with the input channel
    frame0 = findfile('frame', camera=channel+'0', night=night, expid=expid)
    if not os.path.exists(frame0):
        log.fatal("No Frame 0 for channel={:s} and expid={:d}".format(channel, expid))
    # Confirm frame is a Flat
    fmeta = read_meta_frame(frame0)
    assert fmeta['FLAVOR'].strip() == 'flat'
    # Load up all the frames
    x,y,metrics = [],[],[]
    for wedge in range(10):
        # Load
        frame_file = findfile('frame', camera=channel+'{:d}'.format(wedge), night=night, expid=expid)
        fiber_file = findfile('fiberflat', camera=channel+'{:d}'.format(wedge), night=night, expid=expid)
        try:
            frame = read_frame(frame_file)
        except:
            continue
        else:
            fiberflat = read_fiberflat(fiber_file)
        fibermap = frame.fibermap
        gdp = fiberflat.mask == 0
        # X,Y
        x.append([fibermap['X_TARGET']])
        y.append([fibermap['Y_TARGET']])
        area = fiber_area_arcsec2(x[-1], y[-1])
        mean_area = np.mean(area)
        # Metric
        if metric == 'meanflux':
            mean_norm = np.mean(fiberflat.fiberflat*gdp,axis=1) / (area / mean_area)
            metrics.append([mean_norm])
    # Cocatenate
    x = np.concatenate(x)
    y = np.concatenate(y)
    metrics = np.concatenate(metrics)
    # Plot
    if outfile is None:
        outfile='qa_{:08d}_{:s}_fiberflat.png'.format(expid, channel)
    exposure_map(x,y,metrics, mlbl='Mean Flux',
                 title='Mean Flux for Exposure {:08d}, Channel {:s}'.format(expid, channel),
                 outfile=outfile)
Beispiel #3
0
def qa_fiberflat(param, frame, fiberflat):
    """ Calculate QA on FiberFlat object

    Args:
        param: dict of QA parameters
        frame: Frame
        fiberflat: FiberFlat

    Returns:
        qadict: dict of QA outputs
          Need to record simple Python objects for yaml (str, float, int)
    """
    from desimodel.focalplane import fiber_area_arcsec2
    log = get_logger()

    # x, y, area
    fibermap = frame.fibermap
    x = fibermap['X_TARGET']
    y = fibermap['Y_TARGET']
    area = fiber_area_arcsec2(x, y)
    mean_area = np.mean(area)
    norm_area = area / mean_area
    npix = fiberflat.fiberflat.shape[1]

    # Normalize
    norm_flat = fiberflat.fiberflat / np.outer(norm_area, np.ones(npix))

    # Output dict
    qadict = {}

    # Check amplitude of the meanspectrum
    qadict['MAX_MEANSPEC'] = float(np.max(fiberflat.meanspec))
    if qadict['MAX_MEANSPEC'] < 100000:
        log.warning("Low counts in meanspec = {:g}".format(
            qadict['MAX_MEANSPEC']))

    # Record chi2pdf
    try:
        qadict['CHI2PDF'] = float(fiberflat.chi2pdf)
    except TypeError:
        qadict['CHI2PDF'] = 0.

    # N mask
    qadict['N_MASK'] = int(np.sum(fiberflat.mask > 0))
    if qadict['N_MASK'] > param['MAX_N_MASK']:  # Arbitrary
        log.warning("High rejection rate: {:d}".format(qadict['N_MASK']))

    # Scale (search for low/high throughput)
    gdp = fiberflat.mask == 0
    rtio = (frame.flux / np.outer(norm_area, np.ones(npix))) / np.outer(
        np.ones(fiberflat.nspec), fiberflat.meanspec)
    scale = np.median(rtio * gdp, axis=1)
    MAX_SCALE_OFF = float(np.max(np.abs(scale - 1.)))
    fiber = int(np.argmax(np.abs(scale - 1.)))
    qadict['MAX_SCALE_OFF'] = [MAX_SCALE_OFF, fiber]
    if qadict['MAX_SCALE_OFF'][0] > param['MAX_SCALE_OFF']:
        log.warning("Discrepant flux in fiberflat: {:g}, {:d}".format(
            qadict['MAX_SCALE_OFF'][0], qadict['MAX_SCALE_OFF'][1]))

    # Offset in fiberflat
    qadict['MAX_OFF'] = float(np.max(np.abs(norm_flat - 1.)))
    if qadict['MAX_OFF'] > param['MAX_OFF']:
        log.warning("Large offset in fiberflat: {:g}".format(
            qadict['MAX_OFF']))

    # Offset in mean of fiberflat
    #mean = np.mean(fiberflat.fiberflat*gdp,axis=1)
    mean = np.mean(norm_flat * gdp, axis=1)
    fiber = int(np.argmax(np.abs(mean - 1.)))
    qadict['MAX_MEAN_OFF'] = [float(np.max(np.abs(mean - 1.))), fiber]
    if qadict['MAX_MEAN_OFF'][0] > param['MAX_MEAN_OFF']:
        log.warning("Discrepant mean in fiberflat: {:g}, {:d}".format(
            qadict['MAX_MEAN_OFF'][0], qadict['MAX_MEAN_OFF'][1]))

    # RMS in individual fibers
    rms = np.std(gdp * (norm_flat - np.outer(mean, np.ones(fiberflat.nwave))),
                 axis=1)
    #rms = np.std(gdp*(fiberflat.fiberflat-
    #                  np.outer(mean, np.ones(fiberflat.nwave))),axis=1)
    fiber = int(np.argmax(rms))
    qadict['MAX_RMS'] = [float(np.max(rms)), fiber]
    if qadict['MAX_RMS'][0] > param['MAX_RMS']:
        log.warning("Large RMS in fiberflat: {:g}, {:d}".format(
            qadict['MAX_RMS'][0], qadict['MAX_RMS'][1]))

    # Return
    return qadict
Beispiel #4
0
def qa_fiberflat(param, frame, fiberflat):
    """ Calculate QA on FiberFlat object

    Args:
        param: dict of QA parameters
        frame: Frame
        fiberflat: FiberFlat

    Returns:
        qadict: dict of QA outputs
          Need to record simple Python objects for yaml (str, float, int)
    """
    from desimodel.focalplane import fiber_area_arcsec2
    log = get_logger()

    # x, y, area
    fibermap = frame.fibermap
    x = fibermap['DESIGN_X']
    y = fibermap['DESIGN_Y']
    area = fiber_area_arcsec2(x, y)
    mean_area = np.mean(area)
    norm_area = area / mean_area
    npix = fiberflat.fiberflat.shape[1]

    # Normalize
    norm_flat = fiberflat.fiberflat / np.outer(norm_area, np.ones(npix))

    # Output dict
    qadict = {}

    # Check amplitude of the meanspectrum
    qadict['MAX_MEANSPEC'] = float(np.max(fiberflat.meanspec))
    if qadict['MAX_MEANSPEC'] < 100000:
        log.warning("Low counts in meanspec = {:g}".format(qadict['MAX_MEANSPEC']))

    # Record chi2pdf
    try:
        qadict['CHI2PDF'] = float(fiberflat.chi2pdf)
    except TypeError:
        qadict['CHI2PDF'] = 0.

    # N mask
    qadict['N_MASK'] = int(np.sum(fiberflat.mask > 0))
    if qadict['N_MASK'] > param['MAX_N_MASK']:  # Arbitrary
        log.warning("High rejection rate: {:d}".format(qadict['N_MASK']))

    # Scale (search for low/high throughput)
    gdp = fiberflat.mask == 0
    rtio = (frame.flux / np.outer(norm_area, np.ones(npix))) / np.outer(np.ones(fiberflat.nspec),fiberflat.meanspec)
    scale = np.median(rtio*gdp,axis=1)
    MAX_SCALE_OFF = float(np.max(np.abs(scale-1.)))
    fiber = int(np.argmax(np.abs(scale-1.)))
    qadict['MAX_SCALE_OFF'] = [MAX_SCALE_OFF, fiber]
    if qadict['MAX_SCALE_OFF'][0] > param['MAX_SCALE_OFF']:
        log.warning("Discrepant flux in fiberflat: {:g}, {:d}".format(
                qadict['MAX_SCALE_OFF'][0], qadict['MAX_SCALE_OFF'][1]))

    # Offset in fiberflat
    qadict['MAX_OFF'] = float(np.max(np.abs(norm_flat-1.)))
    if qadict['MAX_OFF'] > param['MAX_OFF']:
        log.warning("Large offset in fiberflat: {:g}".format(qadict['MAX_OFF']))

    # Offset in mean of fiberflat
    #mean = np.mean(fiberflat.fiberflat*gdp,axis=1)
    mean = np.mean(norm_flat*gdp,axis=1)
    fiber = int(np.argmax(np.abs(mean-1.)))
    qadict['MAX_MEAN_OFF'] = [float(np.max(np.abs(mean-1.))), fiber]
    if qadict['MAX_MEAN_OFF'][0] > param['MAX_MEAN_OFF']:
        log.warning("Discrepant mean in fiberflat: {:g}, {:d}".format(
                qadict['MAX_MEAN_OFF'][0], qadict['MAX_MEAN_OFF'][1]))

    # RMS in individual fibers
    rms = np.std(gdp*(norm_flat - np.outer(mean, np.ones(fiberflat.nwave))),axis=1)
    #rms = np.std(gdp*(fiberflat.fiberflat-
    #                  np.outer(mean, np.ones(fiberflat.nwave))),axis=1)
    fiber = int(np.argmax(rms))
    qadict['MAX_RMS'] = [float(np.max(rms)), fiber]
    if qadict['MAX_RMS'][0] > param['MAX_RMS']:
        log.warning("Large RMS in fiberflat: {:g}, {:d}".format(
                qadict['MAX_RMS'][0], qadict['MAX_RMS'][1]))

    # Return
    return qadict
Beispiel #5
0
def frame_fiberflat(outfil, qaframe, frame, fiberflat):
    """ QA plots for fiber flat

    Args:
        outfil:
        qaframe:
        frame:
        fiberflat:

    Returns:
        Stuff?
    """
    from desimodel.focalplane import fiber_area_arcsec2
    # Setup
    fibermap = frame.fibermap
    gdp = fiberflat.mask == 0
    nfiber = len(frame.fibers)
    xfiber = np.zeros(nfiber)
    yfiber = np.zeros(nfiber)
    for ii,fiber in enumerate(frame.fibers):
        mt = np.where(fiber == fibermap['FIBER'])[0]
        xfiber[ii] = fibermap['X_TARGET'][mt]
        yfiber[ii] = fibermap['Y_TARGET'][mt]
    area = fiber_area_arcsec2(xfiber,yfiber)
    mean_area = np.mean(area)

    jet = cm = plt.get_cmap('jet')

    # Tile plot(s)
    fig = plt.figure(figsize=(8, 5.0))
    gs = gridspec.GridSpec(2,2)

    # Mean Flatfield flux in each fiber
    ax = plt.subplot(gs[0,0])
    ax.xaxis.set_major_locator(plt.MultipleLocator(100.))

    mean_flux = np.mean(frame.flux*gdp, axis=1) / fiber_area_arcsec2(xfiber,yfiber)
    rms_mean = np.std(mean_flux)
    med_mean = np.median(mean_flux)
    #from xastropy.xutils import xdebug as xdb
    #pdb.set_trace()
    mplt = ax.scatter(xfiber, yfiber, marker='o', s=9., c=mean_flux, cmap=jet)
    mplt.set_clim(vmin=med_mean-2*rms_mean, vmax=med_mean+2*rms_mean)
    cb = fig.colorbar(mplt)
    cb.set_label('Mean Flux')

    # Mean
    ax = plt.subplot(gs[0,1])
    ax.xaxis.set_major_locator(plt.MultipleLocator(100.))
    mean_norm = np.mean(fiberflat.fiberflat*gdp,axis=1) / (area/mean_area)
    m2plt = ax.scatter(xfiber, yfiber, marker='o', s=9., c=mean_norm, cmap=jet)
    #m2plt.set_clim(vmin=0.98, vmax=1.02)
    cb = fig.colorbar(m2plt)
    cb.set_label('Mean of Fiberflat')

    # RMS
    ax = plt.subplot(gs[1,0])
    ax.xaxis.set_major_locator(plt.MultipleLocator(100.))
    rms = np.std(gdp*(fiberflat.fiberflat-
                      np.outer(mean_norm, np.ones(fiberflat.nwave))),axis=1)
    rplt = ax.scatter(xfiber, yfiber, marker='o', s=9., c=rms, cmap=jet)
    #rplt.set_clim(vmin=0.98, vmax=1.02)
    cb = fig.colorbar(rplt)
    cb.set_label('RMS in Fiberflat')

    # Meta text
    ax2 = plt.subplot(gs[1,1])
    ax2.set_axis_off()
    show_meta(ax2, qaframe, 'FIBERFLAT', outfil)
    """
    xlbl = 0.05
    ylbl = 0.85
    i0 = outfil.rfind('/')
    ax2.text(xlbl, ylbl, outfil[i0+1:], color='black', transform=ax2.transAxes, ha='left')
    yoff=0.10
    for key in sorted(qaframe.data['FIBERFLAT']['METRICS'].keys()):
        if key in ['QA_FIG']:
            continue
        # Show
        ylbl -= yoff
        ax2.text(xlbl+0.05, ylbl, key+': '+str(qaframe.data['FIBERFLAT']['METRICS'][key]),
            transform=ax2.transAxes, ha='left', fontsize='x-small')
    """

    # Finish
    plt.tight_layout(pad=0.1,h_pad=0.0,w_pad=0.0)
    _ = makepath(outfil)
    plt.savefig(outfil)
    plt.close()
    print('Wrote QA SkyRes file: {:s}'.format(outfil))