예제 #1
0
    def echelle_2dfit(self, wv_calib, debug=False, skip_QA=False):
        """
        Evaluate 2-d wavelength solution for echelle data. Unpacks
        wv_calib for slits to be input into  arc.fit2darc

        Args:
            wv_calib (dict): Wavelength calibration
            debug (bool, optional):  Show debugging info
            skip_QA (bool, optional): Skip QA

        Returns:
            dict: dictionary containing information from 2-d fit

        """
        msgs.info('Fitting 2-d wavelength solution for echelle....')
        all_wave = np.array([], dtype=float)
        all_pixel = np.array([], dtype=float)
        all_order = np.array([], dtype=float)

        # Obtain a list of good slits
        ok_mask = np.where(~self.maskslits)[0]
        nspec = self.msarc.shape[0]
        for islit in wv_calib.keys():
            if int(islit) not in ok_mask:
                continue
            iorder = self.spectrograph.slit2order(islit)
            mask_now = wv_calib[islit]['mask']
            all_wave = np.append(all_wave,
                                 wv_calib[islit]['wave_fit'][mask_now])
            all_pixel = np.append(all_pixel,
                                  wv_calib[islit]['pixel_fit'][mask_now])
            all_order = np.append(
                all_order,
                np.full_like(wv_calib[islit]['pixel_fit'][mask_now],
                             float(iorder)))

        fit2d_dict = arc.fit2darc(all_wave,
                                  all_pixel,
                                  all_order,
                                  nspec,
                                  nspec_coeff=self.par['ech_nspec_coeff'],
                                  norder_coeff=self.par['ech_norder_coeff'],
                                  sigrej=self.par['ech_sigrej'],
                                  debug=debug)

        self.steps.append(inspect.stack()[0][3])

        # QA
        if not skip_QA:
            outfile_global = qa.set_qa_filename(self.master_key,
                                                'arc_fit2d_global_qa',
                                                out_dir=self.qa_path)
            arc.fit2darc_global_qa(fit2d_dict, outfile=outfile_global)
            outfile_orders = qa.set_qa_filename(self.master_key,
                                                'arc_fit2d_orders_qa',
                                                out_dir=self.qa_path)
            arc.fit2darc_orders_qa(fit2d_dict, outfile=outfile_orders)

        return fit2d_dict
def wv_calib_from_extern(wave_soln, arc, lamps, outfile = None, sigdetect=5.0, fwhm=4.0, nonlinear_counts=1e10, outroot='./', debug=False):

    # TODO add array size checking etc.
    nslits = wave_soln.shape[1]
    nspec  = wave_soln.shape[0]
    line_lists = wavecal.waveio.load_line_lists(lamps)
    wv_calib = {}
    spec_vec = np.arange(nspec)
    for islit in range(nslits):
        print(str(islit))
        # Find peaks for this slit
        tcent, ecent, cut_tcent, icut, spec_cont_sub = wavecal.wvutils.arc_lines_from_spec(arc[:,islit], sigdetect=sigdetect,
                                                                                   nonlinear_counts=nonlinear_counts,
                                                                                   fwhm=fwhm, debug=debug)
        detections = tcent[icut]
        wave_det = (scipy.interpolate.interp1d(spec_vec, wave_soln[:, islit], kind='cubic'))(detections)
        patt_dict = {}
        patt_dict['mask'] = np.ones_like(detections, dtype=bool)
        patt_dict['IDs'] = wave_det
        patt_dict['bdisp'] = (np.max(wave_soln[:,islit]) - np.min(wave_soln[:,islit]))/nspec
        final_fit = wavecal.fitting.fit_slit(spec_cont_sub, patt_dict, detections, line_lists, vel_tol=300.0, outroot=outroot, verbose=True)
        wv_calib[str(islit)] = final_fit
        qa_file = qa.set_qa_filename('GNIRS', 'arc_fit_qa', slit=islit, out_dir=outroot)
        wavecal.qa.arc_fit_qa(wv_calib[str(islit)],outfile=qa_file)
        if debug:
            # Show the QA
            wavecal.qa.arc_fit_qa(wv_calib[str(islit)])

    waveCalib = wavecalib.WaveCalib(None,None)
    if outfile is not None:
        waveCalib.save_master(wv_calib, outfile=outfile)

    return wv_calib
예제 #3
0
def plot_tilt_2d(tilts_dspat, tilts, tilts_model, tot_mask, rej_mask, spat_order, spec_order, rms, fwhm,
                 slit=0, setup='A', outfile=None, show_QA=False, out_dir=None):


    plt.rcdefaults()
    plt.rcParams['font.family']= 'Helvetica'

    # Outfile
    method = inspect.stack()[0][3]
    if (outfile is None):
        outfile = qa.set_qa_filename(setup, method, slit=slit, out_dir=out_dir)


    # Show the fit
    fig, ax = plt.subplots(figsize=(12, 18))
    ax.cla()
    ax.plot(tilts_dspat[tot_mask], tilts[tot_mask], color='black', linestyle=' ', mfc='None', marker='o',
            markersize=9.0, markeredgewidth=1.0, zorder=4, label='Good Tilt')
    ax.plot(tilts_dspat[rej_mask], tilts[rej_mask], color='red', linestyle=' ', mfc='None', marker='o',
            markersize=9.0, markeredgewidth=2.0, zorder=5, label='Rejected')
    ax.plot(tilts_dspat[tot_mask], tilts_model[tot_mask], color='black', linestyle=' ', marker='o',
            markersize=2.0, markeredgewidth=1.0, zorder=1, label='2D Model')

    xmin = 1.1 * tilts_dspat[tot_mask].min()
    xmax = 1.1 * tilts_dspat[tot_mask].max()
    ax.set_xlim((xmin, xmax))
    ax.set_xlabel('Spatial Offset from Central Trace (pixels)', fontsize=15)
    ax.set_ylabel('Spectral Pixel', fontsize=15)
    ax.legend()
    ax.set_title('Tilts vs Fit (spat_order, spec_order)=({:d},{:d}) for slit={:d}: RMS = {:5.3f}, '
                 'RMS/FWHM={:5.3f}'.format(spat_order, spec_order, slit, rms, rms / fwhm), fontsize=15)

    # Finish
    #plt.tight_layout(pad=1.0, h_pad=1.0, w_pad=1.0)

    if outfile is not None:
        plt.savefig(outfile, dpi=400)

    if show_QA:
        plt.show()

    plt.close()
    plt.rcdefaults()
예제 #4
0
    def build_wv_calib(self, arccen, method, skip_QA=False):
        """
        Main routine to generate the wavelength solutions in a loop over slits
        Wrapper to arc.simple_calib or arc.calib_with_arclines

        self.maskslits is updated for slits that fail

        Args:
            method : str
              'simple' -- arc.simple_calib
              'arclines' -- arc.calib_with_arclines
              'holy-grail' -- wavecal.autoid.HolyGrail
              'reidentify' -- wavecal.auotid.ArchiveReid
              'full_template' -- wavecal.auotid.full_template
            skip_QA (bool, optional)

        Returns:
            dict:  self.wv_calib
        """
        # Obtain a list of good slits
        ok_mask = np.where(~self.maskslits)[0]

        # Obtain calibration for all slits
        if method == 'simple':
            lines = self.par['lamps']
            line_lists = waveio.load_line_lists(lines)

            self.wv_calib = arc.simple_calib_driver(
                self.msarc,
                line_lists,
                arccen,
                ok_mask,
                nfitpix=self.par['nfitpix'],
                IDpixels=self.par['IDpixels'],
                IDwaves=self.par['IDwaves'])
        elif method == 'semi-brute':
            # TODO: THIS IS CURRENTLY BROKEN
            debugger.set_trace()
            final_fit = {}
            for slit in ok_mask:
                # HACKS BY JXP
                self.par['wv_cen'] = 8670.
                self.par['disp'] = 1.524
                # ToDO remove these hacks and use the parset in semi_brute
                best_dict, ifinal_fit \
                        = autoid.semi_brute(arccen[:, slit], self.par['lamps'], self.par['wv_cen'],
                                            self.par['disp'], match_toler=self.par['match_toler'],
                                            func=self.par['func'], n_first=self.par['n_first'],
                                            sigrej_first=self.par['n_first'],
                                            n_final=self.par['n_final'],
                                            sigrej_final=self.par['sigrej_final'],
                                            sigdetect=self.par['sigdetect'],
                                            nonlinear_counts= self.nonlinear_counts)
                final_fit[str(slit)] = ifinal_fit.copy()
        elif method == 'basic':
            final_fit = {}
            for slit in ok_mask:
                status, ngd_match, match_idx, scores, ifinal_fit = \
                        autoid.basic(arccen[:, slit], self.par['lamps'], self.par['wv_cen'],
                                     self.par['disp'], nonlinear_counts=self.nonlinear_counts)
                final_fit[str(slit)] = ifinal_fit.copy()
                if status != 1:
                    self.maskslits[slit] = True
        elif method == 'holy-grail':
            # Sometimes works, sometimes fails
            arcfitter = autoid.HolyGrail(arccen, par=self.par, ok_mask=ok_mask)
            patt_dict, final_fit = arcfitter.get_results()
        elif method == 'reidentify':
            # Now preferred
            # Slit positions
            arcfitter = autoid.ArchiveReid(arccen,
                                           self.spectrograph,
                                           self.par,
                                           ok_mask=ok_mask,
                                           slit_spat_pos=self.slit_spat_pos)
            patt_dict, final_fit = arcfitter.get_results()
        elif method == 'full_template':
            # Now preferred
            if self.binspectral is None:
                msgs.error(
                    "You must specify binspectral for the full_template method!"
                )
            final_fit = autoid.full_template(arccen,
                                             self.par,
                                             ok_mask,
                                             self.det,
                                             self.binspectral,
                                             nsnippet=self.par['nsnippet'])
        else:
            msgs.error(
                'Unrecognized wavelength calibration method: {:}'.format(
                    method))

        self.wv_calib = final_fit

        # Remake mask (*mainly for the QA that follows*)
        self.maskslits = self.make_maskslits(len(self.maskslits))
        ok_mask = np.where(~self.maskslits)[0]

        # QA
        if not skip_QA:
            for slit in ok_mask:
                outfile = qa.set_qa_filename(self.master_key,
                                             'arc_fit_qa',
                                             slit=slit,
                                             out_dir=self.qa_path)
                autoid.arc_fit_qa(self.wv_calib[str(slit)], outfile=outfile)

        # Return
        self.steps.append(inspect.stack()[0][3])
        return self.wv_calib
예제 #5
0
def flexure_qa_oldbuggyversion(specobjs,
                               maskslits,
                               basename,
                               det,
                               flex_list,
                               slit_cen=False):
    """ QA on flexure measurement

    Parameters
    ----------
    det
    flex_list : list
      list of dict containing flexure results
    slit_cen : bool, optional
      QA on slit center instead of objects

    Returns
    -------

    """
    plt.rcdefaults()
    plt.rcParams['font.family'] = 'times new roman'

    # Grab the named of the method
    method = inspect.stack()[0][3]
    #
    gdslits = np.where(~maskslits)[0]
    for sl in range(len(specobjs)):
        if sl not in gdslits:
            continue
        if specobjs[sl][0] is None:
            continue
        # Setup
        if slit_cen:
            nobj = 1
            ncol = 1
        else:
            nobj = len(specobjs[sl])
            ncol = min(3, nobj)
        #
        if nobj == 0:
            continue
        nrow = nobj // ncol + ((nobj % ncol) > 0)

        # Get the flexure dictionary
        flex_dict = flex_list[sl]

        # Outfile
        outfile = qa.set_qa_filename(basename,
                                     method + '_corr',
                                     det=det,
                                     slit=specobjs[sl][0].SLITID)

        plt.figure(figsize=(8, 5.0))
        plt.clf()
        gs = gridspec.GridSpec(nrow, ncol)

        # Correlation QA
        for o in range(nobj):
            ax = plt.subplot(gs[o // ncol, o % ncol])
            # Fit
            fit = flex_dict['polyfit'][o]
            xval = np.linspace(
                -10., 10,
                100) + flex_dict['corr_cen'][o]  #+ flex_dict['shift'][o]
            #model = (fit[2]*(xval**2.))+(fit[1]*xval)+fit[0]
            model = utils.func_val(fit, xval, 'polynomial')
            mxmod = np.max(model)
            ylim = [np.min(model / mxmod), 1.3]
            ax.plot(xval - flex_dict['corr_cen'][o], model / mxmod, 'k-')
            # Measurements
            ax.scatter(flex_dict['subpix'][o] - flex_dict['corr_cen'][o],
                       flex_dict['corr'][o] / mxmod,
                       marker='o')
            # Final shift
            ax.plot([flex_dict['shift'][o]] * 2, ylim, 'g:')
            # Label
            if slit_cen:
                ax.text(0.5,
                        0.25,
                        'Slit Center',
                        transform=ax.transAxes,
                        size='large',
                        ha='center')
            else:
                ax.text(0.5,
                        0.25,
                        '{:s}'.format(specobjs[sl][o].name),
                        transform=ax.transAxes,
                        size='large',
                        ha='center')
            ax.text(0.5,
                    0.15,
                    'flex_shift = {:g}'.format(flex_dict['shift'][o]),
                    transform=ax.transAxes,
                    size='large',
                    ha='center')  #, bbox={'facecolor':'white'})
            # Axes
            ax.set_ylim(ylim)
            ax.set_xlabel('Lag')

        # Finish
        plt.tight_layout(pad=0.2, h_pad=0.0, w_pad=0.0)
        plt.savefig(outfile, dpi=400)
        plt.close()

        # Sky line QA (just one object)
        if slit_cen:
            o = 0
        else:
            o = 0
            specobj = specobjs[sl][o]
        sky_spec = flex_dict['sky_spec'][o]
        arx_spec = flex_dict['arx_spec'][o]

        # Sky lines
        sky_lines = np.array([
            3370.0, 3914.0, 4046.56, 4358.34, 5577.338, 6300.304, 7340.885,
            7993.332, 8430.174, 8919.610, 9439.660, 10013.99, 10372.88
        ]) * units.AA
        dwv = 20. * units.AA
        gdsky = np.where((sky_lines > sky_spec.wvmin)
                         & (sky_lines < sky_spec.wvmax))[0]
        if len(gdsky) == 0:
            msgs.warn("No sky lines for Flexure QA")
            return
        if len(gdsky) > 6:
            idx = np.array(
                [0, 1, len(gdsky) // 2,
                 len(gdsky) // 2 + 1, -2, -1])
            gdsky = gdsky[idx]

        # Outfile
        outfile = qa.set_qa_filename(basename,
                                     method + '_sky',
                                     det=det,
                                     slit=specobjs[sl][0].SLITID)
        # Figure
        plt.figure(figsize=(8, 5.0))
        plt.clf()
        nrow, ncol = 2, 3
        gs = gridspec.GridSpec(nrow, ncol)
        if slit_cen:
            plt.suptitle('Sky Comparison for Slit Center', y=1.05)
        else:
            plt.suptitle('Sky Comparison for {:s}'.format(specobj.name),
                         y=1.05)

        for ii, igdsky in enumerate(gdsky):
            skyline = sky_lines[igdsky]
            ax = plt.subplot(gs[ii // ncol, ii % ncol])
            # Norm
            pix = np.where(np.abs(sky_spec.wavelength - skyline) < dwv)[0]
            f1 = np.sum(sky_spec.flux[pix])
            f2 = np.sum(arx_spec.flux[pix])
            norm = f1 / f2
            # Plot
            ax.plot(sky_spec.wavelength[pix],
                    sky_spec.flux[pix],
                    'k-',
                    label='Obj',
                    drawstyle='steps-mid')
            pix2 = np.where(np.abs(arx_spec.wavelength - skyline) < dwv)[0]
            ax.plot(arx_spec.wavelength[pix2],
                    arx_spec.flux[pix2] * norm,
                    'r-',
                    label='Arx',
                    drawstyle='steps-mid')
            # Axes
            ax.xaxis.set_major_locator(plt.MultipleLocator(dwv.value))
            ax.set_xlabel('Wavelength')
            ax.set_ylabel('Counts')

        # Legend
        plt.legend(loc='upper left',
                   scatterpoints=1,
                   borderpad=0.3,
                   handletextpad=0.3,
                   fontsize='small',
                   numpoints=1)

        # Finish
        plt.savefig(outfile, dpi=400)
        plt.close()
        #plt.close()

    plt.rcdefaults()
예제 #6
0
def flexure_qa(specobjs,
               maskslits,
               basename,
               det,
               flex_list,
               slit_cen=False,
               out_dir=None):
    """

    Args:
        specobjs:
        maskslits (np.ndarray):
        basename (str):
        det (int):
        flex_list (list):
        slit_cen:
        out_dir:

    """
    plt.rcdefaults()
    plt.rcParams['font.family'] = 'times new roman'

    # Grab the named of the method
    method = inspect.stack()[0][3]
    #
    gdslits = np.where(np.invert(maskslits))[0]

    # Loop over slits, and then over objects here
    for slit in gdslits:
        indx = specobjs.slitorder_indices(slit)
        this_specobjs = specobjs[indx]
        this_flex_dict = flex_list[slit]

        # Setup
        if slit_cen:
            nobj = 1
            ncol = 1
        else:
            nobj = np.sum(indx)
            ncol = min(3, nobj)
        #
        if nobj == 0:
            continue
        nrow = nobj // ncol + ((nobj % ncol) > 0)
        # Outfile, one QA file per slit
        outfile = qa.set_qa_filename(basename,
                                     method + '_corr',
                                     det=det,
                                     slit=(slit + 1),
                                     out_dir=out_dir)
        plt.figure(figsize=(8, 5.0))
        plt.clf()
        gs = gridspec.GridSpec(nrow, ncol)
        for iobj, specobj in enumerate(this_specobjs):
            if specobj is None or len(specobj._data.keys()) == 1:
                continue
            # Correlation QA
            ax = plt.subplot(gs[iobj // ncol, iobj % ncol])
            # Fit
            fit = this_flex_dict['polyfit'][iobj]
            xval = np.linspace(-10., 10, 100) + this_flex_dict['corr_cen'][
                iobj]  #+ flex_dict['shift'][o]
            #model = (fit[2]*(xval**2.))+(fit[1]*xval)+fit[0]
            model = utils.func_val(fit, xval, 'polynomial')
            mxmod = np.max(model)
            ylim_min = np.min(model /
                              mxmod) if np.isfinite(np.min(model /
                                                           mxmod)) else 0.0
            ylim = [ylim_min, 1.3]
            ax.plot(xval - this_flex_dict['corr_cen'][iobj], model / mxmod,
                    'k-')
            # Measurements
            ax.scatter(this_flex_dict['subpix'][iobj] -
                       this_flex_dict['corr_cen'][iobj],
                       this_flex_dict['corr'][iobj] / mxmod,
                       marker='o')
            # Final shift
            ax.plot([this_flex_dict['shift'][iobj]] * 2, ylim, 'g:')
            # Label
            if slit_cen:
                ax.text(0.5,
                        0.25,
                        'Slit Center',
                        transform=ax.transAxes,
                        size='large',
                        ha='center')
            else:
                ax.text(0.5,
                        0.25,
                        '{:s}'.format(specobj.name),
                        transform=ax.transAxes,
                        size='large',
                        ha='center')
            ax.text(0.5,
                    0.15,
                    'flex_shift = {:g}'.format(this_flex_dict['shift'][iobj]),
                    transform=ax.transAxes,
                    size='large',
                    ha='center')  #, bbox={'facecolor':'white'})
            # Axes
            ax.set_ylim(ylim)
            ax.set_xlabel('Lag')
        # Finish
        plt.tight_layout(pad=0.2, h_pad=0.0, w_pad=0.0)
        plt.savefig(outfile, dpi=400)
        plt.close()

        # Sky line QA (just one object)
        if slit_cen:
            iobj = 0
        else:
            iobj = 0
            specobj = this_specobjs[iobj]

        if len(this_flex_dict['shift']) == 0:
            return

        # Repackage
        sky_spec = this_flex_dict['sky_spec'][iobj]
        arx_spec = this_flex_dict['arx_spec'][iobj]

        # Sky lines
        sky_lines = np.array([
            3370.0, 3914.0, 4046.56, 4358.34, 5577.338, 6300.304, 7340.885,
            7993.332, 8430.174, 8919.610, 9439.660, 10013.99, 10372.88
        ]) * units.AA
        dwv = 20. * units.AA
        gdsky = np.where((sky_lines > sky_spec.wvmin)
                         & (sky_lines < sky_spec.wvmax))[0]
        if len(gdsky) == 0:
            msgs.warn("No sky lines for Flexure QA")
            return
        if len(gdsky) > 6:
            idx = np.array(
                [0, 1, len(gdsky) // 2,
                 len(gdsky) // 2 + 1, -2, -1])
            gdsky = gdsky[idx]

        # Outfile
        outfile = qa.set_qa_filename(basename,
                                     method + '_sky',
                                     det=det,
                                     slit=(slit + 1),
                                     out_dir=out_dir)
        # Figure
        plt.figure(figsize=(8, 5.0))
        plt.clf()
        nrow, ncol = 2, 3
        gs = gridspec.GridSpec(nrow, ncol)
        if slit_cen:
            plt.suptitle('Sky Comparison for Slit Center', y=1.05)
        else:
            plt.suptitle('Sky Comparison for {:s}'.format(specobj.name),
                         y=1.05)

        for ii, igdsky in enumerate(gdsky):
            skyline = sky_lines[igdsky]
            ax = plt.subplot(gs[ii // ncol, ii % ncol])
            # Norm
            pix = np.where(np.abs(sky_spec.wavelength - skyline) < dwv)[0]
            f1 = np.sum(sky_spec.flux[pix])
            f2 = np.sum(arx_spec.flux[pix])
            norm = f1 / f2
            # Plot
            ax.plot(sky_spec.wavelength[pix],
                    sky_spec.flux[pix],
                    'k-',
                    label='Obj',
                    drawstyle='steps-mid')
            pix2 = np.where(np.abs(arx_spec.wavelength - skyline) < dwv)[0]
            ax.plot(arx_spec.wavelength[pix2],
                    arx_spec.flux[pix2] * norm,
                    'r-',
                    label='Arx',
                    drawstyle='steps-mid')
            # Axes
            ax.xaxis.set_major_locator(plt.MultipleLocator(dwv.value))
            ax.set_xlabel('Wavelength')
            ax.set_ylabel('Counts')

        # Legend
        plt.legend(loc='upper left',
                   scatterpoints=1,
                   borderpad=0.3,
                   handletextpad=0.3,
                   fontsize='small',
                   numpoints=1)

        # Finish
        plt.savefig(outfile, dpi=400)
        plt.close()
        #plt.close()

    plt.rcdefaults()

    return
예제 #7
0
    def build_wv_calib(self, arccen, method, skip_QA=False):
        """
        Main routine to generate the wavelength solutions in a loop over slits
        Wrapper to arc.simple_calib or arc.calib_with_arclines

        self.maskslits is updated for slits that fail

        Args:
            method : str
              'simple' -- arc.simple_calib
              'arclines' -- arc.calib_with_arclines
              'holy-grail' -- wavecal.autoid.HolyGrail
              'reidentify' -- wavecal.auotid.ArchiveReid
              'identify' -- wavecal.identify.Identify
              'full_template' -- wavecal.auotid.full_template
            skip_QA (bool, optional)

        Returns:
            dict:  self.wv_calib
        """
        # Obtain a list of good slits
        ok_mask = np.where(np.invert(self.maskslits))[0]
        # Obtain calibration for all slits
        if method == 'simple':
            lines = self.par['lamps']
            line_lists = waveio.load_line_lists(lines)

            final_fit = arc.simple_calib_driver(
                line_lists,
                arccen,
                ok_mask,
                n_final=self.par['n_final'],
                sigdetect=self.par['sigdetect'],
                IDpixels=self.par['IDpixels'],
                IDwaves=self.par['IDwaves'])
        elif method == 'semi-brute':
            # TODO: THIS IS CURRENTLY BROKEN
            embed()
            final_fit = {}
            for slit in ok_mask:
                # HACKS BY JXP
                self.par['wv_cen'] = 8670.
                self.par['disp'] = 1.524
                # ToDO remove these hacks and use the parset in semi_brute
                best_dict, ifinal_fit \
                        = autoid.semi_brute(arccen[:, slit], self.par['lamps'], self.par['wv_cen'],
                                            self.par['disp'], match_toler=self.par['match_toler'],
                                            func=self.par['func'], n_first=self.par['n_first'],
                                            sigrej_first=self.par['n_first'],
                                            n_final=self.par['n_final'],
                                            sigrej_final=self.par['sigrej_final'],
                                            sigdetect=self.par['sigdetect'],
                                            nonlinear_counts= self.nonlinear_counts)
                final_fit[str(slit)] = ifinal_fit.copy()
        elif method == 'basic':
            final_fit = {}
            for slit in ok_mask:
                status, ngd_match, match_idx, scores, ifinal_fit = \
                        autoid.basic(arccen[:, slit], self.par['lamps'], self.par['wv_cen'],
                                     self.par['disp'], nonlinear_counts=self.nonlinear_counts)
                final_fit[str(slit)] = ifinal_fit.copy()
                if status != 1:
                    self.maskslits[slit] = True
        elif method == 'holy-grail':
            # Sometimes works, sometimes fails
            arcfitter = autoid.HolyGrail(arccen, par=self.par, ok_mask=ok_mask)
            patt_dict, final_fit = arcfitter.get_results()
        elif method == 'identify':
            final_fit = {}
            # Manually identify lines
            msgs.info("Initializing the wavelength calibration tool")
            # TODO: Move this loop to the GUI initalise method
            embed()
            for slit in ok_mask:
                arcfitter = gui_identify.initialise(arccen,
                                                    slit=slit,
                                                    par=self.par)
                final_fit[str(slit)] = arcfitter.get_results()
                if final_fit[str(slit)] is not None:
                    ans = 'y'
                    # ans = ''
                    # while ans != 'y' and ans != 'n':
                    #     ans = input("Would you like to store this wavelength solution in the archive? (y/n): ")
                    if ans == 'y' and final_fit[str(
                            slit)]['rms'] < self.par['rms_threshold']:
                        # Store the results in the user reid arxiv
                        specname = self.spectrograph.spectrograph
                        gratname = "UNKNOWN"  # input("Please input the grating name: ")
                        dispangl = "UNKNOWN"  # input("Please input the dispersion angle: ")
                        templates.pypeit_identify_record(
                            final_fit[str(slit)], self.binspectral, specname,
                            gratname, dispangl)
                        msgs.info("Your wavelength solution has been stored")
                        msgs.info(
                            "Please consider sending your solution to the PYPEIT team!"
                        )

        elif method == 'reidentify':
            # Now preferred
            # Slit positions
            arcfitter = autoid.ArchiveReid(arccen,
                                           self.spectrograph,
                                           self.par,
                                           ok_mask=ok_mask,
                                           slit_spat_pos=self.slit_spat_pos)
            patt_dict, final_fit = arcfitter.get_results()
        elif method == 'full_template':
            # Now preferred
            if self.binspectral is None:
                msgs.error(
                    "You must specify binspectral for the full_template method!"
                )
            final_fit = autoid.full_template(arccen,
                                             self.par,
                                             ok_mask,
                                             self.det,
                                             self.binspectral,
                                             nsnippet=self.par['nsnippet'])
        else:
            msgs.error(
                'Unrecognized wavelength calibration method: {:}'.format(
                    method))

        self.wv_calib = final_fit

        # Remake mask (*mainly for the QA that follows*)
        self.maskslits = self.make_maskslits(len(self.maskslits))
        ok_mask = np.where(np.invert(self.maskslits))[0]

        # QA
        if not skip_QA:
            for slit in ok_mask:
                outfile = qa.set_qa_filename(self.master_key,
                                             'arc_fit_qa',
                                             slit=slit,
                                             out_dir=self.qa_path)
                autoid.arc_fit_qa(self.wv_calib[str(slit)], outfile=outfile)

        # Return
        self.steps.append(inspect.stack()[0][3])
        return self.wv_calib
예제 #8
0
파일: wavecalib.py 프로젝트: Tuo-Ji/PypeIt
    def echelle_2dfit(self, wv_calib, debug=False, skip_QA=False):
        """
        Fit a two-dimensional wavelength solution for echelle data.

        Primarily a wrapper for :func:`pypeit.core.arc.fit2darc`,
        using data unpacked from the ``wv_calib`` dictionary.

        Args:
            wv_calib (:class:`pypeit.wavecalib.WaveCalib`):
                Wavelength calibration object
            debug (:obj:`bool`, optional):
                Show debugging info
            skip_QA (:obj:`bool`, optional):
                Flag to skip construction of the nominal QA plots.

        Returns:
            :class:`pypeit.fitting.PypeItFit`: object containing information from 2-d fit.
        """
        if self.spectrograph.pypeline != 'Echelle':
            msgs.error(
                'Cannot execute echelle_2dfit for a non-echelle spectrograph.')

        msgs.info('Fitting 2-d wavelength solution for echelle....')
        all_wave = np.array([], dtype=float)
        all_pixel = np.array([], dtype=float)
        all_order = np.array([], dtype=float)

        # Obtain a list of good slits
        ok_mask_idx = np.where(np.invert(self.wvc_bpm))[0]
        ok_mask_order = self.slits.slitord_id[ok_mask_idx]
        nspec = self.msarc.image.shape[0]
        # Loop
        for ii in range(wv_calib.nslits):
            iorder = self.slits.ech_order[ii]
            if iorder not in ok_mask_order:
                continue
            # Slurp
            mask_now = wv_calib.wv_fits[ii].pypeitfit.bool_gpm
            all_wave = np.append(all_wave,
                                 wv_calib.wv_fits[ii]['wave_fit'][mask_now])
            all_pixel = np.append(all_pixel,
                                  wv_calib.wv_fits[ii]['pixel_fit'][mask_now])
            all_order = np.append(
                all_order,
                np.full_like(wv_calib.wv_fits[ii]['pixel_fit'][mask_now],
                             float(iorder)))

        # Fit
        # THIS NEEDS TO BE DEVELOPED
        fit2d = arc.fit2darc(all_wave,
                             all_pixel,
                             all_order,
                             nspec,
                             nspec_coeff=self.par['ech_nspec_coeff'],
                             norder_coeff=self.par['ech_norder_coeff'],
                             sigrej=self.par['ech_sigrej'],
                             debug=debug)

        self.steps.append(inspect.stack()[0][3])

        # QA
        # TODO -- TURN QA BACK ON!
        #skip_QA = True
        if not skip_QA:
            outfile_global = qa.set_qa_filename(self.master_key,
                                                'arc_fit2d_global_qa',
                                                out_dir=self.qa_path)
            arc.fit2darc_global_qa(fit2d, nspec, outfile=outfile_global)
            outfile_orders = qa.set_qa_filename(self.master_key,
                                                'arc_fit2d_orders_qa',
                                                out_dir=self.qa_path)
            arc.fit2darc_orders_qa(fit2d, nspec, outfile=outfile_orders)

        return fit2d
예제 #9
0
파일: wavecalib.py 프로젝트: Tuo-Ji/PypeIt
    def build_wv_calib(self, arccen, method, skip_QA=False):
        """
        Main routine to generate the wavelength solutions in a loop over slits
        Wrapper to arc.simple_calib or arc.calib_with_arclines

        self.maskslits is updated for slits that fail

        Args:
            method : str
              'simple' -- arc.simple_calib
              'arclines' -- arc.calib_with_arclines
              'holy-grail' -- wavecal.autoid.HolyGrail
              'reidentify' -- wavecal.auotid.ArchiveReid
              'identify' -- wavecal.identify.Identify
              'full_template' -- wavecal.auotid.full_template
            skip_QA (bool, optional)

        Returns:
            dict:  self.wv_calib
        """
        # Obtain a list of good slits
        ok_mask_idx = np.where(np.invert(self.wvc_bpm))[0]

        # Obtain calibration for all slits
        if method == 'simple':
            lines = self.par['lamps']
            line_lists = waveio.load_line_lists(lines)

            final_fit = arc.simple_calib_driver(
                line_lists,
                arccen,
                ok_mask_idx,
                n_final=self.par['n_final'],
                sigdetect=self.par['sigdetect'],
                IDpixels=self.par['IDpixels'],
                IDwaves=self.par['IDwaves'])
        elif method == 'holy-grail':
            # Sometimes works, sometimes fails
            arcfitter = autoid.HolyGrail(
                arccen,
                par=self.par,
                ok_mask=ok_mask_idx,
                nonlinear_counts=self.nonlinear_counts)
            patt_dict, final_fit = arcfitter.get_results()
        elif method == 'identify':
            final_fit = {}
            # Manually identify lines
            msgs.info("Initializing the wavelength calibration tool")
            embed(header='line 222 wavecalib.py')
            for slit_idx in ok_mask_idx:
                arcfitter = Identify.initialise(arccen,
                                                self.slits,
                                                slit=slit_idx,
                                                par=self.par)
                final_fit[str(slit_idx)] = arcfitter.get_results()
                arcfitter.store_solution(final_fit[str(slit_idx)],
                                         "",
                                         self.binspectral,
                                         specname=self.spectrograph.name,
                                         gratname="UNKNOWN",
                                         dispangl="UNKNOWN")
        elif method == 'reidentify':
            # Now preferred
            # Slit positions
            arcfitter = autoid.ArchiveReid(
                arccen,
                self.spectrograph,
                self.par,
                ok_mask=ok_mask_idx,
                #slit_spat_pos=self.spat_coo,
                orders=self.orders,
                nonlinear_counts=self.nonlinear_counts)
            patt_dict, final_fit = arcfitter.get_results()
        elif method == 'full_template':
            # Now preferred
            if self.binspectral is None:
                msgs.error(
                    "You must specify binspectral for the full_template method!"
                )
            final_fit = autoid.full_template(
                arccen,
                self.par,
                ok_mask_idx,
                self.det,
                self.binspectral,
                nonlinear_counts=self.nonlinear_counts,
                nsnippet=self.par['nsnippet'])
        else:
            msgs.error(
                'Unrecognized wavelength calibration method: {:}'.format(
                    method))

        # Build the DataContainer
        # Loop on WaveFit items
        tmp = []
        for idx in range(self.slits.nslits):
            item = final_fit.pop(str(idx))
            if item is None:  # Add an empty WaveFit
                tmp.append(wv_fitting.WaveFit(self.slits.spat_id[idx]))
            else:
                # This is for I/O naming
                item.spat_id = self.slits.spat_id[idx]
                tmp.append(item)
        self.wv_calib = WaveCalib(
            wv_fits=np.asarray(tmp),
            arc_spectra=arccen,
            nslits=self.slits.nslits,
            spat_ids=self.slits.spat_id,
            PYP_SPEC=self.spectrograph.name,
        )

        # Update mask
        self.update_wvmask()

        #TODO For generalized echelle (not hard wired) assign order number here before, i.e. slits.ech_order

        # QA
        if not skip_QA:
            ok_mask_idx = np.where(np.invert(self.wvc_bpm))[0]
            for slit_idx in ok_mask_idx:
                outfile = qa.set_qa_filename(
                    self.master_key,
                    'arc_fit_qa',
                    slit=self.slits.slitord_id[slit_idx],
                    out_dir=self.qa_path)
                #
                #autoid.arc_fit_qa(self.wv_calib[str(self.slits.slitord_id[slit_idx])],
                #                  outfile=outfile)
                autoid.arc_fit_qa(
                    self.wv_calib.wv_fits[slit_idx],
                    #str(self.slits.slitord_id[slit_idx]),
                    outfile=outfile)

        # Return
        self.steps.append(inspect.stack()[0][3])
        return self.wv_calib
예제 #10
0
    def echelle_2dfit(self, wv_calib, debug=False, skip_QA=False):
        """
        Fit a two-dimensional wavelength solution for echelle data.

        Primarily a wrapper for :func:`pypeit.core.arc.fit2darc`,
        using data unpacked from the ``wv_calib`` dictionary.
        
        Args:
            wv_calib (:obj:`dict`):
                Wavelength calibration dictionary.  See ??
            debug (:obj:`bool`, optional):
                Show debugging info
            skip_QA (:obj:`bool`, optional):
                Flag to skip construction of the nominal QA plots.

        Returns:
            :obj:`dict`: Dictionary containing information from 2-d
            fit.
        """
        if self.spectrograph.pypeline != 'Echelle':
            msgs.error(
                'Cannot execute echelle_2dfit for a non-echelle spectrograph.')

        msgs.info('Fitting 2-d wavelength solution for echelle....')
        all_wave = np.array([], dtype=float)
        all_pixel = np.array([], dtype=float)
        all_order = np.array([], dtype=float)

        # Obtain a list of good slits
        ok_mask_idx = np.where(np.invert(self.wvc_bpm))[0]
        ok_mask_order = self.slits.slitord_id[ok_mask_idx]
        nspec = self.msarc.image.shape[0]
        for iorder in wv_calib.keys():  # Spatial based
            if int(iorder) not in ok_mask_order:
                continue
            #try:
            #    iorder, iindx = self.spectrograph.slit2order(self.spat_coo[self.slits.spatid_to_zero(int(islit))])
            #except:
            #    embed()
            mask_now = wv_calib[iorder]['mask']
            all_wave = np.append(all_wave,
                                 wv_calib[iorder]['wave_fit'][mask_now])
            all_pixel = np.append(all_pixel,
                                  wv_calib[iorder]['pixel_fit'][mask_now])
            all_order = np.append(
                all_order,
                np.full_like(wv_calib[iorder]['pixel_fit'][mask_now],
                             float(iorder)))

        # Fit
        fit2d_dict = arc.fit2darc(all_wave,
                                  all_pixel,
                                  all_order,
                                  nspec,
                                  nspec_coeff=self.par['ech_nspec_coeff'],
                                  norder_coeff=self.par['ech_norder_coeff'],
                                  sigrej=self.par['ech_sigrej'],
                                  debug=debug)

        self.steps.append(inspect.stack()[0][3])

        # QA
        if not skip_QA:
            outfile_global = qa.set_qa_filename(self.master_key,
                                                'arc_fit2d_global_qa',
                                                out_dir=self.qa_path)
            arc.fit2darc_global_qa(fit2d_dict, outfile=outfile_global)
            outfile_orders = qa.set_qa_filename(self.master_key,
                                                'arc_fit2d_orders_qa',
                                                out_dir=self.qa_path)
            arc.fit2darc_orders_qa(fit2d_dict, outfile=outfile_orders)

        return fit2d_dict
예제 #11
0
def pca_plot(setup, inpar, ofit, prefix, maxp=25, pcadesc="", addOne=True,
             show=False):
    """ Saves quality control plots for a PCA analysis
    Parameters
    ----------
    inpar
    ofit
    prefix : str
      prefix for the filenames
    maxp
    pcadesc
    addOne

    Returns
    -------

    """

    plt.rcdefaults()
    plt.rcParams['font.family']= 'times new roman'

    # Setup
    method = inspect.stack()[0][3]
    if not show:
        outroot = qa.set_qa_filename(setup, method, prefix=prefix)
    npc = inpar['npc']+1
    pages, npp = qa.get_dimen(npc, maxp=maxp)
    #
    x0 = inpar['x0']
    ordernum = inpar['x0in']
    x0fit = inpar['x0fit']
    usetrc = inpar['usetrc']
    hidden = inpar['hidden']
    high_fit = inpar['high_fit']
    nc = np.max(ordernum[usetrc])
    # Loop through all pages and plot the results
    ndone = 0
    for i in range(len(pages)):
        plt.clf()
        f, axes = plt.subplots(pages[i][1], pages[i][0])
        ipx, ipy = 0, 0
        if i == 0:
            if pages[i][1] == 1: ind = (0,)
            elif pages[i][0] == 1: ind = (0,)
            else: ind = (0,0)
            axes[ind].plot(ordernum[usetrc], x0[usetrc], 'bx')
            axes[ind].plot(ordernum, x0fit, 'k-')
            amn, amx = np.min(x0fit), np.max(x0fit)
            diff = x0[usetrc]-x0fit[usetrc]
            tdiffv = np.median(diff)
            mdiffv = 1.4826*np.median(np.abs(tdiffv-diff))
            amn -= 2.0*mdiffv
            amx += 2.0*mdiffv
            mval = amn-0.15*(amx-amn)
            dmin, dmax = tdiffv-2.0*mdiffv, tdiffv+2.0*mdiffv
            diff = mval + diff*0.20*(amx-amn)/(dmax-dmin)
            wign = np.where(np.abs(diff-np.median(diff))<4.0*1.4826*np.median(np.abs(diff-np.median(diff))))[0]
            dmin, dmax = np.min(diff[wign]), np.max(diff[wign])
            axes[ind].plot(ordernum[usetrc], diff, 'rx')
            if addOne:
                axes[ind].plot([0, nc+1], [mval,mval], 'k-')
                axes[ind].axis([0, nc+1, dmin-0.5*(dmax-dmin), amx + 0.05*(amx-amn)])
            else:
                axes[ind].plot([0, nc], [mval, mval], 'k-')
                axes[ind].axis([0, nc, dmin-0.5*(dmax-dmin), amx + 0.05*(amx-amn)])
            axes[ind].set_title("Mean Value")
            ipx += 1
            if ipx == pages[i][0]:
                ipx = 0
                ipy += 1
            npp[0] -= 1
        for j in range(npp[i]):
            if pages[i][1] == 1: ind = (ipx,)
            elif pages[i][0] == 1: ind = (ipy,)
            else: ind = (ipy, ipx)
            axes[ind].plot(ordernum[usetrc], hidden[j+ndone,:], 'bx')
            axes[ind].plot(ordernum, high_fit[:,j+ndone], 'k-')
            vmin, vmax = np.min(hidden[j+ndone,:]), np.max(hidden[j+ndone,:])
            if ofit[1+j+ndone] != -1:
                cmn, cmx = np.min(high_fit[:,j+ndone]), np.max(high_fit[:,j+ndone])
                diff = hidden[j+ndone,:]-high_fit[:,j+ndone][usetrc]
                tdiffv = np.median(diff)
                mdiffv = 1.4826*np.median(np.abs(tdiffv-diff))
                cmn -= 2.0*mdiffv
                cmx += 2.0*mdiffv
                mval = cmn-0.15*(cmx-cmn)
                dmin, dmax = tdiffv-2.0*mdiffv, tdiffv+2.0*mdiffv
                #dmin, dmax = np.min(diff), np.max(diff)
                diff = mval + diff*0.20*(cmx-cmn)/(dmax-dmin)
                wign = np.where(np.abs(diff-np.median(diff))<4.0*1.4826*np.median(np.abs(diff-np.median(diff))))[0]
                dmin, dmax = np.min(diff[wign]), np.max(diff[wign])
                #vmin, vmax = np.min(hidden[j+ndone,:][wign]), np.max(hidden[j+ndone,:][wign])
                axes[ind].plot(ordernum[usetrc], diff, 'rx')
                axes[ind].plot([0, 1+nc], [mval, mval], 'k-')
#				ymin = np.min([(3.0*dmin-dmax)/2.0,vmin-0.1*(vmax-dmin),dmin-0.1*(vmax-dmin)])
#				ymax = np.max([np.max(high_fit[:,j+ndone]),vmax+0.1*(vmax-dmin),dmax+0.1*(vmax-dmin)])
                ymin = dmin-0.5*(dmax-dmin)
                ymax = cmx + 0.05*(cmx-cmn)
                if addOne: axes[ind].axis([0, nc+1, ymin, ymax])
                else: axes[ind].axis([0, nc, ymin, ymax])
            else:
                if addOne: axes[ind].axis([0, nc+1, vmin-0.1*(vmax-vmin), vmax+0.1*(vmax-vmin)])
                else: axes[ind].axis([0, nc, vmin-0.1*(vmax-vmin), vmax+0.1*(vmax-vmin)])
            axes[ind].set_title("PC {0:d}".format(j+ndone))
            axes[ind].tick_params(labelsize=8)
            ipx += 1
            if ipx == pages[i][0]:
                ipx = 0
                ipy += 1
        if i == 0: npp[0] = npp[0] + 1
        # Delete the unnecessary axes
        for j in range(npp[i], axes.size):
            if pages[i][1] == 1: ind = (ipx,)
            elif pages[i][0] == 1: ind = (ipy,)
            else: ind = (ipy, ipx)
            f.delaxes(axes[ind])
            ipx += 1
            if ipx == pages[i][0]:
                ipx = 0
                ipy += 1
        ndone += npp[i]
        # Save the figure
        if pages[i][1] == 1 or pages[i][0] == 1: ypngsiz = 11.0/axes.size
        else: ypngsiz = 11.0*axes.shape[0]/axes.shape[1]
        f.set_size_inches(11.0, ypngsiz)
        if pcadesc != "":
            pgtxt = ""
            if len(pages) != 1:
                pgtxt = ", page {0:d}/{1:d}".format(i+1, len(pages))
            f.suptitle(pcadesc + pgtxt, y=1.02, size=16)
        f.tight_layout()
        if show:
            plt.show()
        else:
            outfile = outroot+'{:02d}.png'.format(i)
            f.savefig(outfile, dpi=200)
        plt.close()
        f.clf()
    del f

    plt.rcdefaults()

    return
예제 #12
0
def plot_tilt_spat(tilts_dspat, tilts, tilts_model, tilts_spec_fit, tot_mask, rej_mask,spat_order, spec_order, rms, fwhm,
                   setup='A', slit=0, outfile=None, show_QA=False, out_dir=None):


    import matplotlib as mpl
    from matplotlib.lines import Line2D

    plt.rcdefaults()
    plt.rcParams['font.family']= 'Helvetica'

    # Outfil
    method = inspect.stack()[0][3]
    if (outfile is None):
        outfile = qa.set_qa_filename(setup, method, slit=slit, out_dir=out_dir)

    nspat, nuse = tilts_dspat.shape
    # Show the fit residuals as a function of spatial position
    line_indx = np.outer(np.ones(nspat), np.arange(nuse))
    lines_spec = tilts_spec_fit[0, :]
    cmap = mpl.cm.get_cmap('coolwarm', nuse)

    fig, ax = plt.subplots(figsize=(14, 12))
    # dummy mappable shows the spectral pixel
    dummie_cax = ax.scatter(lines_spec, lines_spec, c=lines_spec, cmap=cmap)
    ax.cla()

    for iline in range(nuse):
        iall = (line_indx == iline) & tot_mask
        irej = (line_indx == iline) & tot_mask & rej_mask
        this_color = cmap(iline)
        # plot the residuals
        ax.plot(tilts_dspat[iall], tilts[iall] - tilts_model[iall], color=this_color,
                linestyle='-', linewidth=3.0, marker='None', alpha=0.5)
        ax.plot(tilts_dspat[irej], tilts[irej] - tilts_model[irej], linestyle=' ',
                marker='o', color='limegreen', mfc='limegreen', markersize=5.0)

    xmin = 1.1 * tilts_dspat[tot_mask].min()
    xmax = 1.1 * tilts_dspat[tot_mask].max()
    ax.hlines(0.0, xmin, xmax, linestyle='--', linewidth=2.0, color='k', zorder=10)

    ax.set_xlim((xmin, xmax))
    ax.set_xlabel('Spatial Offset from Central Trace (pixels)')
    ax.set_ylabel('Arc Line Tilt Residual (pixels)')

    legend_elements = [Line2D([0], [0], color='cornflowerblue', linestyle='-', linewidth=3.0, label='residual'),
                       Line2D([0], [0], color='limegreen', linestyle=' ', marker='o', mfc='limegreen', markersize=7.0,
                              label='rejected')]
    ax.legend(handles=legend_elements)
    ax.set_title('Tilts vs Fit (spat_order, spec_order)=({:d},{:d}) for slit={:d}: RMS = {:5.3f}, '
                 'RMS/FWHM={:5.3f}'.format(spat_order, spec_order, slit, rms, rms / fwhm), fontsize=15)
    cb = fig.colorbar(dummie_cax, ticks=lines_spec)
    cb.set_label('Spectral Pixel')

    # Finish
    plt.tight_layout(pad=0.2, h_pad=0.0, w_pad=0.0)

    if outfile is not None:
        plt.savefig(outfile, dpi=400)

    if show_QA:
        plt.show()

    plt.close()
    plt.rcdefaults()
예제 #13
0
def plot_tilt_spec(tilts_spec_fit, tilts, tilts_model, tot_mask, rej_mask, rms, fwhm,
                   slit=0, setup = 'A', outfile=None, show_QA=False, out_dir=None):
    """ Generate a QA plot of the residuals for the fit to the tilts in the spectral direction one slit at a time

    Parameters
    ----------
    """

    plt.rcdefaults()
    plt.rcParams['font.family']= 'Helvetica'

    # Outfil
    method = inspect.stack()[0][3]
    if (outfile is None):
        outfile = qa.set_qa_filename(setup, method, slit=slit, out_dir=out_dir)

    # Setup
    plt.figure(figsize=(14, 6))
    plt.clf()
    ax = plt.gca()

    # Scatter plot
    res = (tilts - tilts_model)

    nspat, nuse = tilts.shape
    # Show the fit residuals as a function of spatial position
    line_indx = np.outer(np.ones(nspat), np.arange(nuse))

    xmin = 0.90*(tilts_spec_fit.min())
    xmax = 1.10*(tilts_spec_fit.max())

    ax.hlines(0.0, xmin, xmax,linestyle='--', color='green')

    for iline in range(nuse):
        iall = (line_indx == iline) & tot_mask
        igd = (line_indx == iline) & tot_mask & (rej_mask == False)
        irej = (line_indx == iline) & tot_mask & rej_mask

        ax.plot(tilts_spec_fit[igd], (res[igd]), 'ko', mfc='k', markersize=4.0)
        ax.plot(tilts_spec_fit[irej],(res[irej]), 'ro', mfc='r', markersize=4.0)
        # Compute the RMS for this line
        all_rms = np.std(res[iall])
        good_rms = np.std(res[igd])
        # ToDo show the mean here as well
        if np.any(igd):
            ax.plot(tilts_spec_fit[igd][0], all_rms, marker='s',linestyle=' ', color='g', mfc='g', markersize=7.0)
            ax.plot(tilts_spec_fit[igd][0], good_rms, marker='^', linestyle=' ', color='orange', mfc='orange', markersize=7.0)

    ax.text(0.90, 0.90, 'Slit {:d}:  Residual (pixels) = {:0.5f}'.format(slit, rms),
            transform=ax.transAxes, size='large', ha='right', color='black',fontsize=16)
    ax.text(0.90, 0.80, ' Slit {:d}:  RMS/FWHM = {:0.5f}'.format(slit, rms/fwhm),
            transform=ax.transAxes, size='large', ha='right', color='black',fontsize=16)
    # Label
    ax.set_xlabel('Spectral Pixel')
    ax.set_ylabel('RMS (pixels)')
    ax.set_title('RMS of Each Arc Line Traced')
    ax.set_xlim((xmin,xmax))
    ax.set_ylim((-5.0*rms,5.0*rms))
    # Legend
    legend_elements = [Line2D([0], [0],linestyle=' ', color='k', marker='o', mfc='k', markersize=4.0, label='good'),
                       Line2D([0], [0], linestyle=' ', color='r', marker='o', mfc='r', markersize=4.0, label='rejected'),
                       Line2D([0], [0], linestyle=' ', color='g', marker='s', mfc='g', markersize=7.0, label='all RMS'),
                       Line2D([0], [0], linestyle=' ', color='orange', marker='^', mfc='orange', markersize=7.0, label='good RMS')]
    ax.legend(handles=legend_elements)

    # Finish
    plt.tight_layout(pad=0.2, h_pad=0.0, w_pad=0.0)

    if outfile is not None:
        plt.savefig(outfile, dpi=400)

    if show_QA:
        plt.show()

    plt.close()
    plt.rcdefaults()
예제 #14
0
    def build_wv_calib(self, arccen, method, skip_QA=False):
        """
        Main routine to generate the wavelength solutions in a loop over slits
        Wrapper to arc.simple_calib or arc.calib_with_arclines

        self.maskslits is updated for slits that fail

        Args:
            method : str
              'simple' -- arc.simple_calib
              'arclines' -- arc.calib_with_arclines
              'holy-grail' -- wavecal.autoid.HolyGrail
              'reidentify' -- wavecal.auotid.ArchiveReid
              'identify' -- wavecal.identify.Identify
              'full_template' -- wavecal.auotid.full_template
            skip_QA (bool, optional)

        Returns:
            dict:  self.wv_calib
        """
        # Obtain a list of good slits
        ok_mask_idx = np.where(np.invert(self.wvc_bpm))[0]

        # Obtain calibration for all slits
        if method == 'simple':
            lines = self.par['lamps']
            line_lists = waveio.load_line_lists(lines)

            final_fit = arc.simple_calib_driver(
                line_lists,
                arccen,
                ok_mask_idx,
                n_final=self.par['n_final'],
                sigdetect=self.par['sigdetect'],
                IDpixels=self.par['IDpixels'],
                IDwaves=self.par['IDwaves'])
#        elif method == 'basic':
#            final_fit = {}
#            for slit in ok_mask:
#                status, ngd_match, match_idx, scores, ifinal_fit = \
#                        autoid.basic(arccen[:, slit], self.par['lamps'], self.par['wv_cen'],
#                                     self.par['disp'], nonlinear_counts=self.nonlinear_counts)
#                final_fit[str(slit)] = ifinal_fit.copy()
#                if status != 1:
#                    self.maskslits[slit] = True
        elif method == 'holy-grail':
            # Sometimes works, sometimes fails
            arcfitter = autoid.HolyGrail(
                arccen,
                par=self.par,
                ok_mask=ok_mask_idx,
                nonlinear_counts=self.nonlinear_counts)
            patt_dict, final_fit = arcfitter.get_results()
        elif method == 'identify':
            final_fit = {}
            # Manually identify lines
            msgs.info("Initializing the wavelength calibration tool")
            # TODO: Move this loop to the GUI initalise method
            embed()
            for slit_idx in ok_mask_idx:
                arcfitter = gui_identify.initialise(arccen,
                                                    slit=slit_idx,
                                                    par=self.par)
                final_fit[str(slit_idx)] = arcfitter.get_results()
                if final_fit[str(slit_idx)] is not None:
                    ans = 'y'
                    # ans = ''
                    # while ans != 'y' and ans != 'n':
                    #     ans = input("Would you like to store this wavelength solution in the archive? (y/n): ")
                    if ans == 'y' and final_fit[str(
                            slit_idx)]['rms'] < self.par['rms_threshold']:
                        # Store the results in the user reid arxiv
                        specname = self.spectrograph.spectrograph
                        gratname = "UNKNOWN"  # input("Please input the grating name: ")
                        dispangl = "UNKNOWN"  # input("Please input the dispersion angle: ")
                        templates.pypeit_identify_record(
                            final_fit[str(slit_idx)], self.binspectral,
                            specname, gratname, dispangl)
                        msgs.info("Your wavelength solution has been stored")
                        msgs.info(
                            "Please consider sending your solution to the PYPEIT team!"
                        )

        elif method == 'reidentify':
            # Now preferred
            # Slit positions
            arcfitter = autoid.ArchiveReid(
                arccen,
                self.spectrograph,
                self.par,
                ok_mask=ok_mask_idx,
                slit_spat_pos=self.spat_coo,
                nonlinear_counts=self.nonlinear_counts)
            patt_dict, final_fit = arcfitter.get_results()
        elif method == 'full_template':
            # Now preferred
            if self.binspectral is None:
                msgs.error(
                    "You must specify binspectral for the full_template method!"
                )
            final_fit = autoid.full_template(
                arccen,
                self.par,
                ok_mask_idx,
                self.det,
                self.binspectral,
                nonlinear_counts=self.nonlinear_counts,
                nsnippet=self.par['nsnippet'])
        else:
            msgs.error(
                'Unrecognized wavelength calibration method: {:}'.format(
                    method))

        # Convert keys to spatial system
        self.wv_calib = {}
        tmp = copy.deepcopy(final_fit)
        for idx in range(self.slits.nslits):
            if str(idx) in final_fit.keys():
                self.wv_calib[str(self.slits.slitord_id[idx])] = final_fit.pop(
                    str(idx))

        # Update mask
        self.update_wvmask()

        #TODO For generalized echelle (not hard wired) assign order number here before, i.e. slits.ech_order

        # QA
        if not skip_QA:
            ok_mask_idx = np.where(np.invert(self.wvc_bpm))[0]
            for slit_idx in ok_mask_idx:
                outfile = qa.set_qa_filename(
                    self.master_key,
                    'arc_fit_qa',
                    slit=self.slits.slitord_id[slit_idx],
                    out_dir=self.qa_path)
                autoid.arc_fit_qa(self.wv_calib[str(
                    self.slits.slitord_id[slit_idx])],
                                  outfile=outfile)

        # Return
        self.steps.append(inspect.stack()[0][3])
        return self.wv_calib
예제 #15
0
def wv_calib_from_extern(wave_soln,
                         arc,
                         lamps,
                         outfile=None,
                         sigdetect=5.0,
                         fwhm=4.0,
                         nonlinear_counts=1e10,
                         outroot='./',
                         debug=False):
    """

    Args:
        wave_soln:
        arc:
        lamps:
        outfile:
        sigdetect:
        fwhm:
        nonlinear_counts:
        outroot:
        debug:

    Returns:

    """

    # TODO add array size checking etc.
    nslits = wave_soln.shape[1]
    nspec = wave_soln.shape[0]
    line_lists = wavecal.waveio.load_line_lists(lamps)
    wv_calib = {}
    spec_vec = np.arange(nspec)
    for islit in range(nslits):
        print(str(islit))
        # Find peaks for this slit
        tcent, ecent, cut_tcent, icut, spec_cont_sub = wavecal.wvutils.arc_lines_from_spec(
            arc[:, islit],
            sigdetect=sigdetect,
            nonlinear_counts=nonlinear_counts,
            fwhm=fwhm,
            debug=debug)
        detections = tcent[icut]
        wave_det = (scipy.interpolate.interp1d(spec_vec,
                                               wave_soln[:, islit],
                                               kind='cubic'))(detections)
        patt_dict = {}
        patt_dict['mask'] = np.ones_like(detections, dtype=bool)
        patt_dict['IDs'] = wave_det
        patt_dict['bdisp'] = (np.max(wave_soln[:, islit]) -
                              np.min(wave_soln[:, islit])) / nspec
        final_fit = wavecal.fitting.fit_slit(spec_cont_sub,
                                             patt_dict,
                                             detections,
                                             line_lists,
                                             vel_tol=300.0,
                                             outroot=outroot,
                                             verbose=True)
        wv_calib[str(islit)] = final_fit
        qa_file = qa.set_qa_filename('GNIRS',
                                     'arc_fit_qa',
                                     slit=islit,
                                     out_dir=outroot)
        wavecal.qa.arc_fit_qa(wv_calib[str(islit)], outfile=qa_file)
        if debug:
            # Show the QA
            wavecal.qa.arc_fit_qa(wv_calib[str(islit)])

    waveCalib = wavecalib.WaveCalib(None, None)
    if outfile is not None:
        waveCalib.save_master(wv_calib, outfile=outfile)

    return wv_calib
예제 #16
0
파일: flexure.py 프로젝트: mcoughlin/PypeIt
def spec_flexure_qa(slitords,
                    bpm,
                    basename,
                    det,
                    flex_list,
                    specobjs=None,
                    out_dir=None):
    """

    Args:
        slitords (`numpy.ndarray`_):
            Array of slit/order numbers
        bpm (`numpy.ndarray`_):
            True = masked slit
        basename (str):
        det (int):
        flex_list (list):
        specobjs: (:class:`pypeit.specobjs.Specobjs`)
            Spectrally extracted objects
        out_dir:

    """
    plt.rcdefaults()
    plt.rcParams['font.family'] = 'times new roman'

    # What type of QA are we doing
    slit_cen = False
    if specobjs is None: slit_cen = True

    # Grab the named of the method
    method = inspect.stack()[0][3]

    # Mask
    gdslits = np.where(np.invert(bpm))[0]

    # Loop over slits, and then over objects here
    for islit in gdslits:
        # Slit/order number
        slitord = slitords[islit]

        # Parse and Setup
        if slit_cen:
            nobj = 1
            ncol = 1
        else:
            indx = specobjs.slitorder_indices(slitord)
            this_specobjs = specobjs[indx]
            nobj = np.sum(indx)
            if nobj == 0:
                continue
            ncol = min(3, nobj)
        this_flex_dict = flex_list[islit]

        # Check that the default was overwritten
        if len(this_flex_dict['shift']) == 0:
            continue

        nrow = nobj // ncol + ((nobj % ncol) > 0)
        # Outfile, one QA file per slit
        outfile = qa.set_qa_filename(basename,
                                     method + '_corr',
                                     det=det,
                                     slit=slitord,
                                     out_dir=out_dir)
        plt.figure(figsize=(8, 5.0))
        plt.clf()
        gs = gridspec.GridSpec(nrow, ncol)
        # TODO -- This cntr is crummy and needs to be replaced by a DataContainer
        #  for flex_dict and flex_list
        cntr = 0
        # Correlation QA
        if slit_cen:
            ax = plt.subplot(gs[0, 0])
            spec_flexure_corrQA(ax, this_flex_dict, cntr, 'Slit Center')
        else:
            for specobj in this_specobjs:
                if specobj is None or (specobj.BOX_WAVE is None
                                       and specobj.OPT_WAVE is None):
                    continue
                ax = plt.subplot(gs[cntr // ncol, cntr % ncol])
                spec_flexure_corrQA(ax, this_flex_dict, cntr,
                                    '{:s}'.format(specobj.NAME))
                cntr += 1
        # Finish
        plt.tight_layout(pad=0.2, h_pad=0.0, w_pad=0.0)
        plt.savefig(outfile, dpi=400)
        plt.close()

        # Sky line QA (just one object)
        if slit_cen:
            iobj = 0
        else:
            iobj = 0
            specobj = this_specobjs[iobj]

        # Repackage
        sky_spec = this_flex_dict['sky_spec'][iobj]
        arx_spec = this_flex_dict['arx_spec'][iobj]
        min_wave = max(np.amin(arx_spec.wavelength.value),
                       np.amin(sky_spec.wavelength.value)) * units.AA
        max_wave = min(np.amax(arx_spec.wavelength.value),
                       np.amax(sky_spec.wavelength.value)) * units.AA

        # Sky lines
        sky_lines = np.array([
            3370.0, 3914.0, 4046.56, 4358.34, 5577.338, 6300.304, 7340.885,
            7993.332, 8430.174, 8919.610, 9439.660, 10013.99, 10372.88
        ]) * units.AA
        dwv = 20. * units.AA
        gdsky = np.where((sky_lines > min_wave) & (sky_lines < max_wave))[0]
        if len(gdsky) == 0:
            msgs.warn("No sky lines for Flexure QA")
            continue
        if len(gdsky) > 6:
            idx = np.array(
                [0, 1, len(gdsky) // 2,
                 len(gdsky) // 2 + 1, -2, -1])
            gdsky = gdsky[idx]

        # Outfile
        outfile = qa.set_qa_filename(basename,
                                     method + '_sky',
                                     det=det,
                                     slit=slitord,
                                     out_dir=out_dir)
        # Figure
        plt.figure(figsize=(8, 5.0))
        plt.clf()
        nrow, ncol = 2, 3
        gs = gridspec.GridSpec(nrow, ncol)
        if slit_cen:
            plt.suptitle('Sky Comparison for Slit Center', y=1.05)
        else:
            plt.suptitle('Sky Comparison for {:s}'.format(specobj.NAME),
                         y=1.05)

        for ii, igdsky in enumerate(gdsky):
            skyline = sky_lines[igdsky]
            ax = plt.subplot(gs[ii // ncol, ii % ncol])
            # Norm
            pix1 = np.where(np.abs(sky_spec.wavelength - skyline) < dwv)[0]
            pix2 = np.where(np.abs(arx_spec.wavelength - skyline) < dwv)[0]
            f1 = np.sum(sky_spec.flux[pix1])
            f2 = np.sum(arx_spec.flux[pix2])
            norm = f1 / f2
            # Plot
            ax.plot(sky_spec.wavelength[pix1],
                    sky_spec.flux[pix1],
                    'k-',
                    label='Obj',
                    drawstyle='steps-mid')
            ax.plot(arx_spec.wavelength[pix2],
                    arx_spec.flux[pix2] * norm,
                    'r-',
                    label='Arx',
                    drawstyle='steps-mid')
            # Axes
            ax.xaxis.set_major_locator(plt.MultipleLocator(dwv.value))
            ax.set_xlabel('Wavelength')
            ax.set_ylabel('Counts')

        # Legend
        plt.legend(loc='upper left',
                   scatterpoints=1,
                   borderpad=0.3,
                   handletextpad=0.3,
                   fontsize='small',
                   numpoints=1)

        # Finish
        plt.savefig(outfile, dpi=400)
        plt.close()
        msgs.info("Wrote spectral flexure QA: {}".format(outfile))
        #plt.close()

    plt.rcdefaults()