Beispiel #1
0
def main(args):
    """
    Parameters
    ----------
    args

    Returns
    -------

    """

    import numpy as np
    from pypit import pyputils
    msgs = pyputils.get_dummy_logger()
    from pypit import arqa
    from linetools.utils import loadjson

    # Read JSON
    fdict = loadjson(args.wave_soln)
    for key in fdict.keys():
        if isinstance(fdict[key], list):
            fdict[key] = np.array(fdict[key])

    # Generate QA
    arqa.arc_fit_qa(None, fdict, outfil=args.outfile, ids_only=True,
                    title=args.title)
    print("Wrote {:s}".format(args.outfile))
Beispiel #2
0
def main(args):
    """
    Parameters
    ----------
    args

    Returns
    -------

    """

    import numpy as np
    from pypit import pyputils
    msgs = pyputils.get_dummy_logger()
    from pypit import arqa
    from linetools.utils import loadjson

    # Read JSON
    fdict = loadjson(args.wave_soln)
    for key in fdict.keys():
        if isinstance(fdict[key], list):
            fdict[key] = np.array(fdict[key])

    # Generate QA
    arqa.arc_fit_qa(None,
                    fdict,
                    outfil=args.outfile,
                    ids_only=True,
                    title=args.title)
    print("Wrote {:s}".format(args.outfile))
Beispiel #3
0
def tst_unknwn_wvcen(spec,
                     lines,
                     wv_cen,
                     disp,
                     siglev=20.,
                     min_ampl=300.,
                     swv_uncertainty=350.,
                     pix_tol=2,
                     plot_fil=None,
                     wvoff=1000.):
    """ As named
    """
    dcen = swv_uncertainty * 0.8
    wvcens = np.arange(wv_cen - wvoff, wv_cen + wvoff + dcen, dcen)
    # Best
    best_dict = dict(nmatch=0, nID=0, rms=0., ibest=-1, bwv=0.)
    # Loop
    for ss, iwv_cen in enumerate(wvcens):
        print('wv_cen guess = {:g}'.format(iwv_cen))
        stuff = grail.basic(spec,
                            lines,
                            iwv_cen,
                            disp,
                            siglev=siglev,
                            min_ampl=min_ampl,
                            swv_uncertainty=swv_uncertainty,
                            pix_tol=pix_tol,
                            plot_fil=None)
        if stuff[0] == -1:
            print("Solution failed for iwv_cen={:g}. Nmatch={:d}".format(
                iwv_cen, stuff[1]))
        elif stuff[0] == 1:
            # Unpack
            status, nmatch, match_idx, scores, final_fit = stuff
            print("Fit finished for iwv_cen={:g}".format(iwv_cen))
            # Metrics -- nmatch, nID, RMS
            nID = len(final_fit['xfit'])
            print("   Nmatch={:d}, nID={:d}, RMS={:g}".format(
                nmatch, nID, final_fit['rms']))
            # Best?
            if nID > best_dict['nID']:
                best_dict['nmatch'] = nmatch
                best_dict['nID'] = nID
                best_dict['rms'] = final_fit['rms']
                best_dict['ibest'] = ss
                best_dict['bwv'] = iwv_cen
                best_dict['fit'] = final_fit
    # Report
    print("Here is the best:")
    print(best_dict)
    # QA
    if plot_fil is not None:
        from pypit import pyputils
        msgs = pyputils.get_dummy_logger()
        from pypit import arqa
        arqa.arc_fit_qa(None, best_dict['fit'], outfil=plot_fil)
Beispiel #4
0
def calib_with_arclines(slf, det, get_poly=False, use_method="general"):
    """Simple calibration algorithm for longslit wavelengths

    Uses slf._arcparam to guide the analysis

    Parameters
    ----------
    get_poly : bool, optional
      Pause to record the polynomial pix = b0 + b1*lambda + b2*lambda**2

    Returns
    -------
    final_fit : dict
      Dict of fit info
    """
    from arclines.holy.grail import basic, semi_brute, general
    # Parameters (just for convenience)
    aparm = slf._arcparam[det - 1]
    # Extract the arc
    msgs.work("Detecting lines")
    tampl, tcent, twid, w, satsnd, spec = detect_lines(slf, det,
                                                       slf._msarc[det - 1])

    if use_method == "semi-brute":
        best_dict, final_fit = semi_brute(spec,
                                          aparm['lamps'],
                                          aparm['wv_cen'],
                                          aparm['disp'],
                                          fit_parm=aparm,
                                          min_ampl=aparm['min_ampl'])
    elif use_method == "basic":
        stuff = basic(spec, aparm['lamps'], aparm['wv_cen'], aparm['disp'])
        status, ngd_match, match_idx, scores, final_fit = stuff
    else:
        # Now preferred
        best_dict, final_fit = general(spec,
                                       aparm['lamps'],
                                       fit_parm=aparm,
                                       min_ampl=aparm['min_ampl'])
    arqa.arc_fit_qa(slf, final_fit)
    #
    return final_fit
Beispiel #5
0
def simple_calib(slf, det, get_poly=False):
    """Simple calibration algorithm for longslit wavelengths

    Uses slf._arcparam to guide the analysis

    Parameters
    ----------
    get_poly : bool, optional
      Pause to record the polynomial pix = b0 + b1*lambda + b2*lambda**2

    Returns
    -------
    final_fit : dict
      Dict of fit info
    """

    # Extract the arc
    msgs.work("Detecting lines..")
    tampl, tcent, twid, w, satsnd, yprep = detect_lines(
        slf, det, slf._msarc[det - 1])

    # Cut down to the good ones
    tcent = tcent[w]
    tampl = tampl[w]
    msgs.info('Detected {:d} lines in the arc spectrum.'.format(len(w[0])))

    # Parameters (just for convenience)
    aparm = slf._arcparam[det - 1]

    # Read Arc linelist
    llist = aparm['llist']

    # IDs were input by hand
    if len(settings.argflag['arc']['calibrate']['IDpixels']) > 0:
        # Check that there are at least 5 values
        pixels = np.array(settings.argflag['arc']['calibrate']['IDpixels'])
        if np.sum(pixels > 0.) < 5:
            msgs.error("Need to give at least 5 pixel values!")
        #
        msgs.info("Using input lines to seed the wavelength solution")
        # Calculate median offset
        mdiff = [
            np.min(np.abs(tcent - pix))
            for pix in settings.argflag['arc']['calibrate']['IDpixels']
        ]
        med_poff = np.median(np.array(mdiff))
        msgs.info("Will apply a median offset of {:g} pixels".format(med_poff))

        # Match input lines to observed spectrum
        nid = len(settings.argflag['arc']['calibrate']['IDpixels'])
        idx_str = np.ones(nid).astype(int)
        ids = np.zeros(nid)
        idsion = np.array(['     '] * nid)
        gd_str = np.arange(nid).astype(int)
        for jj, pix in enumerate(
                settings.argflag['arc']['calibrate']['IDpixels']):
            diff = np.abs(tcent - pix - med_poff)
            if np.min(diff) > 2.:
                debugger.set_trace()
                msgs.error("No match with input pixel {:g}!".format(pix))
            else:
                imn = np.argmin(diff)
            # Set
            idx_str[jj] = imn
            # Take wavelength from linelist instead of input value
            wdiff = np.abs(llist['wave'] -
                           settings.argflag['arc']['calibrate']['IDwaves'][jj])
            imnw = np.argmin(wdiff)
            if wdiff[imnw] > 0.015:  # Arbitrary tolerance
                msgs.error(
                    "Input IDwaves={:g} is not in the linelist.  Fix".format(
                        settings.argflag['arc']['calibrate']['IDwaves'][jj]))
            else:
                ids[jj] = llist['wave'][imnw]
                idsion[jj] = llist['Ion'][imnw]
                msgs.info("Identifying arc line: {:s} {:g}".format(
                    idsion[jj], ids[jj]))
    else:
        # Generate dpix pairs
        msgs.info("Using pair algorithm for wavelength solution")
        nlist = len(llist)
        dpix_list = np.zeros((nlist, nlist))
        for kk, row in enumerate(llist):
            #dpix_list[kk,:] = (np.array(row['wave'] - llist['wave']))/disp
            dpix_list[kk, :] = slf._msarc[det - 1].shape[0] * (
                aparm['b1'] * (np.array(row['wave'] - llist['wave'])) +
                aparm['b2'] * np.array(row['wave']**2 - llist['wave']**2))

        # Lambda pairs for the strongest N lines
        srt = np.argsort(tampl)
        idx_str = srt[-aparm['Nstrong']:]
        idx_str.sort()
        dpix_obs = np.zeros((aparm['Nstrong'], aparm['Nstrong']))
        for kk, idx in enumerate(idx_str):
            dpix_obs[kk, :] = np.array(tcent[idx] - tcent[idx_str])

        # Match up (ugly loops)
        ids = np.zeros(aparm['Nstrong'])
        idsion = np.array(['     '] * aparm['Nstrong'])
        for kk in range(aparm['Nstrong']):
            med_off = np.zeros(nlist)
            for ss in range(nlist):
                dpix = dpix_list[ss]
                min_off = []
                for jj in range(aparm['Nstrong']):
                    min_off.append(np.min(np.abs(dpix_obs[kk, jj] - dpix)))
                med_off[ss] = np.median(min_off)
            # Set by minimum
            idm = np.argmin(med_off)
            ids[kk] = llist['wave'][idm]
            idsion[kk] = llist['Ion'][idm]

        # Calculate disp of the strong lines
        disp_str = np.zeros(aparm['Nstrong'])
        for kk in range(aparm['Nstrong']):
            disp_val = (ids[kk] - ids) / (tcent[idx_str[kk]] - tcent[idx_str])
            isf = np.isfinite(disp_val)
            disp_str[kk] = np.median(disp_val[isf])
        # Consider calculating the RMS with clipping
        gd_str = np.where(
            np.abs(disp_str - aparm['disp']) /
            aparm['disp'] < aparm['disp_toler'])[0]
        msgs.info('Found {:d} lines within the dispersion threshold'.format(
            len(gd_str)))
        if len(gd_str) < 5:
            if msgs._debug['arc']:
                msgs.warn('You should probably try your best to ID lines now.')
                debugger.set_trace()
                debugger.plot1d(yprep)
            else:
                msgs.error('Insufficient lines to auto-fit.')

    # Debug
    #debug=True
    if msgs._debug['arc']:
        #tmp = list(gd_str)
        #tmp.pop(1)
        #gd_str = np.array(tmp)
        #xdb.xpcol(tcent[idx_str[gd_str]],ids[gd_str])
        #xdb.xplot(tcent[idx_str[gd_str]],ids[gd_str],scatter=True)
        # debugger.xplot(yprep)
        debugger.set_trace()

    msgs.work('Cross correlate here?')

    # Setup for fitting
    ifit = idx_str[gd_str]
    sv_ifit = list(ifit)  # Keep the originals
    all_ids = -999. * np.ones(len(tcent))
    all_idsion = np.array(['12345'] * len(tcent))
    all_ids[ifit] = ids[gd_str]
    all_idsion[ifit] = idsion[gd_str]
    # Fit
    n_order = aparm['n_first']
    flg_quit = False
    fmin, fmax = -1., 1.
    msgs.info('Iterative wavelength fitting..')
    while (n_order <= aparm['n_final']) and (flg_quit is False):
        #msgs.info('n_order={:d}'.format(n_order))
        # Fit with rejection
        xfit, yfit = tcent[ifit], all_ids[ifit]
        mask, fit = arutils.robust_polyfit(xfit,
                                           yfit,
                                           n_order,
                                           function=aparm['func'],
                                           sigma=aparm['nsig_rej'],
                                           minv=fmin,
                                           maxv=fmax)
        # Reject but keep originals (until final fit)
        ifit = list(ifit[mask == 0]) + sv_ifit
        # Find new points (should we allow removal of the originals?)
        twave = arutils.func_val(fit,
                                 tcent,
                                 aparm['func'],
                                 minv=fmin,
                                 maxv=fmax)
        for ss, iwave in enumerate(twave):
            mn = np.min(np.abs(iwave - llist['wave']))
            if mn / aparm['disp'] < aparm['match_toler']:
                imn = np.argmin(np.abs(iwave - llist['wave']))
                #if msgs._debug['arc']:
                #    print('Adding {:g} at {:g}'.format(llist['wave'][imn],tcent[ss]))
                # Update and append
                all_ids[ss] = llist['wave'][imn]
                all_idsion[ss] = llist['Ion'][imn]
                ifit.append(ss)
        # Keep unique ones
        ifit = np.unique(np.array(ifit, dtype=int))
        #if msgs._debug['arc']:
        #    debugger.set_trace()
        # Increment order
        if n_order < aparm['n_final']:
            n_order += 1
        else:
            # This does 2 iterations at the final order
            flg_quit = True

    # Final fit (originals can now be rejected)
    fmin, fmax = 0., 1.
    xfit, yfit = tcent[ifit] / (slf._msarc[det - 1].shape[0] -
                                1), all_ids[ifit]
    mask, fit = arutils.robust_polyfit(xfit,
                                       yfit,
                                       n_order,
                                       function=aparm['func'],
                                       sigma=aparm['nsig_rej_final'],
                                       minv=fmin,
                                       maxv=fmax)  #, debug=True)
    irej = np.where(mask == 1)[0]
    if len(irej) > 0:
        xrej = xfit[irej]
        yrej = yfit[irej]
        for imask in irej:
            msgs.info('Rejecting arc line {:g}'.format(yfit[imask]))
    else:
        xrej = []
        yrej = []
    xfit = xfit[mask == 0]
    yfit = yfit[mask == 0]
    ions = all_idsion[ifit][mask == 0]
    #
    if msgs._debug['arc']:
        msarc = slf._msarc[det - 1]
        wave = arutils.func_val(fit,
                                np.arange(msarc.shape[0]) /
                                float(msarc.shape[0]),
                                'legendre',
                                minv=fmin,
                                maxv=fmax)
        debugger.set_trace()

        #debugger.xplot(xfit, np.ones(len(xfit)), scatter=True,
        #    xtwo=np.arange(msarc.shape[0]),ytwo=yprep)
        #debugger.xplot(xfit,yfit, scatter=True, xtwo=np.arange(msarc.shape[0]),
        #    ytwo=wave)
        #debugger.set_trace()
        #wave = arutils.func_val(fit, np.arange(msarc.shape[0])/float(msarc.shape[0]),
        #    'legendre', min=fmin, max=fmax)

    # 2nd order Poly fit for archival
    #get_poly=True
    if get_poly:
        poly_fit = arutils.func_fit(yfit,
                                    xfit,
                                    'polynomial',
                                    2,
                                    minv=fmin,
                                    maxv=fmax)
        print(' Most likely you with to record these values:')
        print(poly_fit)
        debugger.set_trace()
    # Pack up fit
    final_fit = dict(fitc=fit,
                     function=aparm['func'],
                     xfit=xfit,
                     yfit=yfit,
                     ions=ions,
                     fmin=fmin,
                     fmax=fmax,
                     xnorm=float(slf._msarc[det - 1].shape[0]),
                     xrej=xrej,
                     yrej=yrej,
                     mask=mask,
                     spec=yprep,
                     nrej=aparm['nsig_rej_final'],
                     shift=0.,
                     tcent=tcent)
    # QA
    arqa.arc_fit_qa(slf, final_fit)
    # RMS
    rms_ang = arutils.calc_fit_rms(xfit,
                                   yfit,
                                   fit,
                                   aparm['func'],
                                   minv=fmin,
                                   maxv=fmax)
    wave = arutils.func_val(fit,
                            np.arange(slf._msarc[det - 1].shape[0]) /
                            float(slf._msarc[det - 1].shape[0]),
                            aparm['func'],
                            minv=fmin,
                            maxv=fmax)
    rms_pix = rms_ang / np.median(np.abs(wave - np.roll(wave, 1)))
    msgs.info("Fit RMS = {} pix".format(rms_pix))
    # Return
    return final_fit
Beispiel #6
0
def iterative_fitting(spec,
                      tcent,
                      ifit,
                      IDs,
                      llist,
                      disp,
                      plot_fil=None,
                      verbose=False,
                      load_pypit=False,
                      aparm=None):

    if aparm is None:
        aparm = dict(
            llist='',
            disp=disp,  # Ang/unbinned pixel
            disp_toler=0.1,  # 10% tolerance
            match_toler=3.,  # Matcing tolerance (pixels)
            func='legendre',  # Function for fitting
            n_first=3,  # Order of polynomial for first fit
            n_final=4,  # Order of polynomial for final fit
            nsig_rej=2.,  # Number of sigma for rejection
            nsig_rej_final=3.0)  # Number of sigma for rejection (final fit)
    # PYPIT
    if load_pypit:
        from pypit import pyputils
        msgs = pyputils.get_dummy_logger()
    from pypit import arutils
    from pypit import arqa
    if load_pypit:
        arutils.dummy_settings()

    npix = spec.size

    # Setup for fitting
    sv_ifit = list(ifit)  # Keep the originals
    all_ids = -999. * np.ones(len(tcent))
    all_idsion = np.array(['UNKNWN'] * len(tcent))
    all_ids[ifit] = IDs

    # Fit
    n_order = aparm['n_first']
    flg_quit = False
    fmin, fmax = -1., 1.
    while (n_order <= aparm['n_final']) and (flg_quit is False):
        # Fit with rejection
        xfit, yfit = tcent[ifit], all_ids[ifit]
        mask, fit = arutils.robust_polyfit(xfit,
                                           yfit,
                                           n_order,
                                           function=aparm['func'],
                                           sigma=aparm['nsig_rej'],
                                           minv=fmin,
                                           maxv=fmax)

        rms_ang = arutils.calc_fit_rms(xfit[mask == 0],
                                       yfit[mask == 0],
                                       fit,
                                       aparm['func'],
                                       minv=fmin,
                                       maxv=fmax)
        rms_pix = rms_ang / disp
        if verbose:
            print("RMS = {:g}".format(rms_pix))
        # DEBUG
        # Reject but keep originals (until final fit)
        ifit = list(ifit[mask == 0]) + sv_ifit
        # Find new points (should we allow removal of the originals?)
        twave = arutils.func_val(fit,
                                 tcent,
                                 aparm['func'],
                                 minv=fmin,
                                 maxv=fmax)
        for ss, iwave in enumerate(twave):
            mn = np.min(np.abs(iwave - llist['wave']))
            if mn / aparm['disp'] < aparm['match_toler']:
                imn = np.argmin(np.abs(iwave - llist['wave']))
                #if verbose:
                #    print('Adding {:g} at {:g}'.format(llist['wave'][imn],tcent[ss]))
                # Update and append
                all_ids[ss] = llist['wave'][imn]
                all_idsion[ss] = llist['ion'][imn]
                ifit.append(ss)
        # Keep unique ones
        ifit = np.unique(np.array(ifit, dtype=int))
        # Increment order
        if n_order < (aparm['n_final'] + 2):
            n_order += 1
        else:
            # This does 2 iterations at the final order
            flg_quit = True

    # Final fit (originals can now be rejected)
    fmin, fmax = 0., 1.
    xfit, yfit = tcent[ifit] / (npix - 1), all_ids[ifit]
    mask, fit = arutils.robust_polyfit(xfit,
                                       yfit,
                                       n_order,
                                       function=aparm['func'],
                                       sigma=aparm['nsig_rej_final'],
                                       minv=fmin,
                                       maxv=fmax)  #, debug=True)
    irej = np.where(mask == 1)[0]
    if len(irej) > 0:
        xrej = xfit[irej]
        yrej = yfit[irej]
        if verbose:
            for kk, imask in enumerate(irej):
                wave = arutils.func_val(fit,
                                        xrej[kk],
                                        aparm['func'],
                                        minv=fmin,
                                        maxv=fmax)
                print('Rejecting arc line {:g}; {:g}'.format(
                    yfit[imask], wave))
    else:
        xrej = []
        yrej = []
    xfit = xfit[mask == 0]
    yfit = yfit[mask == 0]
    ions = all_idsion[ifit][mask == 0]
    # Final RMS
    rms_ang = arutils.calc_fit_rms(xfit,
                                   yfit,
                                   fit,
                                   aparm['func'],
                                   minv=fmin,
                                   maxv=fmax)
    rms_pix = rms_ang / disp
    #
    '''
    if msgs._debug['arc']:
        msarc = slf._msarc[det-1]
        wave = arutils.func_val(fit, np.arange(msarc.shape[0])/float(msarc.shape[0]),
            'legendre', minv=fmin, maxv=fmax)
        debugger.xplot(xfit,yfit, scatter=True,
            xtwo=np.arange(msarc.shape[0])/float(msarc.shape[0]),
            ytwo=wave)
        debugger.xpcol(xfit*msarc.shape[0], yfit)
        debugger.set_trace()
    '''

    #debugger.xplot(xfit, np.ones(len(xfit)), scatter=True,
    #    xtwo=np.arange(msarc.shape[0]),ytwo=yprep)
    #debugger.xplot(xfit,yfit, scatter=True, xtwo=np.arange(msarc.shape[0]),
    #    ytwo=wave)
    #debugger.set_trace()
    #wave = arutils.func_val(fit, np.arange(msarc.shape[0])/float(msarc.shape[0]),
    #    'legendre', min=fmin, max=fmax)

    # Pack up fit
    final_fit = dict(fitc=fit,
                     function=aparm['func'],
                     xfit=xfit,
                     yfit=yfit,
                     ions=ions,
                     fmin=fmin,
                     fmax=fmax,
                     xnorm=float(npix),
                     xrej=xrej,
                     yrej=yrej,
                     mask=mask,
                     spec=spec,
                     nrej=aparm['nsig_rej_final'],
                     shift=0.,
                     tcent=tcent,
                     rms=rms_pix)
    # QA
    if plot_fil is not None:
        arqa.arc_fit_qa(None, final_fit, outfil=plot_fil)
    # Return
    return final_fit