Esempio n. 1
0
def plotspec(spec,spec2=None,model=None,figsize=10):
    """ Plot a spectrum."""
    norder = spec.norder
    fig = plt.gcf()   # get current graphics window
    fig.clf()         # clear
    # Single-order plot
    if norder==1:
        ax = fig.subplots()
        fig.set_figheight(figsize*0.5)
        fig.set_figwidth(figsize)
        plt.plot(spec.wave,spec.flux,'b',label='Spectrum 1',linewidth=1)
        if spec2 is not None:
            plt.plot(spec2.wave,spec2.flux,'green',label='Spectrum 2',linewidth=1)            
        if model is not None:
            plt.plot(model.wave,model.flux,'r',label='Model',linewidth=1,alpha=0.8)
        leg = ax.legend(loc='upper left', frameon=False)
        plt.xlabel('Wavelength (Angstroms)')
        plt.ylabel('Normalized Flux')
        xr = dln.minmax(spec.wave)
        allflux = spec.flux.flatten()
        if spec2 is not None:
            allflux = np.concatenate((allflux,spec2.flux.flatten()))
        if model is not None:
            allflux = np.concatenate((allflux,model.flux.flatten()))                
        yr = [np.min(allflux), np.max(allflux)]
        yr = [yr[0]-dln.valrange(yr)*0.15,yr[1]+dln.valrange(yr)*0.005]
        yr = [np.max([yr[0],-0.2]), np.min([yr[1],2.0])]
        plt.xlim(xr)
        plt.ylim(yr)
    # Multi-order plot
    else:
        ax = fig.subplots(norder)
        fig.set_figheight(figsize)
        fig.set_figwidth(figsize)
        for i in range(norder):
            ax[i].plot(spec.wave[:,i],spec.flux[:,i],'b',label='Spectrum 1',linewidth=1)
            if spec2 is not None:
                ax[i].plot(spec2.wave[:,i],spec2.flux[:,i],'green',label='Spectrum 2',linewidth=1)                        
            if model is not None:
                ax[i].plot(model.wave[:,i],model.flux[:,i],'r',label='Model',linewidth=1,alpha=0.8)
            if i==0:
                leg = ax[i].legend(loc='upper left', frameon=False)
            ax[i].set_xlabel('Wavelength (Angstroms)')
            ax[i].set_ylabel('Normalized Flux')
            xr = dln.minmax(spec.wave[:,i])
            allflux = spec.flux[:,i].flatten()
            if spec2 is not None:
                allflux = np.concatenate((allflux,spec2.flux[:,i].flatten()))
            if model is not None:
                allflux = np.concatenate((allflux,model.flux[:,i].flatten()))                
            yr = [np.min(allflux), np.max(allflux)]
            yr = [yr[0]-dln.valrange(yr)*0.05,yr[1]+dln.valrange(yr)*0.05]
            if i==0:
                yr = [yr[0]-dln.valrange(yr)*0.15,yr[1]+dln.valrange(yr)*0.05]            
            yr = [np.max([yr[0],-0.2]), np.min([yr[1],2.0])]
            ax[i].set_xlim(xr)
            ax[i].set_ylim(yr)
def plotfit(cat, pars, cov, savefig=None):
    """ Plot a figure of the data and the proper motion/parallax fit."""

    plt.rcParams.update({'font.size': 12})

    # Compute relative positions
    cenra = np.mean(cat['ra'])
    cendec = np.mean(cat['dec'])
    lon, lat = dcoords.rotsphcen(cat['ra'],
                                 cat['dec'],
                                 cenra,
                                 cendec,
                                 gnomic=True)
    lon *= d2a
    lat *= d2a

    # Array of MJDs for model curve
    mjd = np.linspace(np.min(cat['mjd']), np.max(cat['mjd']), 100)
    out = astrometryfunc([cenra, cendec, mjd], pars[0], pars[1], pars[2],
                         pars[3], pars[4])
    ll = out[0:100]
    bb = out[100:]

    # Plot the model and data
    plt.plot(ll, bb)
    plt.errorbar(lon,
                 lat,
                 xerr=cat['raerr'],
                 yerr=cat['decerr'],
                 fmt='o',
                 color='black',
                 markersize=5,
                 ecolor='lightgray',
                 elinewidth=2,
                 linestyle='none',
                 capsize=0)
    plt.xlabel('dRA (arcsec)')
    plt.ylabel('dDEC (arcsec)')
    xr = dln.minmax(np.concatenate((lon, ll)))
    xr = [xr[0] - 0.05 * dln.valrange(xr), xr[1] + 0.05 * dln.valrange(xr)]
    yr = dln.minmax(np.concatenate((lat, bb)))
    yr = [yr[0] - 0.05 * dln.valrange(yr), yr[1] + 0.05 * dln.valrange(yr)]
    plt.xlim(xr)
    plt.ylim(yr)
    perr = np.sqrt(np.diag(cov))
    plt.annotate(
        r'$\mu_\alpha$ = %5.3f $\pm$ %5.3f mas/yr' %
        (pars[2] * 1e3, perr[2] * 1e3) + '\n' +
        r'$\mu_\delta$ = %5.3f $\pm$ %5.3f mas/yr' %
        (pars[3] * 1e3, perr[3] * 1e3) + '\n' +
        r'$\pi$ = %5.3f $\pm$ %5.3f mas' % (pars[4] * 1e3, perr[4] * 1e3),
        xy=(xr[0] + 0.05 * dln.valrange(xr), yr[1] - 0.20 * dln.valrange(yr)),
        ha='left')
    if savefig is not None:
        plt.savefig(savefig)
Esempio n. 3
0
def cutoutfig(im, meas, figfile):
    """ Make a figure of an image."""

    matplotlib.use('Agg')
    if os.path.exists(figfile): os.remove(figfile)
    fig = plt.gcf()  # get current graphics window
    fig.clf()  # clear

    ax = fig.subplots()
    fig.set_figheight(figsize * 0.5)
    fig.set_figwidth(figsize)
    plt.imshow(im, origin='lower')
    leg = ax.legend(loc='upper left', frameon=False)
    plt.xlabel('X')
    plt.ylabel('Y')
    #plt.xlim(xr)
    #plt.ylim(yr)
    ax.annotate(r'S/N=%5.1f',
                xy=(np.mean(xr), yr[0] + dln.valrange(yr) * 0.05),
                ha='center')
    plt.save(figfile)
Esempio n. 4
0
def continuum(spec, norder=6, perclevel=90.0, binsize=0.1, interp=True):
    """
    Measure the continuum of a spectrum.

    Parameters
    ----------
    spec : Spec1D object
           A spectrum object.  This at least needs
                to have a FLUX and WAVE attribute.
    norder : float, optional
            Polynomial order to use for the continuum fitting.
            The default is 6.
    perclevel : float, optional
            Percent level to use for the continuum value
            in large bins.  Default is 90.
    binsize : float, optional
            Fraction of the wavelength range (scaled to -1 to +1) to bin.
            Default is 0.1.
    interp : bool, optional
            Use interpolation of the binned values instead of a polynomial
            fit.  Default is True.

    Returns
    -------
    cont : numpy array
            The continuum array, in the same shape as the input flux.

    Examples
    --------
    .. code-block:: python

         cont = continuum(spec)

    """

    wave = spec.wave.copy().reshape(spec.npix, spec.norder)  # make 2D
    flux = spec.flux.copy().reshape(spec.npix, spec.norder)  # make 2D
    err = spec.err.copy().reshape(spec.npix, spec.norder)  # make 2D
    mask = spec.mask.copy().reshape(spec.npix, spec.norder)  # make 2D
    cont = err.copy() * 0.0 + 1
    for o in range(spec.norder):
        w = wave[:, o].copy()
        wr = [np.min(w), np.max(w)]
        x = (w - np.mean(wr)) / dln.valrange(wr) * 2  # -1 to +1
        y = flux[:, o].copy()
        m = mask[:, o].copy()
        # Divide by median
        medy = np.nanmedian(y)
        if medy <= 0.0:
            medy = 1.0
        y /= medy
        # Perform sigma clipping out large positive outliers
        coef = dln.poly_fit(x[~m], y[~m], 2, robust=True)
        sig = dln.mad(y - dln.poly(x, coef))
        bd, nbd = dln.where((y - dln.poly(x, coef)) > 5 * sig)
        if nbd > 0: m[bd] = True
        gdmask = (y > 0) & (m == False)  # need positive fluxes and no mask set
        if np.sum(gdmask) == 0:
            continue
        # Bin the data points
        xr = [np.nanmin(x), np.nanmax(x)]
        bins = int(np.ceil((xr[1] - xr[0]) / binsize))
        ybin, bin_edges, binnumber = bindata.binned_statistic(
            x[gdmask],
            y[gdmask],
            statistic='percentile',
            percentile=perclevel,
            bins=bins,
            range=None)
        xbin = bin_edges[0:-1] + 0.5 * binsize
        # Interpolate to full grid
        if interp is True:
            fnt = np.isfinite(ybin)
            cont1 = dln.interp(xbin[fnt],
                               ybin[fnt],
                               x,
                               kind='quadratic',
                               extrapolate=True,
                               exporder=1)
        else:
            coef = dln.poly_fit(xbin, ybin, norder)
            cont1 = dln.poly(x, coef)
        cont1 *= medy
        cont[:, o] = cont1

    # Flatten to 1D if norder=1
    if spec.norder == 1:
        cont = cont.flatten()

    return cont
Esempio n. 5
0
def broaden(wave, flux, vgauss=None, vsini=None):
    """
    Broaden a spectrum with Gaussian and Rotational broadening.

    Parameters
    ----------
    wave : numpy array
       Wavelength array of the spectrum.
    flux : numpy array
       Flux array of the spectrum.
    vgauss : float
       The input Gaussian sigma velocity in km/s. Optional.
    vsini : float
       The rotational velocity in km/s.  Optional.
    eps : float, optional
       The linear limb-darkening coefficient (epsilon, 0-1) to use for the
       rotational profile.  Default is 0.6.

    Returns
    -------
    oflux : numpy array
       The output broadened flux array.

    Example
    -------
    .. code-block:: python

         oflux = broaden(wave,flux,vgauss=10.0,vsini=20.0)

    """

    # Create the 2D broadening kernel array
    npix = len(wave)
    # Are the wavelengths logarithmically spaced
    logwave = False
    if dln.valrange(np.diff(np.log(wave))) < 1e-7: logwave = True

    # If the wavelengths are on a logarithmic wavelength scale
    #  then just convolve with a 1D kernel with np.convolve(flux,kernel,mode='same')

    # Check the rotational kernel to see if it will have any effect
    #  this can happen if vsini is low (<~ 3.5 km/s).
    # If it has no effect, then use Vgauss instead
    #  note that this will also have a small (but nonzero) effect
    if vsini is not None:
        if vsini > 0.0:
            if check_rotkernel(wave, vsini) is False:
                if vgauss is None:
                    vgauss = vsini
                else:
                    vgauss = np.sqrt(vgauss**2 + vsini**2)  # add in quadrature
                vsini = 0.0

    # Initializing output flux
    oflux = flux.copy()

    # Add Gaussian broadening
    if vgauss is not None:
        if vgauss != 0.0:
            # 2D kernel
            if logwave == False:
                gkernel = gausskernel(wave, vgauss)
                # Don't use this if it's not going to do anything!!!
                if gkernel.ndim == 2:
                    oflux = convolve_sparse(oflux, gkernel)
            # 1D kernel, log wavelengths
            else:
                gkernel = gausskernel(wave[0:2], vgauss)
                if (gkernel.ndim
                        == 1) and (gkernel[0] > 0.99):  # nothing happened
                    return flux
                oflux = np.convolve(oflux, gkernel[0, :], mode='same')

    # Add Rotational broadening
    if vsini is not None:
        if vsini != 0.0:
            # 2D kernel
            if logwave == False:
                rkernel = rotkernel(wave, vsini)
                # Don't use this if it's not going to do anything!!!
                if rkernel.ndim == 2:
                    oflux = convolve_sparse(oflux, rkernel)
            # 1D kernel, log wavelengths
            else:
                rkernel = rotkernel(wave[0:2], vsini)
                if (rkernel.ndim
                        == 1) and (rkernel[0] > 0.99):  # nothing happened
                    return flux
                oflux = np.convolve(oflux, rkernel[0, :], mode='same')

    return oflux
Esempio n. 6
0
def meascutout(meas, obj, size=10, outdir='./', domask=True):
    """ Input the measurements and create cutouts. """

    expstr = fits.getdata(
        '/net/dl2/dnidever/nsc/instcal/v3/lists/nsc_v3_exposures.fits.gz', 1)
    #expstr = fits.getdata('/net/dl2/dnidever/nsc/instcal/v3/lists/nsc_v3_exposure.fits.gz',1)
    decam = Table.read('/home/dnidever/projects/delvered/data/decam.txt',
                       format='ascii')

    objid = obj['id'][0]

    # Sort by MJD
    si = np.argsort(meas['mjd'])
    meas = meas[si]

    # Make cut on FWHM
    # maybe only use values for 0.5*fwhm_chip to 1.5*fwhm_chip
    sql = "select chip.* from nsc_dr2.chip as chip join nsc_dr2.meas as meas on chip.exposure=meas.exposure and chip.ccdnum=meas.ccdnum"
    sql += " where meas.objectid='" + objid + "'"
    chip = qc.query(sql=sql, fmt='table')
    ind3, ind4 = dln.match(chip['exposure'], meas['exposure'])
    si = np.argsort(ind4)  # sort by input meas catalog
    ind3 = ind3[si]
    ind4 = ind4[si]
    chip = chip[ind3]
    meas = meas[ind4]
    gdfwhm, = np.where((meas['fwhm'] > 0.2 * chip['fwhm'])
                       & (meas['fwhm'] < 2.0 * chip['fwhm']))
    if len(gdfwhm) == 0:
        print('All measurements have bad FWHM values')
        return
    if len(gdfwhm) < len(meas):
        print('Removing ' + str(len(meas) - len(gdfwhm)) +
              ' measurements with bad FWHM values')
        meas = meas[gdfwhm]

    ind1, ind2 = dln.match(expstr['base'], meas['exposure'])
    nind = len(ind1)
    if nind == 0:
        print('No matches')
        return
    # Sort by input meas catalog
    si = np.argsort(ind2)
    ind1 = ind1[si]
    ind2 = ind2[si]

    # Create the reference WCS
    wref = WCS(naxis=2)
    pixscale = 0.26  # DECam, "/pix
    npix = round(size / pixscale)
    if npix % 2 == 0:  # must be odd
        npix += 1
    hpix = npix // 2  # center of image
    wref.wcs.ctype = ['RA---TAN', 'DEC--TAN']
    wref.wcs.crval = [obj['ra'][0], obj['dec'][0]]
    wref.wcs.crpix = [npix // 2, npix // 2]
    wref.wcs.cd = np.array([[pixscale / 3600.0, 0.0], [0.0, pixscale / 3600]])
    wref.array_shape = (npix, npix)
    refheader = wref.to_header()
    refheader['NAXIS'] = 2
    refheader['NAXIS1'] = npix
    refheader['NAXIS2'] = npix

    # Load the data
    instrument = expstr['instrument'][ind1]
    plver = expstr['plver'][ind1]
    fluxfile = expstr['file'][ind1]
    fluxfile = fluxfile.replace('/net/mss1/', '/mss1/')  # for thing/hulk
    maskfile = expstr['maskfile'][ind1]
    maskfile = maskfile.replace('/net/mss1/', '/mss1/')  # for thing/hulk
    ccdnum = meas['ccdnum'][ind2]
    figfiles = []
    xmeas = []
    ymeas = []
    cutimarr = np.zeros((npix, npix, nind), float)
    for i in range(nind):
        #for i in range(3):
        instcode = instrument[i]
        plver1 = plver[i]
        try:
            if instrument[i] == 'c4d':
                dind, = np.where(decam['CCDNUM'] == ccdnum[i])
                extname = decam['NAME'][dind[0]]
                im, head = getfitsext(fluxfile[i], extname, header=True)
                mim, mhead = getfitsext(maskfile[i], extname, header=True)
                #im,head = fits.getdata(fluxfile[i],header=True,extname=extname)
                #mim,mhead = fits.getdata(maskfile[i],header=True,extname=extname)
            else:
                im, head = fits.getdata(fluxfile[i], ccdnum[i], header=True)
                mim, mhead = fits.getdata(maskfile[i], ccdnum[i], header=True)
        except:
            print('error')
            import pdb
            pdb.set_trace()

        # Turn the mask from integer to bitmask
        if ((instcode == 'c4d') &
            (plver1 >= 'V3.5.0')) | (instcode == 'k4m') | (instcode == 'ksb'):
            omim = mim.copy()
            mim *= 0
            nonzero = (omim > 0)
            mim[nonzero] = 2**((omim - 1)[nonzero])  # This takes about 1 sec
        # Fix the DECam Pre-V3.5.0 masks
        if (instcode == 'c4d') & (plver1 < 'V3.5.0'):
            omim = mim.copy()
            mim *= 0  # re-initialize
            mim += (np.bitwise_and(omim, 1) == 1) * 1  # bad pixels
            mim += (np.bitwise_and(omim, 2) == 2) * 4  # saturated
            mim += (np.bitwise_and(omim, 4) == 4) * 32  # interpolated
            mim += (np.bitwise_and(omim, 16) == 16) * 16  # cosmic ray
            mim += (np.bitwise_and(omim, 64) == 64) * 8  # bleed trail

        # Get chip-level information
        exposure = os.path.basename(fluxfile[i])[0:-8]  # remove fits.fz
        chres = qc.query(sql="select * from nsc_dr2.chip where exposure='" +
                         exposure + "' and ccdnum=" + str(ccdnum[i]),
                         fmt='table')

        w = WCS(head)
        # RA/DEC correction for the object
        lon = obj['ra'][0] - chres['ra'][0]
        lat = obj['dec'][0] - chres['dec'][0]
        racorr = chres['ra_coef1'][0] + chres['ra_coef2'][0] * lon + chres[
            'ra_coef3'][0] * lon * lat + chres['ra_coef4'][0] * lat
        deccorr = chres['dec_coef1'][0] + chres['dec_coef2'][0] * lon + chres[
            'dec_coef3'][0] * lon * lat + chres['dec_coef4'][0] * lat
        # apply these offsets to the header WCS CRVAL
        #w.wcs.crval += [racorr,deccorr]
        #head['CRVAL1'] += racorr
        #head['CRVAL2'] += deccorr
        print(racorr, deccorr)

        # Object X/Y position
        xobj, yobj = w.all_world2pix(obj['ra'], obj['dec'], 0)
        # Get the cutout
        xcen = meas['x'][ind2[i]] - 1  # convert to 0-indexes
        ycen = meas['y'][ind2[i]] - 1
        smim = dln.gsmooth(im, 2)
        # use the object coords for centering
        #cutim,xr,yr = cutout(smim,xobj,yobj,size)

        # Mask the bad pixels
        if domask == True:
            badmask = (mim > 0)
            im[badmask] = np.nanmedian(im[~badmask])
        else:
            badmask = (im < 0)

        # Create a common TAN WCS that each image gets interpoled onto!!!
        #hdu1 = fits.open(fluxfile[i],extname=extname)
        smim1 = dln.gsmooth(im, 1.5)
        hdu = fits.PrimaryHDU(smim1, head)
        cutim, footprint = reproject_interp(hdu, refheader,
                                            order='bicubic')  # biquadratic
        cutim[footprint == 0] = np.nanmedian(
            im[~badmask])  # set out-of-bounds to background
        #xr = [0,npix-1]
        #yr = [0,npix-1]
        xr = [-hpix * pixscale, hpix * pixscale]
        yr = [-hpix * pixscale, hpix * pixscale]

        # exposure_ccdnum, filter, MJD, delta_MJD, mag
        print(
            str(i + 1) + ' ' + meas['exposure'][ind2[i]] + ' ' +
            str(ccdnum[i]) + ' ' + str(meas['x'][ind2[i]]) + ' ' +
            str(meas['y'][ind2[i]]) + ' ' + str(meas['mag_auto'][ind2[i]]))

        #figdir = '/net/dl2/dnidever/nsc/instcal/v3/hpm2/cutouts/'
        figfile = outdir
        figfile += '%s_%04d_%s_%02d.jpg' % (str(
            obj['id'][0]), i + 1, meas['exposure'][ind2[i]], ccdnum[i])
        figfiles.append(figfile)
        matplotlib.use('Agg')
        plt.rc('font', size=15)
        plt.rc('axes', titlesize=20)
        plt.rc('axes', labelsize=20)
        plt.rc('xtick', labelsize=20)
        plt.rc('ytick', labelsize=20)
        #plt.rcParams.update({'font.size': 15})
        #plt.rcParams.update({'axes.size': 20})
        #plt.rcParams.update({'xtick.size': 20})
        #plt.rcParams.update({'ytick.size': 20})
        if os.path.exists(figfile): os.remove(figfile)
        fig = plt.gcf()  # get current graphics window
        fig.clf()  # clear

        gskw = dict(width_ratios=[30, 1])
        fig, ax = plt.subplots(ncols=2, nrows=1, gridspec_kw=gskw)

        figsize = 8.0  #6.0
        figheight = 8.0
        figwidth = 9.0
        #ax = fig.subplots()  # projection=wcs
        #fig.set_figheight(figsize*0.8)
        fig.set_figheight(figheight)
        fig.set_figwidth(figwidth)
        med = np.nanmedian(smim)
        sig = dln.mad(smim)
        bigim, xr2, yr2 = cutout(smim, xcen, ycen, 151, missing=med)
        lmed = np.nanmedian(bigim)

        # Get the flux of the object and scale each image to the same height
        #meas.mag_aper1 = cat1.mag_aper[0] + 2.5*alog10(exptime) + chstr[i].zpterm
        #cmag = mag_auto + 2.5*alog10(exptime) + zpterm
        instmag = meas['mag_auto'][ind2[i]] - 2.5 * np.log10(
            chres['exptime'][0]) - chres['zpterm'][0]
        #mag = -2.5*log(flux)+25.0
        instflux = 10**((25.0 - instmag) / 2.5)
        print('flux = ' + str(instflux))
        # Get height of object
        #  flux of 2D Gaussian is ~2*pi*height*sigma^2
        pixscale1 = np.max(np.abs(w.wcs.cd)) * 3600
        fwhm = chres['fwhm'][0] / pixscale1
        instheight = instflux / (2 * 3.14 * (fwhm / 2.35)**2)
        print('height = ' + str(instheight))
        # Scale the images to the flux level of the first image
        cutim -= lmed
        if i == 0:
            instflux0 = instflux.copy()
            instheight0 = instheight.copy()
        else:
            scale = instflux0 / instflux
            #scale = instheight0/instheight
            cutim *= scale
            print('scaling image by ' + str(scale))

        #vmin = lmed-8*sig  # 3*sig
        #vmax = lmed+12*sig  # 5*sig
        if i == 0:
            vmin = -8 * sig  # 3*sig
            #vmax = 12*sig  # 5*sig
            vmax = 0.5 * instheight  # 0.5
            vmin0 = vmin
            vmax0 = vmax
        else:
            vmin = vmin0
            vmax = vmax0

        print('vmin = ' + str(vmin))
        print('vmax = ' + str(vmax))

        cutimarr[:, :, i] = cutim.copy()

        ax[0].imshow(cutim,
                     origin='lower',
                     aspect='auto',
                     interpolation='none',
                     extent=(xr[0], xr[1], yr[0], yr[1]),
                     vmin=vmin,
                     vmax=vmax,
                     cmap='viridis')  # viridis, Greys, jet
        #plt.imshow(cutim,origin='lower',aspect='auto',interpolation='none',
        #           vmin=vmin,vmax=vmax,cmap='viridis')   # viridis, Greys, jet
        #plt.colorbar()

        # show one vertical, one horizontal line pointing to the center but offset
        # then a small dot on the meas position
        # 13, 8
        ax[0].plot(np.array([0, 0]),
                   np.array([-0.066 * npix, 0.066 * npix]) * pixscale,
                   c='white',
                   alpha=0.7)
        ax[0].plot(np.array([-0.066 * npix, 0.066 * npix]) * pixscale,
                   np.array([0, 0]),
                   c='white',
                   alpha=0.7)

        # Meas X/Y position
        xmeas1, ymeas1 = wref.all_world2pix(meas['ra'][ind2[i]],
                                            meas['dec'][ind2[i]], 0)
        xmeas.append(xmeas1)
        ymeas.append(ymeas1)
        ax[0].scatter([(xmeas1 - hpix) * pixscale],
                      [(ymeas1 - hpix) * pixscale],
                      c='r',
                      marker='+',
                      s=20)
        #plt.scatter([xmeas],[ymeas],c='r',marker='+',s=100)
        #plt.scatter([xcen],[ycen],c='r',marker='+',s=100)
        # Object X/Y position
        #xobj,yobj = w.all_world2pix(obj['ra'],obj['dec'],0)
        xobj, yobj = wref.all_world2pix(obj['ra'], obj['dec'], 0)
        #plt.scatter(xobj,yobj,marker='o',s=200,facecolors='none',edgecolors='y',linewidth=3)
        #plt.scatter(xobj,yobj,c='y',marker='+',s=100)
        #leg = ax.legend(loc='upper left', frameon=False)
        ax[0].set_xlabel(r'$\Delta$ RA (arcsec)')
        ax[0].set_ylabel(r'$\Delta$ DEC (arcsec)')
        ax[0].set_xlim((xr[1], xr[0]))  # sky right
        ax[0].set_ylim(yr)
        #plt.xlabel('X')
        #plt.ylabel('Y')
        #plt.xlim(xr)
        #plt.ylim(yr)
        #ax.annotate(r'S/N=%5.1f',xy=(np.mean(xr), yr[0]+dln.valrange(yr)*0.05),ha='center')
        co = 'white'  #'lightgray' # blue
        ax[0].annotate('%s  %02d  %s  %6.1f  ' %
                       (meas['exposure'][ind2[i]], ccdnum[i],
                        meas['filter'][ind2[i]], expstr['exptime'][ind1[i]]),
                       xy=(np.mean(xr), yr[0] + dln.valrange(yr) * 0.05),
                       ha='center',
                       color=co)
        ax[0].annotate(
            '%10.2f    $\Delta$t=%7.2f  ' %
            (meas['mjd'][ind2[i]], meas['mjd'][ind2[i]] - np.min(meas['mjd'])),
            xy=(xr[1] - dln.valrange(xr) * 0.05,
                yr[1] - dln.valrange(yr) * 0.05),
            ha='left',
            color=co)
        #               xy=(xr[0]+dln.valrange(xr)*0.05, yr[1]-dln.valrange(yr)*0.05),ha='left',color=co)
        ax[0].annotate('%s = %5.2f +/- %4.2f' %
                       (meas['filter'][ind2[i]], meas['mag_auto'][ind2[i]],
                        meas['magerr_auto'][ind2[i]]),
                       xy=(xr[0] + dln.valrange(xr) * 0.05,
                           yr[1] - dln.valrange(yr) * 0.05),
                       ha='right',
                       color=co)
        #               xy=(xr[1]-dln.valrange(xr)*0.05, yr[1]-dln.valrange(yr)*0.05),ha='right',color=co)

        # Progress bar
        frameratio = (i + 1) / float(nind)
        timeratio = (meas['mjd'][ind2[i]] -
                     np.min(meas['mjd'])) / dln.valrange(meas['mjd'])
        #ratio = frameratio
        ratio = timeratio
        print('ratio = ' + str(100 * ratio))
        barim = np.zeros((100, 100), int)
        ind = dln.limit(int(round(ratio * 100)), 1, 99)
        barim[:, 0:ind] = 1
        ax[1].imshow(barim.T, origin='lower', aspect='auto', cmap='Greys')
        ax[1].set_xlabel('%7.1f \n days' %
                         (meas['mjd'][ind2[i]] - np.min(meas['mjd'])))
        #ax[1].set_xlabel('%d/%d' % (i+1,nind))
        ax[1].set_title('%d/%d' % (i + 1, nind))
        ax[1].axes.xaxis.set_ticks([])
        #ax[1].axes.xaxis.set_visible(False)
        ax[1].axes.yaxis.set_visible(False)
        #ax[1].axis('off')
        right_side = ax[1].spines['right']
        right_side.set_visible(False)
        left_side = ax[1].spines['left']
        left_side.set_visible(False)
        top_side = ax[1].spines['top']
        top_side.set_visible(False)

        plt.savefig(figfile)
        print('Cutout written to ' + figfile)

        #import pdb; pdb.set_trace()

    avgim = np.sum(cutimarr, axis=2) / nind
    avgim *= instheight0 / np.max(avgim)
    medim = np.median(cutimarr, axis=2)

    # Make a single blank file at the end so you know it looped
    figfile = outdir
    figfile += '%s_%04d_%s.jpg' % (str(obj['id'][0]), i + 2, 'path')
    figfiles.append(figfile)
    matplotlib.use('Agg')
    if os.path.exists(figfile): os.remove(figfile)
    fig = plt.gcf()  # get current graphics window
    fig.clf()  # clear
    gskw = dict(width_ratios=[30, 1])
    fig, ax = plt.subplots(ncols=2, nrows=1, gridspec_kw=gskw)
    fig.set_figheight(figheight)
    fig.set_figwidth(figwidth)
    ax[0].imshow(avgim,
                 origin='lower',
                 aspect='auto',
                 interpolation='none',
                 extent=(xr[0], xr[1], yr[0], yr[1]),
                 vmin=vmin,
                 vmax=vmax,
                 cmap='viridis')  # viridis, Greys, jet
    ax[0].plot(np.array([0, 0]),
               np.array([-0.066 * npix, 0.066 * npix]) * pixscale,
               c='white',
               alpha=0.7,
               zorder=1)
    ax[0].plot(np.array([-0.066 * npix, 0.066 * npix]) * pixscale,
               np.array([0, 0]),
               c='white',
               alpha=0.7,
               zorder=1)
    xmeas = np.array(xmeas)
    ymeas = np.array(ymeas)
    ax[0].plot((xmeas - hpix) * pixscale, (ymeas - hpix) * pixscale, c='r')
    #plt.scatter((xmeas-hpix)*pixscale,(ymeas-hpix)*pixscale,c='r',marker='+',s=30)
    ax[0].set_xlabel(r'$\Delta$ RA (arcsec)')
    ax[0].set_ylabel(r'$\Delta$ DEC (arcsec)')
    ax[0].set_xlim((xr[1], xr[0]))  # sky -right
    ax[0].set_ylim(yr)
    ax[1].axis('off')
    plt.savefig(figfile)
    # Make four copies
    for j in np.arange(2, 11):
        #pathfile = figfile.replace('path1','path'+str(j))
        pathfile = figfile.replace('%04d' % (i + 2), '%04d' % (i + 1 + j))
        if os.path.exists(pathfile): os.remove(pathfile)
        shutil.copyfile(figfile, pathfile)
        figfiles.append(pathfile)

    # Make the animated gif
    animfile = outdir + str(objid) + '_cutouts.gif'
    if os.path.exists(animfile): os.remove(animfile)
    # put list of files in a separate file
    listfile = outdir + str(objid) + '_cutouts.lst'
    if os.path.exists(listfile): os.remove(listfile)
    dln.writelines(listfile, figfiles)
    delay = dln.scale(nind, [20, 1000], [20, 1])
    delay = int(np.round(dln.limit(delay, 1, 20)))
    print('delay = ' + str(delay))
    print('Creating animated gif ' + animfile)
    #ret = subprocess.run('convert -delay 100 '+figdir+str(objid)+'_*.jpg '+animfile,shell=True)
    #ret = subprocess.run('convert -delay 20 '+' '.join(figfiles)+' '+animfile,shell=True)
    ret = subprocess.run('convert @' + listfile + ' -delay ' + str(delay) +
                         ' ' + animfile,
                         shell=True)
    #import pdb; pdb.set_trace()
    dln.remove(figfiles)
Esempio n. 7
0
def meascutout(meas, obj, size=10, outdir='./'):
    """ Input the measurements and create cutouts. """

    expstr = fits.getdata(
        '/net/dl2/dnidever/nsc/instcal/v3/lists/nsc_v3_exposures.fits.gz', 1)
    #expstr = fits.getdata('/net/dl2/dnidever/nsc/instcal/v3/lists/nsc_v3_exposure.fits.gz',1)
    decam = Table.read('/home/dnidever/projects/delvered/data/decam.txt',
                       format='ascii')

    objid = obj['id'][0]

    # Sort by MJD
    si = np.argsort(meas['mjd'])
    meas = meas[si]

    ind1, ind2 = dln.match(expstr['base'], meas['exposure'])
    nind = len(ind1)
    if nind == 0:
        print('No matches')
        return
    # Sort by input meas catalog
    si = np.argsort(ind2)
    ind1 = ind1[si]
    ind2 = ind2[si]

    # Create the reference WCS
    wref = WCS(naxis=2)
    pixscale = 0.26  # DECam, "/pix
    npix = round(size / pixscale)
    if npix % 2 == 0:  # must be odd
        npix += 1
    hpix = npix // 2  # center of image
    wref.wcs.ctype = ['RA---TAN', 'DEC--TAN']
    wref.wcs.crval = [obj['ra'][0], obj['dec'][0]]
    wref.wcs.crpix = [npix // 2, npix // 2]
    wref.wcs.cd = np.array([[pixscale / 3600.0, 0.0], [0.0, pixscale / 3600]])
    wref.array_shape = (npix, npix)
    refheader = wref.to_header()
    refheader['NAXIS'] = 2
    refheader['NAXIS1'] = npix
    refheader['NAXIS2'] = npix

    # Load the data
    instrument = expstr['instrument'][ind1]
    fluxfile = expstr['file'][ind1]
    fluxfile = fluxfile.replace('/net/mss1/', '/mss1/')  # for thing/hulk
    maskfile = expstr['maskfile'][ind1]
    maskfile = maskfile.replace('/net/mss1/', '/mss1/')  # for thing/hulk
    ccdnum = meas['ccdnum'][ind2]
    figfiles = []
    for i in range(nind):
        try:
            if instrument[i] == 'c4d':
                dind, = np.where(decam['CCDNUM'] == ccdnum[i])
                extname = decam['NAME'][dind[0]]
                im, head = getfitsext(fluxfile[i], extname, header=True)
                mim, mhead = getfitsext(maskfile[i], extname, header=True)
                #im,head = fits.getdata(fluxfile[i],header=True,extname=extname)
                #mim,mhead = fits.getdata(maskfile[i],header=True,extname=extname)
            else:
                im, head = fits.getdata(fluxfile[i], ccdnum[i], header=True)
                mim, mhead = fits.getdata(maskfile[i], ccdnum[i], header=True)
        except:
            print('error')
            import pdb
            pdb.set_trace()

        # Get chip-level information
        exposure = os.path.basename(fluxfile[i])[0:-8]  # remove fits.fz
        chres = qc.query(sql="select * from nsc_dr2.chip where exposure='" +
                         exposure + "' and ccdnum=" + str(ccdnum[i]),
                         fmt='table')

        w = WCS(head)
        # RA/DEC correction for the object
        lon = obj['ra'][0] - chres['ra'][0]
        lat = obj['dec'][0] - chres['dec'][0]
        racorr = chres['ra_coef1'][0] + chres['ra_coef2'][0] * lon + chres[
            'ra_coef3'][0] * lon * lat + chres['ra_coef4'][0] * lat
        deccorr = chres['dec_coef1'][0] + chres['dec_coef2'][0] * lon + chres[
            'dec_coef3'][0] * lon * lat + chres['dec_coef4'][0] * lat
        # apply these offsets to the header WCS CRVAL
        w.wcs.crval += [racorr, deccorr]
        head['CRVAL1'] += racorr
        head['CRVAL2'] += deccorr

        # Object X/Y position
        xobj, yobj = w.all_world2pix(obj['ra'], obj['dec'], 0)
        # Get the cutout
        xcen = meas['x'][ind2[i]] - 1  # convert to 0-indexes
        ycen = meas['y'][ind2[i]] - 1
        smim = dln.gsmooth(im, 2)
        # use the object coords for centering
        #cutim,xr,yr = cutout(smim,xobj,yobj,size)

        # Mask the bad pixels
        badmask = (mim > 0)
        im[badmask] = np.nanmedian(im[~badmask])

        # Create a common TAN WCS that each image gets interpoled onto!!!
        #hdu1 = fits.open(fluxfile[i],extname=extname)
        smim1 = dln.gsmooth(im, 1.5)
        hdu = fits.PrimaryHDU(smim1, head)
        cutim, footprint = reproject_interp(hdu, refheader,
                                            order='bicubic')  # biquadratic
        cutim[footprint == 0] = np.nanmedian(
            im[~badmask])  # set out-of-bounds to background
        #xr = [0,npix-1]
        #yr = [0,npix-1]
        xr = [-hpix * pixscale, hpix * pixscale]
        yr = [-hpix * pixscale, hpix * pixscale]

        # exposure_ccdnum, filter, MJD, delta_MJD, mag
        print(
            str(i + 1) + ' ' + meas['exposure'][ind2[i]] + ' ' +
            str(ccdnum[i]) + ' ' + str(meas['x'][ind2[i]]) + ' ' +
            str(meas['y'][ind2[i]]) + ' ' + str(meas['mag_auto'][ind2[i]]))

        #figdir = '/net/dl2/dnidever/nsc/instcal/v3/hpm2/cutouts/'
        figfile = outdir
        figfile += '%s_%04d_%s_%02d.jpg' % (str(
            obj['id'][0]), i + 1, meas['exposure'][ind2[i]], ccdnum[i])
        figfiles.append(figfile)
        matplotlib.use('Agg')
        plt.rcParams.update({'font.size': 11})
        if os.path.exists(figfile): os.remove(figfile)
        fig = plt.gcf()  # get current graphics window
        fig.clf()  # clear

        figsize = 8.0  #6.0
        ax = fig.subplots()  # projection=wcs
        #fig.set_figheight(figsize*0.8)
        fig.set_figheight(figsize)
        fig.set_figwidth(figsize)
        med = np.nanmedian(smim)
        sig = dln.mad(smim)
        bigim, xr2, yr2 = cutout(smim, xcen, ycen, 151, missing=med)
        lmed = np.nanmedian(bigim)

        # Get the flux of the object and scale each image to the same height
        #meas.mag_aper1 = cat1.mag_aper[0] + 2.5*alog10(exptime) + chstr[i].zpterm
        #cmag = mag_auto + 2.5*alog10(exptime) + zpterm
        instmag = meas['mag_auto'][ind2[i]] - 2.5 * np.log10(
            chres['exptime'][0]) - chres['zpterm'][0]
        #mag = -2.5*log(flux)+25.0
        instflux = 10**((25.0 - instmag) / 2.5)
        print('flux = ' + str(instflux))
        # Get height of object
        #  flux of 2D Gaussian is ~2*pi*height*sigma^2
        pixscale1 = np.max(np.abs(w.wcs.cd)) * 3600
        fwhm = chres['fwhm'][0] / pixscale1
        instheight = instflux / (2 * 3.14 * (fwhm / 2.35)**2)
        print('height = ' + str(instheight))
        # Scale the images to the flux level of the first image
        cutim -= lmed
        if i == 0:
            instflux0 = instflux.copy()
            instheight0 = instheight.copy()
        else:
            scale = instflux0 / instflux
            #scale = instheight0/instheight
            cutim *= scale
            print('scaling image by ' + str(scale))

        #vmin = lmed-8*sig  # 3*sig
        #vmax = lmed+12*sig  # 5*sig
        if i == 0:
            vmin = -8 * sig  # 3*sig
            #vmax = 12*sig  # 5*sig
            vmax = 0.5 * instheight  # 0.5
            vmin0 = vmin
            vmax0 = vmax
        else:
            vmin = vmin0
            vmax = vmax0

        print('vmin = ' + str(vmin))
        print('vmax = ' + str(vmax))

        plt.imshow(cutim,
                   origin='lower',
                   aspect='auto',
                   interpolation='none',
                   extent=(xr[0], xr[1], yr[0], yr[1]),
                   vmin=vmin,
                   vmax=vmax,
                   cmap='viridis')  # viridis, Greys, jet
        #plt.imshow(cutim,origin='lower',aspect='auto',interpolation='none',
        #           vmin=vmin,vmax=vmax,cmap='viridis')   # viridis, Greys, jet
        #plt.colorbar()

        # show one vertical, one horizontal line pointing to the center but offset
        # then a small dot on the meas position
        # 13, 8
        plt.plot(np.array([0, 0]),
                 np.array([-0.066 * npix, 0.066 * npix]) * pixscale,
                 c='white',
                 alpha=0.7)
        plt.plot(np.array([-0.066 * npix, 0.066 * npix]) * pixscale,
                 np.array([0, 0]),
                 c='white',
                 alpha=0.7)

        # Meas X/Y position
        xmeas, ymeas = wref.all_world2pix(meas['ra'][ind2[i]],
                                          meas['dec'][ind2[i]], 0)
        plt.scatter([(xmeas - hpix) * pixscale], [(ymeas - hpix) * pixscale],
                    c='r',
                    marker='+',
                    s=20)
        #plt.scatter([xmeas],[ymeas],c='r',marker='+',s=100)
        #plt.scatter([xcen],[ycen],c='r',marker='+',s=100)
        # Object X/Y position
        #xobj,yobj = w.all_world2pix(obj['ra'],obj['dec'],0)
        xobj, yobj = wref.all_world2pix(obj['ra'], obj['dec'], 0)
        #plt.scatter(xobj,yobj,marker='o',s=200,facecolors='none',edgecolors='y',linewidth=3)
        #plt.scatter(xobj,yobj,c='y',marker='+',s=100)
        #leg = ax.legend(loc='upper left', frameon=False)
        plt.xlabel(r'$\Delta$ RA (arcsec)')
        plt.ylabel(r'$\Delta$ DEC (arcsec)')
        #plt.xlabel('X')
        #plt.ylabel('Y')
        #plt.xlim(xr)
        #plt.ylim(yr)
        #ax.annotate(r'S/N=%5.1f',xy=(np.mean(xr), yr[0]+dln.valrange(yr)*0.05),ha='center')
        co = 'white'  #'lightgray' # blue
        ax.annotate('%s  %02d  %s  %6.1f  ' %
                    (meas['exposure'][ind2[i]], ccdnum[i],
                     meas['filter'][ind2[i]], expstr['exptime'][ind1[i]]),
                    xy=(np.mean(xr), yr[0] + dln.valrange(yr) * 0.05),
                    ha='center',
                    color=co)
        ax.annotate(
            '%10.2f  %10.2f  ' %
            (meas['mjd'][ind2[i]], meas['mjd'][ind2[i]] - np.min(meas['mjd'])),
            xy=(xr[0] + dln.valrange(xr) * 0.05,
                yr[1] - dln.valrange(yr) * 0.05),
            ha='left',
            color=co)
        ax.annotate('%s = %5.2f +/- %4.2f' %
                    (meas['filter'][ind2[i]], meas['mag_auto'][ind2[i]],
                     meas['magerr_auto'][ind2[i]]),
                    xy=(xr[1] - dln.valrange(xr) * 0.05,
                        yr[1] - dln.valrange(yr) * 0.05),
                    ha='right',
                    color=co)
        plt.savefig(figfile)
        print('Cutout written to ' + figfile)

        #import pdb; pdb.set_trace()

    # Make a single blank file at the end so you know it looped
    figfile = outdir
    figfile += '%s_%04d_%s.jpg' % (str(obj['id'][0]), i + 2, 'blank')
    figfiles.append(figfile)
    matplotlib.use('Agg')
    if os.path.exists(figfile): os.remove(figfile)
    fig = plt.gcf()  # get current graphics window
    fig.clf()  # clear
    figsize = 8.0  #6.0
    fig.set_figheight(figsize)
    fig.set_figwidth(figsize)
    plt.savefig(figfile)
    print(figfile)

    # Make the animated gif
    animfile = outdir + str(objid) + '_cutouts.gif'
    print('Creating animated gif ' + animfile)
    if os.path.exists(animfile): os.remove(animfile)
    #ret = subprocess.run('convert -delay 100 '+figdir+str(objid)+'_*.jpg '+animfile,shell=True)
    ret = subprocess.run('convert -delay 20 ' + ' '.join(figfiles) + ' ' +
                         animfile,
                         shell=True)
    #import pdb; pdb.set_trace()
    dln.remove(figfiles)