Пример #1
0
    def MasterWave(self, fitsdict, det):
        """
        Generate Master Wave frame for a given detector

        Parameters
        ----------
        fitsdict : dict
          Contains relevant information from fits header files
        det : int
          Index of the detector

        Returns
        -------
        boolean : bool
          Should other ScienceExposure classes be updated?
        """

        if self._mswave[det - 1] is not None:
            msgs.info("An identical master arc frame already exists")
            return False
        if self._argflag['reduce']['usewave'] in ['wave']:
            msgs.info("Preparing a master wave frame")
            mswave = arutils.func_val(self._wvcalib[det - 1]['fitc'],
                                      self._tilts[det - 1],
                                      self._wvcalib[det - 1]['function'],
                                      minv=self._wvcalib[det - 1]['fmin'],
                                      maxv=self._wvcalib[det - 1]['fmax'])
        else:  # It must be the name of a file the user wishes to load
            mswave_name = self._argflag['run'][
                'masterdir'] + '/' + self._argflag['reduce']['usewave']
            mswave = arload.load_master(mswave_name, frametype=None)
        # Set and then delete the Master Arc frame
        self.SetMasterFrame(mswave, "wave", det)
        del mswave
        return True
Пример #2
0
def extrapolate(outpar, ords, function='polynomial'):
    nords = ords.size

    x0ex = arutils.func_val(outpar['x0res'], ords, function,
                            minv=outpar['x0in'][0], maxv=outpar['x0in'][-1])

    # Order centre
    high_matr = np.zeros((nords, outpar['npc']))
    for i in xrange(1, outpar['npc']+1):
        if outpar['coeffstr'][i-1][0] == -9.99E9:
            high_matr[:,i-1] = np.ones(nords)*outpar['high_fit'][0,i-1]
            continue
        high_matr[:,i-1] = arutils.func_val(outpar['coeffstr'][i-1], ords, function,
                                            minv=outpar['x0in'][0], maxv=outpar['x0in'][-1])
    extfit = np.dot(outpar['eigv'], high_matr.T) + np.outer(x0ex, np.ones(outpar['eigv'].shape[0])).T
    outpar['high_matr'] = high_matr
    return extfit, outpar
Пример #3
0
def refine_iter(outpar, orders, mask, irshft, relshift, fitord, function='polynomial'):
    fail = False
    x0ex = arutils.func_val(outpar['x0res'], orders, function,  minv=outpar['x0in'][0], maxv=outpar['x0in'][-1])
    # Make the refinement
    x0ex[irshft] += relshift
    # Refit the data to improve the refinement
    good = np.where(mask != 0.0)[0]
#	x0res = arutils.robust_regression(x0in[good],x0[good],pnpc[0],0.2,function=function)
    null, x0res = arutils.robust_polyfit(orders[good], x0ex[good], fitord, sigma=2.0, function=function,
                                         minv=outpar['x0in'][0], maxv=outpar['x0in'][-1])
    #x0res = arutils.func_fit(orders[good], x0ex[good], function, fitord, min=outpar['x0in'][0], max=outpar['x0in'][-1])
    x0fit = arutils.func_val(x0res, orders, function, minv=outpar['x0in'][0], maxv=outpar['x0in'][-1])
    chisq = (x0ex[good]-x0fit[good])**2.0
    chisqnu = np.sum(chisq)/np.sum(mask)
    msgs.prindent("  Reduced chi-squared = {0:E}".format(chisqnu))
    if chisqnu > 0.5: # The refinement went wrong, ignore the refinement
        fail = True
    outpar['x0res'] = x0res
    extfit = np.dot(outpar['eigv'], outpar['high_matr'].T) + np.outer(x0fit, np.ones(outpar['eigv'].shape[0])).T
    return extfit, outpar, fail
Пример #4
0
def refine_iter(outpar,
                orders,
                mask,
                irshft,
                relshift,
                fitord,
                function='polynomial'):
    fail = False
    x0ex = arutils.func_val(outpar['x0res'],
                            orders,
                            function,
                            minv=outpar['x0in'][0],
                            maxv=outpar['x0in'][-1])
    # Make the refinement
    x0ex[irshft] += relshift
    # Refit the data to improve the refinement
    good = np.where(mask != 0.0)[0]
    #	x0res = arutils.robust_regression(x0in[good],x0[good],pnpc[0],0.2,function=function)
    null, x0res = arutils.robust_polyfit(orders[good],
                                         x0ex[good],
                                         fitord,
                                         sigma=2.0,
                                         function=function,
                                         minv=outpar['x0in'][0],
                                         maxv=outpar['x0in'][-1])
    #x0res = arutils.func_fit(orders[good], x0ex[good], function, fitord, min=outpar['x0in'][0], max=outpar['x0in'][-1])
    x0fit = arutils.func_val(x0res,
                             orders,
                             function,
                             minv=outpar['x0in'][0],
                             maxv=outpar['x0in'][-1])
    chisq = (x0ex[good] - x0fit[good])**2.0
    chisqnu = np.sum(chisq) / np.sum(mask)
    msgs.prindent("  Reduced chi-squared = {0:E}".format(chisqnu))
    if chisqnu > 0.5:  # The refinement went wrong, ignore the refinement
        fail = True
    outpar['x0res'] = x0res
    extfit = np.dot(outpar['eigv'], outpar['high_matr'].T) + np.outer(
        x0fit, np.ones(outpar['eigv'].shape[0])).T
    return extfit, outpar, fail
Пример #5
0
def extrapolate(outpar, ords, function='polynomial'):
    nords = ords.size

    x0ex = arutils.func_val(outpar['x0res'],
                            ords,
                            function,
                            minv=outpar['x0in'][0],
                            maxv=outpar['x0in'][-1])

    # Order centre
    high_matr = np.zeros((nords, outpar['npc']))
    for i in xrange(1, outpar['npc'] + 1):
        if outpar['coeffstr'][i - 1][0] == -9.99E9:
            high_matr[:, i - 1] = np.ones(nords) * outpar['high_fit'][0, i - 1]
            continue
        high_matr[:, i - 1] = arutils.func_val(outpar['coeffstr'][i - 1],
                                               ords,
                                               function,
                                               minv=outpar['x0in'][0],
                                               maxv=outpar['x0in'][-1])
    extfit = np.dot(outpar['eigv'], high_matr.T) + np.outer(
        x0ex, np.ones(outpar['eigv'].shape[0])).T
    outpar['high_matr'] = high_matr
    return extfit, outpar
Пример #6
0
def apply_sensfunc(slf, scidx, fitsdict, MAX_EXTRAP=0.05):
    """
    Apply the sensitivity function to the data
    We also correct for extinction.

    Parameters
    ----------
    MAX_EXTRAP : float, optional [0.05]
      Fractional amount to extrapolate sensitivity function
    """

    # Load extinction data
    extinct = load_extinction_data(slf)
    airmass = fitsdict['airmass'][scidx]
    # Loop on objects
    for spobj in slf._specobjs:
        # Loop on extraction modes
        for extract_type in ['boxcar']:
            try:
                extract = getattr(spobj, extract_type)
            except AttributeError:
                continue
            msgs.info("Fluxing {:s} extraction".format(extract_type))
            wave = extract['wave']  # for convenience
            scale = np.zeros(wave.size)
            # Allow for some extrapolation
            dwv = slf._sensfunc['wave_max'] - slf._sensfunc['wave_min']
            inds = ((wave >= slf._sensfunc['wave_min'] - dwv * MAX_EXTRAP)
                    & (wave <= slf._sensfunc['wave_max'] + dwv * MAX_EXTRAP))
            mag_func = arutils.func_val(slf._sensfunc['c'], wave[inds],
                                        slf._sensfunc['func'])
            sens = 10.0**(0.4 * mag_func)
            # Extinction
            ext_corr = extinction_correction(wave[inds], airmass, extinct)
            scale[inds] = sens * ext_corr
            # Fill
            extract['flam'] = extract['counts'] * scale / slf._fitsdict[
                'exptime'][scidx]
            extract['flam_var'] = (
                extract['var'] * (scale / slf._fitsdict['exptime'][scidx])**2)
Пример #7
0
def apply_sensfunc(slf, scidx, fitsdict, MAX_EXTRAP=0.05):
    """
    Apply the sensitivity function to the data
    We also correct for extinction.

    Parameters
    ----------
    MAX_EXTRAP : float, optional [0.05]
      Fractional amount to extrapolate sensitivity function
    """

    # Load extinction data
    extinct = load_extinction_data(slf)
    airmass = fitsdict['airmass'][scidx]
    # Loop on objects
    for spobj in slf._specobjs:
        # Loop on extraction modes
        for extract_type in ['boxcar']:
            try:
                extract = getattr(spobj,extract_type)
            except AttributeError:
                continue
            msgs.info("Fluxing {:s} extraction".format(extract_type))
            wave = extract['wave'] # for convenience
            scale = np.zeros(wave.size)
            # Allow for some extrapolation 
            dwv = slf._sensfunc['wave_max']-slf._sensfunc['wave_min']
            inds = ((wave >= slf._sensfunc['wave_min']-dwv*MAX_EXTRAP)
                    & (wave <= slf._sensfunc['wave_max']+dwv*MAX_EXTRAP))
            mag_func = arutils.func_val(slf._sensfunc['c'], wave[inds],
                                        slf._sensfunc['func'])
            sens = 10.0**(0.4*mag_func)
            # Extinction
            ext_corr = extinction_correction(wave[inds],airmass,extinct)
            scale[inds] = sens*ext_corr
            # Fill
            extract['flam'] = extract['counts']*scale/slf._fitsdict['exptime'][scidx]
            extract['flam_var'] = (extract['var']*
                                   (scale/slf._fitsdict['exptime'][scidx])**2)
Пример #8
0
def arc_fit_qa(slf, fit, arc_spec, outfil=None):
    """
    QA for Arc spectrum

    Parameters
    ----------
    fit : Wavelength fit
    arc_spec : ndarray
      Arc spectrum
    outfil : str, optional
      Name of output file
    """
    if outfil is not None:
        msgs.error("Not ready for this anymore")

    # Begin
    plt.figure(figsize=(8, 4.0))
    plt.clf()
    gs = gridspec.GridSpec(2, 2)

    # Simple spectrum plot
    ax_spec = plt.subplot(gs[:, 0])
    ax_spec.plot(np.arange(len(arc_spec)), arc_spec)
    ymin, ymax = 0., np.max(arc_spec)
    ysep = ymax * 0.03
    for kk, x in enumerate(fit['xfit'] * fit['xnorm']):
        yline = np.max(arc_spec[int(x) - 2:int(x) + 2])
        # Tick mark
        ax_spec.plot([x, x], [yline + ysep * 0.25, yline + ysep], 'g-')
        # label
        ax_spec.text(x,
                     yline + ysep * 1.3,
                     '{:s} {:g}'.format(fit['ions'][kk], fit['yfit'][kk]),
                     ha='center',
                     va='bottom',
                     size='xx-small',
                     rotation=90.,
                     color='green')
    ax_spec.set_xlim(0., len(arc_spec))
    ax_spec.set_ylim(ymin, ymax * 1.2)
    ax_spec.set_xlabel('Pixel')
    ax_spec.set_ylabel('Flux')

    # Arc Fit
    ax_fit = plt.subplot(gs[0, 1])
    # Points
    ax_fit.scatter(fit['xfit'] * fit['xnorm'], fit['yfit'], marker='x')
    if len(fit['xrej']) > 0:
        ax_fit.scatter(fit['xrej'] * fit['xnorm'],
                       fit['yrej'],
                       marker='o',
                       edgecolor='gray',
                       facecolor='none')
    # Solution
    xval = np.arange(len(arc_spec))
    wave = arutils.func_val(fit['fitc'],
                            xval / fit['xnorm'],
                            'legendre',
                            minv=fit['fmin'],
                            maxv=fit['fmax'])
    ax_fit.plot(xval, wave, 'r-')
    xmin, xmax = 0., len(arc_spec)
    ax_fit.set_xlim(xmin, xmax)
    ymin, ymax = np.min(wave) * .95, np.max(wave) * 1.05
    ax_fit.set_ylim(np.min(wave) * .95, np.max(wave) * 1.05)
    ax_fit.set_ylabel('Wavelength')
    ax_fit.get_xaxis().set_ticks([])  # Suppress labeling
    # Stats
    wave_fit = arutils.func_val(fit['fitc'],
                                fit['xfit'],
                                'legendre',
                                minv=fit['fmin'],
                                maxv=fit['fmax'])
    dwv_pix = np.median(np.abs(wave - np.roll(wave, 1)))
    rms = np.sqrt(np.sum(
        (fit['yfit'] - wave_fit)**2) / len(fit['xfit']))  # Ang
    ax_fit.text(0.1 * len(arc_spec),
                0.90 * ymin + (ymax - ymin),
                r'$\Delta\lambda$={:.3f}$\AA$ (per pix)'.format(dwv_pix),
                size='small')
    ax_fit.text(0.1 * len(arc_spec),
                0.80 * ymin + (ymax - ymin),
                'RMS={:.3f} (pixels)'.format(rms / dwv_pix),
                size='small')
    # Arc Residuals
    ax_res = plt.subplot(gs[1, 1])
    res = fit['yfit'] - wave_fit
    ax_res.scatter(fit['xfit'] * fit['xnorm'], res / dwv_pix, marker='x')
    ax_res.plot([xmin, xmax], [0., 0], 'k--')
    ax_res.set_xlim(xmin, xmax)
    ax_res.set_xlabel('Pixel')
    ax_res.set_ylabel('Residuals (Pix)')

    # Finish
    plt.tight_layout(pad=0.2, h_pad=0.0, w_pad=0.0)
    slf._qa.savefig(bbox_inches='tight')
    plt.close()
    return
Пример #9
0
def basis(xfit,
          yfit,
          coeff,
          npc,
          pnpc,
          weights=None,
          skipx0=True,
          x0in=None,
          mask=None,
          function='polynomial',
          retmask=False):
    nrow = xfit.shape[0]
    ntrace = xfit.shape[1]
    if x0in is None:
        x0in = np.arange(float(ntrace))

    # Mask out some orders if they are bad
    if mask is None or mask.size == 0:
        usetrace = np.arange(ntrace)
        outmask = np.ones((nrow, ntrace))
    else:
        usetrace = np.where(np.in1d(np.arange(ntrace), mask) == False)[0]
        outmask = np.ones((nrow, ntrace))
        outmask[:, mask] = 0.0

    # Do the PCA analysis
    eigc, hidden = get_pc(coeff[1:npc + 1, usetrace], npc)

    modl = arutils.func_vander(xfit[:, 0], function, npc)
    eigv = np.dot(modl[:, 1:], eigc)

    med_hidden = np.median(hidden, axis=1)
    med_highorder = med_hidden.copy()
    med_highorder[0] = 0

    high_order_matrix = med_highorder.T[np.newaxis, :].repeat(ntrace, axis=0)

    # y = hidden[0,:]
    # coeff0 = arutils.robust_regression(x0in[usetrace], y, pnpc[1], 0.1, function=function)

    # y = hidden[1,:]
    # coeff1 = arutils.robust_regression(x0in[usetrace], y, pnpc[2], 0.1, function=function)

    coeffstr = []
    for i in xrange(1, npc + 1):
        # if pnpc[i] == 0:
        #     coeffstr.append([-9.99E9])
        #     continue
        # coeff0 = arutils.robust_regression(x0in[usetrace], hidden[i-1,:], pnpc[i], 0.1, function=function, min=x0in[0], max=x0in[-1])
        if weights is not None:
            tmask, coeff0 = arutils.robust_polyfit(x0in[usetrace],
                                                   hidden[i - 1, :],
                                                   pnpc[i],
                                                   weights=weights[usetrace],
                                                   sigma=2.0,
                                                   function=function,
                                                   minv=x0in[0],
                                                   maxv=x0in[-1])
        else:
            tmask, coeff0 = arutils.robust_polyfit(x0in[usetrace],
                                                   hidden[i - 1, :],
                                                   pnpc[i],
                                                   sigma=2.0,
                                                   function=function,
                                                   minv=x0in[0],
                                                   maxv=x0in[-1])
        coeffstr.append(coeff0)
        high_order_matrix[:, i - 1] = arutils.func_val(coeff0,
                                                       x0in,
                                                       function,
                                                       minv=x0in[0],
                                                       maxv=x0in[-1])
    # high_order_matrix[:,1] = arutils.func_val(coeff1, x0in, function)
    high_fit = high_order_matrix.copy()

    high_order_fit = np.dot(eigv, high_order_matrix.T)
    sub = (yfit - high_order_fit) * outmask

    numer = np.sum(sub, axis=0)
    denom = np.sum(outmask, axis=0)
    x0 = np.zeros(float(ntrace))
    fitmask = np.zeros(float(ntrace))
    #fitmask[mask] = 1
    x0fit = np.zeros(float(ntrace))
    chisqnu = 0.0
    chisqold = 0.0
    robust = True
    #svx0 = numer/(denom+(denom == 0).astype(np.int))
    if not skipx0:
        fitmask = (np.abs(denom) > 10).astype(np.int)
        if robust:
            good = np.where(fitmask != 0)[0]
            bad = np.where(fitmask == 0)[0]
            x0[good] = numer[good] / denom[good]
            imask = np.zeros(float(ntrace))
            imask[bad] = 1.0
            ttmask, x0res = arutils.robust_polyfit(x0in,
                                                   x0,
                                                   pnpc[0],
                                                   weights=weights,
                                                   sigma=2.0,
                                                   function=function,
                                                   minv=x0in[0],
                                                   maxv=x0in[-1],
                                                   initialmask=imask)
            x0fit = arutils.func_val(x0res,
                                     x0in,
                                     function,
                                     minv=x0in[0],
                                     maxv=x0in[-1])
            good = np.where(ttmask == 0)[0]
            xstd = 1.0  # This should represent the dispersion in the fit
            chisq = ((x0[good] - x0fit[good]) / xstd)**2.0
            chisqnu = np.sum(chisq) / np.sum(ttmask)
            fitmask = 1.0 - ttmask
            msgs.prindent("  Reduced chi-squared = {0:E}".format(chisqnu))
        else:
            for i in xrange(1, 5):
                good = np.where(fitmask != 0)[0]
                x0[good] = numer[good] / denom[good]
                #				x0res = arutils.robust_regression(x0in[good],x0[good],pnpc[0],0.2,function=function)
                x0res = arutils.func_fit(x0in[good],
                                         x0[good],
                                         function,
                                         pnpc[0],
                                         weights=weights,
                                         minv=x0in[0],
                                         maxv=x0in[-1])
                x0fit = arutils.func_val(x0res,
                                         x0in,
                                         function,
                                         minv=x0in[0],
                                         maxv=x0in[-1])
                chisq = (x0[good] - x0fit[good])**2.0
                fitmask[good] *= (chisq < np.sum(chisq) / 2.0).astype(np.int)
                chisqnu = np.sum(chisq) / np.sum(fitmask)
                msgs.prindent("  Reduced chi-squared = {0:E}".format(chisqnu))
                if chisqnu == chisqold:
                    break
                else:
                    chisqold = chisqnu
        if chisqnu > 2.0:
            msgs.warn("PCA has very large residuals")
        elif chisqnu > 0.5:
            msgs.warn("PCA has fairly large residuals")
        #bad = np.where(fitmask==0)[0]
        #x0[bad] = x0fit[bad]
    else:
        x0res = 0.0
    x3fit = np.dot(eigv, high_order_matrix.T) + np.outer(x0fit,
                                                         np.ones(nrow)).T
    outpar = dict({
        'high_fit': high_fit,
        'x0': x0,
        'x0in': x0in,
        'x0fit': x0fit,
        'x0res': x0res,
        'x0mask': fitmask,
        'hidden': hidden,
        'usetrc': usetrace,
        'eigv': eigv,
        'npc': npc,
        'coeffstr': coeffstr
    })
    if retmask:
        return x3fit, outpar, tmask
    else:
        return x3fit, outpar
Пример #10
0
def bspline_magfit(wave, flux, var, flux_std, nointerp=False, **kwargs):
    """
    Perform a bspline fit to the flux ratio of standard to
    observed counts.  Used to generate a sensitivity function.

    Parameters
    ----------
    wave : ndarray
    flux : ndarray
      counts/s as observed
    var : ndarray
      variance
    flux_std : Quantity array
      standard star true flux (erg/s/cm^2/A)
    nointer : bool, optional [False]
      Skip interpolation over bad points (not recommended)?
    **kwargs : keywords for robust_polyfit

    Returns
    -------
    """
    invvar = (var > 0.)/(var + (var <= 0.))
    nx = wave.size
    pos_error = 1./np.sqrt(np.maximum(invvar,0.) + (invvar == 0))
    pos_mask = (flux > pos_error/10.0) & (invvar > 0) & (flux_std > 0.0)
    #pos = pos_mask==1 npos)

    fluxlog = 2.5*np.log10(np.maximum(flux,pos_error/10))
    logivar = invvar * flux**2 * pos_mask*1.08574

    # cap the magfunc so that sensfunc < 1.0e10
    magfunc = 2.5*np.log10(np.maximum(flux_std,1.0e-2)) - fluxlog
    magfunc = np.minimum(magfunc,25.0)
    sensfunc = 10.0**(0.4*magfunc)*pos_mask

    # Interpolate over masked pixels
    if not nointerp:
        bad = logivar <= 0. 
        if np.sum(bad) > 0:
            f = scipy.interpolate.InterpolatedUnivariateSpline(wave[~bad], magfunc[~bad], k=2)
            magfunc[bad] = f(wave[bad])
            fi = scipy.interpolate.InterpolatedUnivariateSpline(wave[~bad], logivar[~bad], k=2)
            logivar[bad] = fi(wave[bad])

    #  First iteration
    mask, tck = arutils.robust_polyfit(wave, magfunc, 3, function='bspline', weights=np.sqrt(logivar), **kwargs)
    logfit1 = arutils.func_val(tck,wave,'bspline')
    modelfit1 = 10.0**(0.4*(logfit1))

    residual = sensfunc/(modelfit1 + (modelfit1 == 0)) - 1.
    new_mask = pos_mask & (sensfunc > 0)
    residual_ivar = (modelfit1*flux/(sensfunc + (sensfunc == 0.0)))**2*invvar
    residual_ivar = residual_ivar*new_mask

    # Interpolate over masked pixels
    if not nointerp:
        if np.sum(bad) > 0:
            f = scipy.interpolate.InterpolatedUnivariateSpline(wave[~bad], residual[~bad], k=2)
            residual[bad] = f(wave[bad])
            fi = scipy.interpolate.InterpolatedUnivariateSpline(wave[~bad], residual_ivar[~bad], k=2)
            residual_ivar[bad] = fi(wave[bad])

    #  Now do one more fit to the ratio of data/model - 1.
    # Fuss with the knots first ()
    inner_knots = arutils.bspline_inner_knots(tck[0])
    #
    mask, tck_residual = arutils.robust_polyfit(wave, residual, 3, function='bspline', weights=np.sqrt(residual_ivar), knots=inner_knots, **kwargs)
    if tck_residual[1].size != tck[1].size:
        msgs.error('Problem with bspline knots in bspline_magfit')
    #bset_residual = bspline_iterfit(wave, residual, weights=np.sqrt(residual_ivar), knots = tck[0])

    tck_log1 = list(tck)
    tck_log1[1] = tck[1] + tck_residual[1]

    sensfit = 10.0**(0.4*(arutils.func_val(tck_log1,wave, 'bspline')))

    absdev = np.median(np.abs(sensfit/modelfit1-1))
    msgs.info('Difference between fits is {:g}'.format(absdev))

    # QA
    msgs.work("Add QA for sensitivity function")

    return tck_log1
Пример #11
0
def arc_fit_qa(slf, fit, arc_spec, outfil=None):
    """
    QA for Arc spectrum

    Parameters
    ----------
    fit : Wavelength fit
    arc_spec : ndarray
      Arc spectrum
    outfil : str, optional
      Name of output file
    """
    if outfil is not None:
        msgs.error("Not ready for this anymore")

    # Begin
    plt.figure(figsize=(8, 4.0))
    plt.clf()
    gs = gridspec.GridSpec(2, 2)

    # Simple spectrum plot
    ax_spec = plt.subplot(gs[:,0])
    ax_spec.plot(np.arange(len(arc_spec)), arc_spec)
    ymin, ymax = 0., np.max(arc_spec)
    ysep = ymax*0.03
    for kk, x in enumerate(fit['xfit']*fit['xnorm']):
        yline = np.max(arc_spec[int(x)-2:int(x)+2])
        # Tick mark
        ax_spec.plot([x,x], [yline+ysep*0.25, yline+ysep], 'g-')
        # label
        ax_spec.text(x, yline+ysep*1.3, 
            '{:s} {:g}'.format(fit['ions'][kk], fit['yfit'][kk]), ha='center', va='bottom',
            size='xx-small', rotation=90., color='green')
    ax_spec.set_xlim(0., len(arc_spec))
    ax_spec.set_ylim(ymin, ymax*1.2)
    ax_spec.set_xlabel('Pixel')
    ax_spec.set_ylabel('Flux')

    # Arc Fit
    ax_fit = plt.subplot(gs[0, 1])
    # Points
    ax_fit.scatter(fit['xfit']*fit['xnorm'], fit['yfit'], marker='x')
    if len(fit['xrej']) > 0:
        ax_fit.scatter(fit['xrej']*fit['xnorm'], fit['yrej'], marker='o',
            edgecolor='gray', facecolor='none')
    # Solution
    xval = np.arange(len(arc_spec))
    wave = arutils.func_val(fit['fitc'], xval/fit['xnorm'], 'legendre', 
        minv=fit['fmin'], maxv=fit['fmax'])
    ax_fit.plot(xval, wave, 'r-')
    xmin, xmax = 0., len(arc_spec)
    ax_fit.set_xlim(xmin, xmax)
    ymin,ymax = np.min(wave)*.95,  np.max(wave)*1.05
    ax_fit.set_ylim(np.min(wave)*.95,  np.max(wave)*1.05)
    ax_fit.set_ylabel('Wavelength')
    ax_fit.get_xaxis().set_ticks([]) # Suppress labeling
    # Stats
    wave_fit = arutils.func_val(fit['fitc'], fit['xfit'], 'legendre', 
        minv=fit['fmin'], maxv=fit['fmax'])
    dwv_pix = np.median(np.abs(wave-np.roll(wave,1)))
    rms = np.sqrt(np.sum((fit['yfit']-wave_fit)**2)/len(fit['xfit'])) # Ang
    ax_fit.text(0.1*len(arc_spec), 0.90*ymin+(ymax-ymin),
        r'$\Delta\lambda$={:.3f}$\AA$ (per pix)'.format(dwv_pix), size='small')
    ax_fit.text(0.1*len(arc_spec), 0.80*ymin+(ymax-ymin),
        'RMS={:.3f} (pixels)'.format(rms/dwv_pix), size='small')
    # Arc Residuals
    ax_res = plt.subplot(gs[1,1])
    res = fit['yfit']-wave_fit
    ax_res.scatter(fit['xfit']*fit['xnorm'], res/dwv_pix, marker='x')
    ax_res.plot([xmin,xmax], [0.,0], 'k--')
    ax_res.set_xlim(xmin, xmax)
    ax_res.set_xlabel('Pixel')
    ax_res.set_ylabel('Residuals (Pix)')

    # Finish
    plt.tight_layout(pad=0.2, h_pad=0.0, w_pad=0.0)
    slf._qa.savefig(bbox_inches='tight')
    plt.close()
    return
Пример #12
0
def basis(xfit, yfit, coeff, npc, pnpc, weights=None, skipx0=True, x0in=None, mask=None, function='polynomial', retmask=False):
    nrow = xfit.shape[0]
    ntrace = xfit.shape[1]
    if x0in is None:
        x0in = np.arange(float(ntrace))

    # Mask out some orders if they are bad
    if mask is None or mask.size == 0:
        usetrace = np.arange(ntrace)
        outmask = np.ones((nrow, ntrace))
    else:
        usetrace = np.where(np.in1d(np.arange(ntrace), mask) == False)[0]
        outmask = np.ones((nrow, ntrace))
        outmask[:,mask] = 0.0

    # Do the PCA analysis
    eigc, hidden = get_pc(coeff[1:npc+1, usetrace], npc)

    modl = arutils.func_vander(xfit[:,0], function, npc)
    eigv = np.dot(modl[:,1:], eigc)

    med_hidden = np.median(hidden, axis=1)
    med_highorder = med_hidden.copy()
    med_highorder[0] = 0

    high_order_matrix = med_highorder.T[np.newaxis,:].repeat(ntrace, axis=0)

    # y = hidden[0,:]
    # coeff0 = arutils.robust_regression(x0in[usetrace], y, pnpc[1], 0.1, function=function)

    # y = hidden[1,:]
    # coeff1 = arutils.robust_regression(x0in[usetrace], y, pnpc[2], 0.1, function=function)

    coeffstr = []
    for i in xrange(1, npc+1):
        # if pnpc[i] == 0:
        #     coeffstr.append([-9.99E9])
        #     continue
        # coeff0 = arutils.robust_regression(x0in[usetrace], hidden[i-1,:], pnpc[i], 0.1, function=function, min=x0in[0], max=x0in[-1])
        if weights is not None:
            tmask, coeff0 = arutils.robust_polyfit(x0in[usetrace], hidden[i-1,:], pnpc[i],
                                                   weights=weights[usetrace], sigma=2.0, function=function,
                                                   minv=x0in[0], maxv=x0in[-1])
        else:
            tmask, coeff0 = arutils.robust_polyfit(x0in[usetrace], hidden[i-1,:], pnpc[i],
                                                   sigma=2.0, function=function, minv=x0in[0], maxv=x0in[-1])
        coeffstr.append(coeff0)
        high_order_matrix[:,i-1] = arutils.func_val(coeff0, x0in, function, minv=x0in[0], maxv=x0in[-1])
    # high_order_matrix[:,1] = arutils.func_val(coeff1, x0in, function)
    high_fit = high_order_matrix.copy()

    high_order_fit = np.dot(eigv, high_order_matrix.T)
    sub = (yfit - high_order_fit) * outmask

    numer = np.sum(sub, axis=0)
    denom = np.sum(outmask, axis=0)
    x0 = np.zeros(float(ntrace))
    fitmask = np.zeros(float(ntrace))
    #fitmask[mask] = 1
    x0fit = np.zeros(float(ntrace))
    chisqnu = 0.0
    chisqold = 0.0
    robust = True
    #svx0 = numer/(denom+(denom == 0).astype(np.int))
    if not skipx0:
        fitmask = (np.abs(denom) > 10).astype(np.int)
        if robust:
            good = np.where(fitmask != 0)[0]
            bad = np.where(fitmask == 0)[0]
            x0[good] = numer[good]/denom[good]
            imask = np.zeros(float(ntrace))
            imask[bad] = 1.0
            ttmask, x0res = arutils.robust_polyfit(x0in, x0, pnpc[0], weights=weights, sigma=2.0,
                                                   function=function, minv=x0in[0], maxv=x0in[-1], initialmask=imask)
            x0fit = arutils.func_val(x0res, x0in, function, minv=x0in[0], maxv=x0in[-1])
            good = np.where(ttmask == 0)[0]
            xstd = 1.0  # This should represent the dispersion in the fit
            chisq = ((x0[good]-x0fit[good])/xstd)**2.0
            chisqnu = np.sum(chisq)/np.sum(ttmask)
            fitmask = 1.0-ttmask
            msgs.prindent("  Reduced chi-squared = {0:E}".format(chisqnu))
        else:
            for i in xrange(1, 5):
                good = np.where(fitmask != 0)[0]
                x0[good] = numer[good]/denom[good]
#				x0res = arutils.robust_regression(x0in[good],x0[good],pnpc[0],0.2,function=function)
                x0res = arutils.func_fit(x0in[good], x0[good], function, pnpc[0],
                                         weights=weights, minv=x0in[0], maxv=x0in[-1])
                x0fit = arutils.func_val(x0res, x0in, function, minv=x0in[0], maxv=x0in[-1])
                chisq = (x0[good]-x0fit[good])**2.0
                fitmask[good] *= (chisq < np.sum(chisq)/2.0).astype(np.int)
                chisqnu = np.sum(chisq)/np.sum(fitmask)
                msgs.prindent("  Reduced chi-squared = {0:E}".format(chisqnu))
                if chisqnu == chisqold:
                    break
                else:
                    chisqold = chisqnu
        if chisqnu > 2.0:
            msgs.warn("PCA has very large residuals")
        elif chisqnu > 0.5:
            msgs.warn("PCA has fairly large residuals")
        #bad = np.where(fitmask==0)[0]
        #x0[bad] = x0fit[bad]
    else:
        x0res = 0.0
    x3fit = np.dot(eigv,high_order_matrix.T) + np.outer(x0fit,np.ones(nrow)).T
    outpar = dict({'high_fit': high_fit, 'x0': x0, 'x0in': x0in, 'x0fit': x0fit, 'x0res': x0res, 'x0mask': fitmask,
                   'hidden': hidden, 'usetrc': usetrace, 'eigv': eigv, 'npc': npc, 'coeffstr': coeffstr})
    if retmask:
        return x3fit, outpar, tmask
    else:
        return x3fit, outpar
Пример #13
0
def bspline_magfit(wave, flux, var, flux_std, nointerp=False, **kwargs):
    """
    Perform a bspline fit to the flux ratio of standard to
    observed counts.  Used to generate a sensitivity function.

    Parameters
    ----------
    wave : ndarray
    flux : ndarray
      counts/s as observed
    var : ndarray
      variance
    flux_std : Quantity array
      standard star true flux (erg/s/cm^2/A)
    nointer : bool, optional [False]
      Skip interpolation over bad points (not recommended)?
    **kwargs : keywords for robust_polyfit

    Returns
    -------
    """
    invvar = (var > 0.) / (var + (var <= 0.))
    nx = wave.size
    pos_error = 1. / np.sqrt(np.maximum(invvar, 0.) + (invvar == 0))
    pos_mask = (flux > pos_error / 10.0) & (invvar > 0) & (flux_std > 0.0)
    #pos = pos_mask==1 npos)

    fluxlog = 2.5 * np.log10(np.maximum(flux, pos_error / 10))
    logivar = invvar * flux**2 * pos_mask * 1.08574

    # cap the magfunc so that sensfunc < 1.0e10
    magfunc = 2.5 * np.log10(np.maximum(flux_std, 1.0e-2)) - fluxlog
    magfunc = np.minimum(magfunc, 25.0)
    sensfunc = 10.0**(0.4 * magfunc) * pos_mask

    # Interpolate over masked pixels
    if not nointerp:
        bad = logivar <= 0.
        if np.sum(bad) > 0:
            f = scipy.interpolate.InterpolatedUnivariateSpline(wave[~bad],
                                                               magfunc[~bad],
                                                               k=2)
            magfunc[bad] = f(wave[bad])
            fi = scipy.interpolate.InterpolatedUnivariateSpline(wave[~bad],
                                                                logivar[~bad],
                                                                k=2)
            logivar[bad] = fi(wave[bad])

    #  First iteration
    mask, tck = arutils.robust_polyfit(wave,
                                       magfunc,
                                       3,
                                       function='bspline',
                                       weights=np.sqrt(logivar),
                                       **kwargs)
    logfit1 = arutils.func_val(tck, wave, 'bspline')
    modelfit1 = 10.0**(0.4 * (logfit1))

    residual = sensfunc / (modelfit1 + (modelfit1 == 0)) - 1.
    new_mask = pos_mask & (sensfunc > 0)
    residual_ivar = (modelfit1 * flux / (sensfunc +
                                         (sensfunc == 0.0)))**2 * invvar
    residual_ivar = residual_ivar * new_mask

    # Interpolate over masked pixels
    if not nointerp:
        if np.sum(bad) > 0:
            f = scipy.interpolate.InterpolatedUnivariateSpline(wave[~bad],
                                                               residual[~bad],
                                                               k=2)
            residual[bad] = f(wave[bad])
            fi = scipy.interpolate.InterpolatedUnivariateSpline(
                wave[~bad], residual_ivar[~bad], k=2)
            residual_ivar[bad] = fi(wave[bad])

    #  Now do one more fit to the ratio of data/model - 1.
    # Fuss with the knots first ()
    inner_knots = arutils.bspline_inner_knots(tck[0])
    #
    mask, tck_residual = arutils.robust_polyfit(wave,
                                                residual,
                                                3,
                                                function='bspline',
                                                weights=np.sqrt(residual_ivar),
                                                knots=inner_knots,
                                                **kwargs)
    if tck_residual[1].size != tck[1].size:
        msgs.error('Problem with bspline knots in bspline_magfit')
    #bset_residual = bspline_iterfit(wave, residual, weights=np.sqrt(residual_ivar), knots = tck[0])

    tck_log1 = list(tck)
    tck_log1[1] = tck[1] + tck_residual[1]

    sensfit = 10.0**(0.4 * (arutils.func_val(tck_log1, wave, 'bspline')))

    absdev = np.median(np.abs(sensfit / modelfit1 - 1))
    msgs.info('Difference between fits is {:g}'.format(absdev))

    # QA
    msgs.work("Add QA for sensitivity function")

    return tck_log1