Example #1
0
    def show(self, item, slit=None):
        """
        Show one of the class internals

        Args:
            item (str):
              'spec' -- Show the fitted points and solution;  requires slit
              'fit' -- Show fit QA; requires slit
            slit (int, optional):

        Returns:

        """
        if item == 'spec':
            # spec
            spec = self.wv_calib[str(slit)]['spec']
            # tcent
            tcent = self.wv_calib[str(slit)]['tcent']
            yt = np.zeros_like(tcent)
            for jj, t in enumerate(tcent):
                it = int(np.round(t))
                yt[jj] = np.max(spec[it - 1:it + 1])
            # Plot
            plt.clf()
            ax = plt.gca()
            ax.plot(spec, drawstyle='steps-mid')
            ax.scatter(tcent, yt, color='red', marker='*')
            ax.set_xlabel('Pixel')
            ax.set_ylabel('Counts')
            plt.show()
        elif item == 'fit':
            autoid.arc_fit_qa(self.wv_calib[str(slit)])
Example #2
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
Example #3
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
Example #4
0
def main(flg):

    # Keck LRISb
    if flg & (2**0): # B300, all lamps
        binspec = 1
        slits = [15]
        xidl_file = os.path.join(template_path, 'Keck_LRIS', 'B300', 'lris_blue_300.sav')
        outroot = 'keck_lris_blue_300_d680.fits'
        build_template(xidl_file, slits, None, binspec, outroot, lowredux=True)

    if flg & (2**1): # B400, all lamps I think)
        binspec = 2
        outroot='keck_lris_blue_400_d560.fits'
        slits = [19,14]
        lcut = [5500.]
        xidl_file = os.path.join(template_path, 'Keck_LRIS', 'B400', 'lris_blue_400_d560.sav')
        build_template(xidl_file, slits, lcut, binspec, outroot, lowredux=True)

    if flg & (2**2): # B600, all lamps
        binspec = 2
        outroot='keck_lris_blue_600_d560.fits'
        slits = [0,7]
        lcut = [4500.]
        wfile = os.path.join(template_path, 'Keck_LRIS', 'B600', 'MasterWaveCalib_A_1_01.json')
        build_template(wfile, slits, lcut, binspec, outroot, lowredux=False)

    if flg & (2**3): # B1200, all lamps?
        binspec = 2
        outroot='keck_lris_blue_1200_d460.fits'
        slits = [19,44]
        lcut = [3700.]
        xidl_file = os.path.join(template_path, 'Keck_LRIS', 'B1200', 'lris_blue_1200.sav')
        build_template(xidl_file, slits, lcut, binspec, outroot, lowredux=True)

    # Shane Kastb
    if flg & (2**4):  # 452/3306
        binspec = 1
        slits = [0]
        xidl_file = os.path.join(template_path, 'Shane_Kast', '452_3306', 'kast_452_3306.sav')
        outroot = 'shane_kast_blue_452.fits'
        build_template(xidl_file, slits, None, binspec, outroot, lowredux=True)

    if flg & (2**5):  # 600/4310
        binspec = 1
        slits = [0,3]
        lcut = [4550.]
        xidl_file = os.path.join(template_path, 'Shane_Kast', '600_4310', 'kast_600_4310.sav')
        outroot = 'shane_kast_blue_600.fits'
        build_template(xidl_file, slits, lcut, binspec, outroot, lowredux=True)

    if flg & (2**6):  # 830/3460
        binspec = 1
        slits = [0]
        xidl_file = os.path.join(template_path, 'Shane_Kast', '830_3460', 'kast_830_3460.sav')
        outroot = 'shane_kast_blue_830.fits'
        build_template(xidl_file, slits, None, binspec, outroot, lowredux=True)

    # Keck/DEIMOS
    if flg & (2**7):  # 600ZD :: Might not go red enough
        binspec = 1
        slits = [0,1]
        lcut = [7192.]
        xidl_file = os.path.join(template_path, 'Keck_DEIMOS', '600ZD', 'deimos_600.sav')
        outroot = 'keck_deimos_600.fits'
        build_template(xidl_file, slits, lcut, binspec, outroot, lowredux=True)

    if flg & (2**8):  # 830G
        binspec = 1
        outroot='keck_deimos_830G.fits'
        # 3-12 = blue  6508 -- 8410
        # 7-24 = blue  8497 -- 9925 (no lines after XeI)
        ifiles = [0, 0, 1]
        slits = [12, 14, 24]
        lcut = [8400., 8480]
        wfile1 = os.path.join(template_path, 'Keck_DEIMOS', '830G_M_8600', 'MasterWaveCalib_A_1_03.json')
        wfile2 = os.path.join(template_path, 'Keck_DEIMOS', '830G_M_8600', 'MasterWaveCalib_A_1_07.json')
        # det_dict
        det_cut = {}
        det_cut['dets'] = [[1,2,3,4], [5,6,7,8]]
        det_cut['wcuts'] = [[0,9000.], [8200,1e9]]  # Significant overlap is fine
        #
        build_template([wfile1,wfile2], slits, lcut, binspec, outroot, lowredux=False,
                       ifiles=ifiles, det_cut=det_cut)

    if flg & (2**9):  # 1200
        binspec = 1
        outroot='keck_deimos_1200G.fits'
        # 3-3 = blue  6268.23 -- 7540
        # 3-14 = red   6508 -- 7730
        # 7-3 = blue  7589 -- 8821
        # 7-17 = red  8000 - 9230
        # 7c-0 = red  9120 -- 9950
        ifiles = [0, 0, 1, 1, 2]
        slits = [3, 14, 3, 17, 0]
        lcut = [7450., 7730., 8170, 9120]
        wfile1 = os.path.join(template_path, 'Keck_DEIMOS', '1200G', 'MasterWaveCalib_A_1_03.json')
        wfile2 = os.path.join(template_path, 'Keck_DEIMOS', '1200G', 'MasterWaveCalib_A_1_07.json')
        wfile3 = os.path.join(template_path, 'Keck_DEIMOS', '1200G', 'MasterWaveCalib_A_1_07c.json')
        # det_dict
        det_cut = None
        #det_cut = {}
        #det_cut['dets'] = [[1,2,3,4], [5,6,7,8]]
        #det_cut['wcuts'] = [[0,9000.], [8200,1e9]]  # Significant overlap is fine
        #
        build_template([wfile1,wfile2,wfile3], slits, lcut, binspec, outroot, lowredux=False,
                       ifiles=ifiles, det_cut=det_cut, chk=True)

    # ###############################################3
    # Keck/LRISr
    if flg & (2**10): # R400
        binspec = 2
        outroot='keck_lris_red_400.fits'
        slits = [7]  # Quite blue, but not the bluest
        lcut = []
        wfile = os.path.join(template_path, 'Keck_LRIS', 'R400', 'MasterWaveCalib_A_1_01.json')
        build_template(wfile, slits, lcut, binspec, outroot, lowredux=False)

    if flg & (2**11):  # R1200
        # slits = [2-3]  # 7726 -- 9250
        # slits = [1-4]  # 9250 -- 9925
        binspec = 1
        outroot='keck_lris_red_1200_9000.fits'
        ifiles = [0, 1]
        slits = [3, 7]
        lcut = [9250.]
        wfile1 = os.path.join(template_path, 'Keck_LRIS', 'R1200_9000', 'MasterWaveCalib_A_1_02.json')  # Original Dev
        wfile2 = os.path.join(template_path, 'Keck_LRIS', 'R1200_9000', 'MasterWaveCalib_A_1_01.json')  # Dev suite 2x1
        build_template([wfile1,wfile2], slits, lcut, binspec, outroot, lowredux=False,
                       ifiles=ifiles)

    if flg & (2**12):  # R600/5000
        # slits = [1-4]  # 5080 -- 7820
        # slits = [1-7]  # 7820 -- 9170
        binspec = 2
        outroot='keck_lris_red_600_5000.fits'
        slits = [4, 7]
        lcut = [7820.]
        wfile = os.path.join(template_path, 'Keck_LRIS', 'R600_5000', 'MasterWaveCalib_B_1_01.json')
        build_template(wfile, slits, lcut, binspec, outroot, lowredux=False)

    if flg & (2**27):  # R600/7500
        # slits = [1-10]  # 5000 -- 7840
        # slits = [1-4]  # 7840 -- 9230
        binspec = 2
        outroot='keck_lris_red_600_7500.fits'
        slits = [10, 4]
        lcut = [7840.]
        wfile = os.path.join(template_path, 'Keck_LRIS', 'R600_7500', 'MasterWaveCalib_I_1_01.json')
        build_template(wfile, slits, lcut, binspec, outroot, lowredux=False,
                       chk=True, normalize=True, subtract_conti=True)

    # ##################################
    # Magellan/MagE
    if flg & (2**13):
        # Load
        mase_path = os.path.join(os.getenv('XIDL_DIR'), 'Magellan', 'MAGE', 'mase', 'Calib')
        sav_file = os.path.join(mase_path, 'MagE_wvguess_jfh.idl')
        mase_dict = readsav(sav_file)
        mase_sol = Table(mase_dict['all_arcfit'])
        # Do it
        all_wave = np.zeros((2048, 15))
        all_flux = np.zeros_like(all_wave)
        for order in np.arange(15):
            all_flux[:,order] = mase_dict['sv_aspec'][order]
            # Build the wavelengths
            wv_air = cheby_val(mase_sol['FFIT'][order], np.arange(2048), mase_sol['NRM'][order],
                                         mase_sol['NORD'][order])
            all_wave[:,order] = airtovac(wv_air * units.AA).value
        # Write
        tbl = Table()
        tbl['wave'] = all_wave.T
        tbl['flux'] = all_flux.T
        tbl['order'] = np.arange(20, 5, -1, dtype=int)
        tbl.meta['BINSPEC'] = 1
        # Write
        outroot='magellan_mage.fits'
        outfile = os.path.join(template_path, outroot)
        tbl.write(outfile, overwrite=True)
        print("Wrote: {}".format(outfile))

    if flg & (2**14):  # Magellan/MagE Plots
        outpath = os.path.join(resource_filename('pypeit', 'data'), 'arc_lines', 'plots')
        new_mage_file = os.path.join(resource_filename('pypeit', 'data'), 'arc_lines', 'reid_arxiv',
                                     'magellan_mage.fits')
        # Load
        mage_wave = Table.read(new_mage_file)
        llist = waveio.load_line_lists(['ThAr_MagE'])
        #
        for kk in range(mage_wave['wave'].shape[1]):
            wv = mage_wave['wave'][:, kk]
            fx = mage_wave['flux'][:, kk]
            order = 20 - kk
            # Reidentify
            detections, spec_cont_sub, patt_dict = autoid.reidentify(fx, fx, wv, llist, 1)
            # Fit
            final_fit = fitting.fit_slit(fx, patt_dict, detections, llist)
            # Output
            outfile=os.path.join(outpath, 'MagE_order{:2d}_IDs.pdf'.format(order))
            autoid.arc_fit_qa(final_fit, outfile=outfile, ids_only=True)
            print("Wrote: {}".format(outfile))
            autoid.arc_fit_qa(final_fit, outfile=os.path.join(outpath, 'MagE_order{:2d}_full.pdf'.format(order)))

    if flg & (2**15):  # VLT/X-Shooter reid_arxiv
        # VIS
        reid_path = os.path.join(resource_filename('pypeit', 'data'), 'arc_lines', 'reid_arxiv')
        for iroot, iout in zip(['vlt_xshooter_vis1x1.json', 'vlt_xshooter_nir.json'],
            ['vlt_xshooter_vis1x1.fits', 'vlt_xshooter_nir.fits']):
            # Load
            old_file = os.path.join(reid_path, iroot)
            odict, par = waveio.load_reid_arxiv(old_file)

            # Do it
            orders = odict['fit2d']['orders'][::-1].astype(int)  # Flipped
            all_wave = np.zeros((odict['0']['nspec'], orders.size))
            all_flux = np.zeros_like(all_wave)
            for kk,order in enumerate(orders):
                all_flux[:,kk] = odict[str(kk)]['spec']
                if 'nir' in iroot:
                    all_wave[:,kk] = odict[str(kk)]['wave_soln']
                else:
                    all_wave[:,kk] = airtovac(odict[str(kk)]['wave_soln'] * units.AA).value
            # Write
            tbl = Table()
            tbl['wave'] = all_wave.T
            tbl['flux'] = all_flux.T
            tbl['order'] = orders
            tbl.meta['BINSPEC'] = 1
            # Write
            outfile = os.path.join(reid_path, iout)
            tbl.write(outfile, overwrite=True)
            print("Wrote: {}".format(outfile))

    if flg & (2**16):  # VLT/X-Shooter line list
        line_path = os.path.join(resource_filename('pypeit', 'data'), 'arc_lines', 'lists')
        old_file = os.path.join(line_path, 'ThAr_XSHOOTER_VIS_air_lines.dat')
        # Load
        air_list = waveio.load_line_list(old_file)
        # Vacuum
        vac_wv = airtovac(air_list['wave']*units.AA).value
        vac_list = air_list.copy()
        vac_list['wave'] = vac_wv
        # Write
        new_file = os.path.join(line_path, 'ThAr_XSHOOTER_VIS_lines.dat')
        vac_list.write(new_file, format='ascii.fixed_width', overwrite=True)
        print("Wrote: {}".format(new_file))

    if flg & (2**17):  # NIRES
        reid_path = os.path.join(resource_filename('pypeit', 'data'), 'arc_lines', 'reid_arxiv')
        iroot = 'keck_nires.json'
        iout = 'keck_nires.fits'
        # Load
        old_file = os.path.join(reid_path, iroot)
        odict, par = waveio.load_reid_arxiv(old_file)

        # Do it
        orders = odict['fit2d']['orders'][::-1].astype(int)  # Flipped
        all_wave = np.zeros((odict['0']['nspec'], orders.size))
        all_flux = np.zeros_like(all_wave)
        for kk,order in enumerate(orders):
            all_flux[:,kk] = odict[str(kk)]['spec']
            if 'nir' in iroot:
                all_wave[:,kk] = odict[str(kk)]['wave_soln']
            else:
                all_wave[:,kk] = airtovac(odict[str(kk)]['wave_soln'] * units.AA).value
        # Write
        tbl = Table()
        tbl['wave'] = all_wave.T
        tbl['flux'] = all_flux.T
        tbl['order'] = orders
        tbl.meta['BINSPEC'] = 1
        # Write
        outfile = os.path.join(reid_path, iout)
        tbl.write(outfile, overwrite=True)
        print("Wrote: {}".format(outfile))


    if flg & (2**18):  # Gemini/GNIRS
        reid_path = os.path.join(resource_filename('pypeit', 'data'), 'arc_lines', 'reid_arxiv')
        iroot = 'gemini_gnirs.json'
        iout = 'gemini_gnirs.fits'
        # Load
        old_file = os.path.join(reid_path, iroot)
        odict, par = waveio.load_reid_arxiv(old_file)

        # Do it
        orders = odict['fit2d']['orders'][::-1].astype(int)  # Flipped
        all_wave = np.zeros((odict['0']['nspec'], orders.size))
        all_flux = np.zeros_like(all_wave)
        for kk,order in enumerate(orders):
            all_flux[:,kk] = odict[str(kk)]['spec']
            if 'nir' in iroot:
                all_wave[:,kk] = odict[str(kk)]['wave_soln']
            else:
                all_wave[:,kk] = airtovac(odict[str(kk)]['wave_soln'] * units.AA).value
        # Write
        tbl = Table()
        tbl['wave'] = all_wave.T
        tbl['flux'] = all_flux.T
        tbl['order'] = orders
        tbl.meta['BINSPEC'] = 1
        # Write
        outfile = os.path.join(reid_path, iout)
        tbl.write(outfile, overwrite=True)
        print("Wrote: {}".format(outfile))

    # ##############################
    if flg & (2**20):  # GMOS R400 Hamamatsu
        binspec = 2
        outroot='gemini_gmos_r400_ham.fits'
        #
        ifiles = [0, 1, 2, 3, 4]
        slits = [0, 2, 3, 0, 0]  # Be careful with the order..
        lcut = [5400., 6620., 8100., 9000.]
        wfile1 = os.path.join(template_path, 'GMOS', 'R400', 'MasterWaveCalib_A_01_aa.json')
        wfile5 = os.path.join(template_path, 'GMOS', 'R400', 'MasterWaveCalib_A_05_aa.json') # 5190 -- 6679
        #wfile2 = os.path.join(template_path, 'GMOS', 'R400', 'MasterWaveCalib_A_02_aa.json')
        wfile3 = os.path.join(template_path, 'GMOS', 'R400', 'MasterWaveCalib_A_04_aa.json')
        wfile4 = os.path.join(template_path, 'GMOS', 'R400', 'MasterWaveCalib_A_03_aa.json')
        wfile6 = os.path.join(template_path, 'GMOS', 'R400', 'MasterWaveCalib_A_06_aa.json')
        #
        build_template([wfile1,wfile5,wfile3,wfile4, wfile6], slits, lcut, binspec,
                       outroot, lowredux=False, ifiles=ifiles, chk=True,
                       normalize=True, subtract_conti=True)


    # ##############################
    if flg & (2**21):  # GMOS R400 E2V
        binspec = 2
        outroot='gemini_gmos_r400_e2v.fits'
        #
        ifiles = [0, 1, 2]
        slits = [0, 0, 0]
        lcut = [6000., 7450]
        wfile1 = os.path.join(template_path, 'GMOS', 'R400', 'MasterWaveCalib_A_1_01.json')
        wfile2 = os.path.join(template_path, 'GMOS', 'R400', 'MasterWaveCalib_A_1_02.json')
        wfile3 = os.path.join(template_path, 'GMOS', 'R400', 'MasterWaveCalib_A_1_03.json')
        #
        build_template([wfile1,wfile2,wfile3], slits, lcut, binspec,
                       outroot, lowredux=False, ifiles=ifiles, chk=True,
                       normalize=True)

    # ##############################
    if flg & (2**22):  # GMOS R400 Hamamatsu
        binspec = 2
        outroot='gemini_gmos_b600_ham.fits'
        #
        ifiles = [0, 1, 2, 3, 4]
        slits = [0, 0, 0, 0, 0]
        lcut = [4250., 4547., 5250., 5615.]
        wfile1 = os.path.join(template_path, 'GMOS', 'B600', 'MasterWaveCalib_C_1_01.json')
        wfile5 = os.path.join(template_path, 'GMOS', 'B600', 'MasterWaveCalib_D_1_01.json') # - 4547
        wfile2 = os.path.join(template_path, 'GMOS', 'B600', 'MasterWaveCalib_C_1_02.json')
        wfile4 = os.path.join(template_path, 'GMOS', 'B600', 'MasterWaveCalib_D_1_02.json') # 4610-5608
        wfile3 = os.path.join(template_path, 'GMOS', 'B600', 'MasterWaveCalib_C_1_03.json')
        #
        build_template([wfile1,wfile5,wfile2,wfile4,wfile3], slits, lcut, binspec,
                       outroot, lowredux=False, ifiles=ifiles, chk=True,
                       normalize=True, subtract_conti=True, miny=-100.)

    if flg & (2**23):  # WHT/ISIS
        iroot = 'wht_isis_blue_1200_4800.json'
        outroot = 'wht_isis_blue_1200_4800.fits'
        wfile = os.path.join(template_path, 'WHT_ISIS', '1200B', iroot)
        binspec = 2
        slits = [0]
        lcut = [3200.]
        build_template(wfile, slits, lcut, binspec, outroot, lowredux=False)

    if flg & (2**24):  # Magellan/FIRE
        reid_path = os.path.join(resource_filename('pypeit', 'data'), 'arc_lines', 'reid_arxiv')
        iroot = 'magellan_fire_echelle.json'
        iout = 'magellan_fire_echelle.fits'
        # Load
        old_file = os.path.join(reid_path, iroot)
        odict, par = waveio.load_reid_arxiv(old_file)

        # Do it
        orders = odict['fit2d']['orders'][::-1].astype(int)  # Flipped
        all_wave = np.zeros((odict['0']['nspec'], orders.size))
        all_flux = np.zeros_like(all_wave)
        for kk,order in enumerate(orders):
            all_flux[:,kk] = odict[str(kk)]['spec']
            if 'nir' in iroot:
                all_wave[:,kk] = odict[str(kk)]['wave_soln']
            else:
                all_wave[:,kk] = airtovac(odict[str(kk)]['wave_soln'] * units.AA).value

        # Write
        tbl = Table()
        tbl['wave'] = all_wave.T
        tbl['flux'] = all_flux.T
        tbl['order'] = orders
        tbl.meta['BINSPEC'] = 1
        # Write
        outfile = os.path.join(reid_path, iout)
        tbl.write(outfile, overwrite=True)
        print("Wrote: {}".format(outfile))

    if flg & (2**25): # FIRE longslit
        binspec = 1
        reid_path = os.path.join(resource_filename('pypeit', 'data'), 'arc_lines', 'reid_arxiv')
        outroot = 'magellan_fire_long.fits'
        xidl_file = os.path.join(os.getenv('FIRE_DIR'), 'LowDispersion', 'NeNeAr_archive_fit.fits')
        spec_file = os.path.join(os.getenv('FIRE_DIR'), 'LowDispersion', 'NeNeAr2.sav')
        fire_sol = Table.read(xidl_file)
        wave = cheby_val(fire_sol['FFIT'].data[0], np.arange(2048), fire_sol['NRM'].data[0], fire_sol['NORD'].data[0])
        wv_vac = airtovac(wave * units.AA)
        xidl_dict = readsav(spec_file)
        flux = xidl_dict['arc1d']
        write_template(wv_vac.value, flux, binspec, reid_path, outroot, det_cut=None)

    # Gemini/Flamingos2
    if flg & (2**26):
        reid_path = os.path.join(resource_filename('pypeit', 'data'), 'arc_lines', 'reid_arxiv')
        iroot = ['Flamingos2_JH_JH.json','Flamingos2_HK_HK.json']
        outroot=['Flamingos2_JH_JH.fits','Flamingos2_HK_HK.fits']
        binspec = 1
        slits = [0]
        lcut = []
        for ii in range(len(iroot)):
            wfile = os.path.join(reid_path, iroot[ii])
            build_template(wfile, slits, lcut, binspec, outroot[ii], lowredux=False)


    # MDM/OSMOS -- MDM4K
    if flg & (2 ** 28):
        # ArI 4159 -- 6800
        wfile = os.path.join(template_path, 'MDM_OSMOS', 'MasterWaveCalib_MDM4K_01.json')
        outroot = 'mdm_osmos_mdm4k.fits'
        binspec = 1
        slits = [0]
        lcut = [3200.]
        build_template(wfile, slits, lcut, binspec, outroot, lowredux=False,
                       chk=True, subtract_conti=True)
Example #5
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 == '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
Example #6
0
def iterative_fitting(spec, tcent, ifit, IDs, llist, disp,
                      match_toler = 2.0, func = 'legendre', n_first=2, sigrej_first=2.0,
                      n_final=4, sigrej_final=3.0,
                      weights=None, plot_fil=None, verbose=False):

    """ Routine for iteratively fitting wavelength solutions.

    Parameters
    ----------
    spec : ndarray, shape = (nspec,)
      arcline spectrum
    tcent : ndarray
      Centroids in pixels of lines identified in spec
    ifit : ndarray
      Indices of the lines that will be fit
    IDs: ndarray
      wavelength IDs of the lines that will be fit (I think?)
    llist: dict
      Linelist dictionary
    disp: float
      dispersion

    Optional Parameters
    -------------------
    match_toler: float, default = 3.0
      Matching tolerance when searching for new lines. This is the difference in pixels between the wavlength assigned to
      an arc line by an iteration of the wavelength solution to the wavelength in the line list.
    func: str, default = 'legendre'
      Name of function used for the wavelength solution
    n_first: int, default = 2
      Order of first guess to the wavelength solution.
    sigrej_first: float, default = 2.0
      Number of sigma for rejection for the first guess to the wavelength solution.
    n_final: int, default = 4
      Order of the final wavelength solution fit
    sigrej_final: float, default = 3.0
      Number of sigma for rejection for the final fit to the wavelength solution.
    weights: ndarray
      Weights to be used?
    verbose : bool
      If True, print out more information.
    plot_fil:
      Filename for plotting some QA?

    Returns
    -------
    final_fit: dict
      Dictionary containing the full fitting results and the final best guess of the line IDs
    """

    #TODO JFH add error checking here to ensure that IDs and ifit have the same size!

    if weights is None:
        weights = np.ones(tcent.size)

    nspec = spec.size
    xnspecmin1 = float(nspec-1)
    # 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 = n_first
    flg_continue = True
    flg_penultimate = False
    fmin, fmax = 0.0, 1.0
    # Note the number of parameters is actually n_order and not n_order+1
    while flg_continue:
        if flg_penultimate:
            flg_continue = False
        # Fit with rejection
        xfit, yfit, wfit = tcent[ifit], all_ids[ifit], weights[ifit]
        mask, fit = utils.robust_polyfit(xfit/xnspecmin1, yfit, n_order, function=func, sigma=sigrej_first,
                                         minx=fmin, maxx=fmax, verbose=verbose, weights=wfit)

        rms_ang = utils.calc_fit_rms(xfit[mask == 0]/xnspecmin1, yfit[mask == 0], fit, func, minx=fmin, maxx=fmax,
                                     weights=wfit[mask == 0])
        rms_pix = rms_ang/disp
        if verbose:
            msgs.info('n_order = {:d}'.format(n_order) + ': RMS = {:g}'.format(rms_pix))

        # 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 = utils.func_val(fit, tcent/xnspecmin1, func, minx=fmin, maxx=fmax)
        for ss, iwave in enumerate(twave):
            mn = np.min(np.abs(iwave-llist['wave']))
            if mn/disp < 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 < n_final:
            n_order += 1
        else:
            flg_penultimate = True

    # Final fit (originals can now be rejected)
    #fmin, fmax = 0., 1.
    #xfit, yfit, wfit = tcent[ifit]/(nspec-1), all_ids[ifit], weights[ifit]
    xfit, yfit, wfit = tcent[ifit], all_ids[ifit], weights[ifit]
    mask, fit = utils.robust_polyfit(xfit/xnspecmin1, yfit, n_order, function=func, sigma=sigrej_final,
                                     minx=fmin, maxx=fmax, verbose=verbose, weights=wfit)#, 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 = utils.func_val(fit, xrej[kk]/xnspecmin1, func, minx=fmin, maxx=fmax)
                msgs.info('Rejecting arc line {:g}; {:g}'.format(yfit[imask], wave))
    else:
        xrej = []
        yrej = []

    #xfit = xfit[mask == 0]
    #yfit = yfit[mask == 0]
    #wfit = wfit[mask == 0]
    ions = all_idsion[ifit]
#    ions = all_idsion[ifit][mask == 0]
    # Final RMS
    rms_ang = utils.calc_fit_rms(xfit[mask==0]/xnspecmin1, yfit[mask==0], fit, func,
                                 minx=fmin, maxx=fmax, weights=wfit[mask==0])
#    rms_ang = utils.calc_fit_rms(xfit, yfit, fit, func,
#                                 minx=fmin, maxx=fmax, weights=wfit)
    rms_pix = rms_ang/disp

    # Pack up fit
    spec_vec = np.arange(nspec)
    wave_soln = utils.func_val(fit,spec_vec/xnspecmin1, func, minx=fmin, maxx=fmax)
    cen_wave = utils.func_val(fit, float(nspec)/2/xnspecmin1, func, minx=fmin, maxx=fmax)
    cen_wave_min1 = utils.func_val(fit, (float(nspec)/2 - 1.0)/xnspecmin1, func, minx=fmin, maxx=fmax)
    cen_disp = cen_wave - cen_wave_min1

    final_fit = dict(fitc=fit, function=func, pixel_fit=xfit, wave_fit=yfit, weights=wfit, ions=ions,
                     fmin=fmin, fmax=fmax, xnorm = xnspecmin1, nspec=nspec, cen_wave = cen_wave, cen_disp = cen_disp,
                     xrej=xrej, yrej=yrej, mask=(mask == 0), spec=spec, wave_soln = wave_soln, nrej=sigrej_final,
                     shift=0., tcent=tcent, rms=rms_pix)

    # If set to True, this will output a file that can then be included in the tests
    saveit = False
    if saveit:
        from linetools import utils as ltu
        jdict = ltu.jsonify(final_fit)
        if plot_fil is None:
            outname = "temp"
            print("You should have set the plot_fil directory to save wavelength fits... using 'temp' as a filename")
        else:
            outname = plot_fil
        ltu.savejson(outname + '.json', jdict, easy_to_read=True, overwrite=True)
        print(" Wrote: {:s}".format(outname + '.json'))

    # QA
    if plot_fil is not None:
        autoid.arc_fit_qa(final_fit, plot_fil)
    # Return
    return final_fit
Example #7
0
def iterative_fitting(spec, tcent, ifit, IDs, llist, disp,
                      match_toler = 2.0, func = 'legendre', n_first=2, sigrej_first=2.0,
                      n_final=4, sigrej_final=3.0, input_only=False,
                      weights=None, plot_fil=None, verbose=False):

    """ Routine for iteratively fitting wavelength solutions.

    Parameters
    ----------
    spec : ndarray, shape = (nspec,)
      arcline spectrum
    tcent : ndarray
      Centroids in pixels of lines identified in spec
    ifit : ndarray
      Indices of the lines that will be fit
    IDs: ndarray
      wavelength IDs of the lines that will be fit (I think?)
    llist: dict
      Linelist dictionary
    disp: float
      dispersion

    Optional Parameters
    -------------------
    match_toler: float, default = 3.0
      Matching tolerance when searching for new lines. This is the difference in pixels between the wavlength assigned to
      an arc line by an iteration of the wavelength solution to the wavelength in the line list.
    func: str, default = 'legendre'
      Name of function used for the wavelength solution
    n_first: int, default = 2
      Order of first guess to the wavelength solution.
    sigrej_first: float, default = 2.0
      Number of sigma for rejection for the first guess to the wavelength solution.
    n_final: int, default = 4
      Order of the final wavelength solution fit
    sigrej_final: float, default = 3.0
      Number of sigma for rejection for the final fit to the wavelength solution.
    input_only: bool
      If True, the routine will only perform a robust polyfit to the input IDs.
      If False, the routine will fit the input IDs, and then include additional
      lines in the linelist that are a satisfactory fit.
    weights: ndarray
      Weights to be used?
    verbose : bool
      If True, print out more information.
    plot_fil:
      Filename for plotting some QA?

    Returns
    -------
    final_fit: :class:`pypeit.core.wavecal.wv_fitting.WaveFit`
    """

    #TODO JFH add error checking here to ensure that IDs and ifit have the same size!

    if weights is None:
        weights = np.ones(tcent.size)

    nspec = spec.size
    xnspecmin1 = float(nspec-1)
    # 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 = n_first
    flg_continue = True
    flg_penultimate = False
    fmin, fmax = 0.0, 1.0
    # Note the number of parameters is actually n_order and not n_order+1
    while flg_continue:
        if flg_penultimate:
            flg_continue = False
        # Fit with rejection
        xfit, yfit, wfit = tcent[ifit], all_ids[ifit], weights[ifit]
        maxiter = xfit.size - n_order - 2
        #
        if xfit.size == 0:
            msgs.warn("All points rejected !!")
            return None
        # Fit
        pypeitFit = fitting.robust_fit(xfit/xnspecmin1, yfit, n_order, function=func, maxiter=maxiter,
                                       lower=sigrej_first, upper=sigrej_first, maxrej=1, sticky=True,
                                       minx=fmin, maxx=fmax, weights=wfit)
        # Junk fit?
        if pypeitFit is None:
            msgs.warn("Bad fit!!")
            return None

        rms_ang = pypeitFit.calc_fit_rms(apply_mask=True)
        rms_pix = rms_ang/disp
        if verbose:
            msgs.info('n_order = {:d}'.format(n_order) + ': RMS = {:g}'.format(rms_pix))

        # Reject but keep originals (until final fit)
        ifit = list(ifit[pypeitFit.gpm == 1]) + sv_ifit
        if not input_only:
            # Find new points from the linelist (should we allow removal of the originals?)
            twave = pypeitFit.eval(tcent/xnspecmin1)#, func, minx=fmin, maxx=fmax)
            for ss, iwave in enumerate(twave):
                mn = np.min(np.abs(iwave-llist['wave']))
                if mn/disp < 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 < n_final:
            n_order += 1
        else:
            flg_penultimate = True

    # Final fit (originals can now be rejected)
    xfit, yfit, wfit = tcent[ifit], all_ids[ifit], weights[ifit]
    pypeitFit = fitting.robust_fit(xfit/xnspecmin1, yfit, n_order, function=func,
                                   lower=sigrej_final, upper=sigrej_final, maxrej=1, sticky=True,
                                   minx=fmin, maxx=fmax, weights=wfit)#, debug=True)
    irej = np.where(np.logical_not(pypeitFit.bool_gpm))[0]
    if len(irej) > 0:
        xrej = xfit[irej]
        yrej = yfit[irej]
        if verbose:
            for kk, imask in enumerate(irej):
                wave = pypeitFit.eval(xrej[kk]/xnspecmin1)#, func, minx=fmin, maxx=fmax)
                msgs.info('Rejecting arc line {:g}; {:g}'.format(yfit[imask], wave))
    else:
        xrej = []
        yrej = []

    ions = all_idsion[ifit]
    # Final RMS
    rms_ang = pypeitFit.calc_fit_rms(apply_mask=True)
    rms_pix = rms_ang/disp

    # Pack up fit
    spec_vec = np.arange(nspec)
    wave_soln = pypeitFit.eval(spec_vec/xnspecmin1)
    cen_wave = pypeitFit.eval(float(nspec)/2/xnspecmin1)
    cen_wave_min1 = pypeitFit.eval((float(nspec)/2 - 1.0)/xnspecmin1)
    cen_disp = cen_wave - cen_wave_min1

    # Ions bit
    ion_bits = np.zeros(len(ions), dtype=WaveFit.bitmask.minimum_dtype())
    for kk,ion in enumerate(ions):
        ion_bits[kk] = WaveFit.bitmask.turn_on(ion_bits[kk], ion.replace(' ', ''))

    # DataContainer time
    # spat_id is set to an arbitrary -1 here and is updated in wavecalib.py
    final_fit = WaveFit(-1, pypeitfit=pypeitFit, pixel_fit=xfit, wave_fit=yfit,
                        ion_bits=ion_bits, xnorm=xnspecmin1,
                        cen_wave=cen_wave, cen_disp=cen_disp,
                        spec=spec, wave_soln = wave_soln, sigrej=sigrej_final,
                        shift=0., tcent=tcent, rms=rms_pix)

    # QA
    if plot_fil is not None:
        autoid.arc_fit_qa(final_fit, plot_fil)
    # Return
    return final_fit
Example #8
0
def main(flg):

    # Keck LRISb
    if flg & (2**0):  # B300, all lamps
        binspec = 1
        slits = [15]
        xidl_file = os.path.join(template_path, 'Keck_LRIS', 'B300',
                                 'lris_blue_300.sav')
        outroot = 'keck_lris_blue_300_d680.fits'
        build_template(xidl_file, slits, None, binspec, outroot, lowredux=True)

    if flg & (2**1):  # B400, all lamps I think)
        binspec = 2
        outroot = 'keck_lris_blue_400_d560.fits'
        slits = [19, 14]
        lcut = [5500.]
        xidl_file = os.path.join(template_path, 'Keck_LRIS', 'B400',
                                 'lris_blue_400_d560.sav')
        build_template(xidl_file, slits, lcut, binspec, outroot, lowredux=True)

    if flg & (2**2):  # B600, all lamps
        binspec = 2
        outroot = 'keck_lris_blue_600_d560.fits'
        slits = [0, 7]
        lcut = [4500.]
        wfile = os.path.join(template_path, 'Keck_LRIS', 'B600',
                             'MasterWaveCalib_A_1_01.json')
        build_template(wfile, slits, lcut, binspec, outroot, lowredux=False)

    if flg & (2**3):  # B1200, all lamps?
        binspec = 2
        outroot = 'keck_lris_blue_1200_d460.fits'
        slits = [19, 44]
        lcut = [3700.]
        xidl_file = os.path.join(template_path, 'Keck_LRIS', 'B1200',
                                 'lris_blue_1200.sav')
        build_template(xidl_file, slits, lcut, binspec, outroot, lowredux=True)

    # ###############################################3
    # Keck/LRISr
    if flg & (2**10):  # R400
        binspec = 2
        outroot = 'keck_lris_red_400.fits'
        slits = [7]  # Quite blue, but not the bluest
        lcut = []
        wfile = os.path.join(template_path, 'Keck_LRIS', 'R400',
                             'MasterWaveCalib_A_1_01.json')
        build_template(wfile, slits, lcut, binspec, outroot, lowredux=False)

    if flg & (2**11):  # R1200
        # slits = [2-3]  # 7726 -- 9250
        # slits = [1-4]  # 9250 -- 9925
        binspec = 1
        outroot = 'keck_lris_red_1200_9000.fits'
        ifiles = [0, 1]
        slits = [3, 7]
        lcut = [9250.]
        wfile1 = os.path.join(template_path, 'Keck_LRIS', 'R1200_9000',
                              'MasterWaveCalib_A_1_02.json')  # Original Dev
        wfile2 = os.path.join(template_path, 'Keck_LRIS', 'R1200_9000',
                              'MasterWaveCalib_A_1_01.json')  # Dev suite 2x1
        build_template([wfile1, wfile2],
                       slits,
                       lcut,
                       binspec,
                       outroot,
                       lowredux=False,
                       ifiles=ifiles)

    if flg & (2**12):  # R600/5000
        # slits = [1-4]  # 5080 -- 7820
        # slits = [1-7]  # 7820 -- 9170
        binspec = 2
        outroot = 'keck_lris_red_600_5000.fits'
        slits = [4, 7]
        lcut = [7820.]
        wfile = os.path.join(template_path, 'Keck_LRIS', 'R600_5000',
                             'MasterWaveCalib_B_1_01.json')
        build_template(wfile, slits, lcut, binspec, outroot, lowredux=False)

    if flg & (2**27):  # R600/7500
        # slits = [1-10]  # 5000 -- 7840
        # slits = [1-4]  # 7840 -- 9230
        binspec = 2
        outroot = 'keck_lris_red_600_7500.fits'
        slits = [10, 4]
        lcut = [7840.]
        wfile = os.path.join(template_path, 'Keck_LRIS', 'R600_7500',
                             'MasterWaveCalib_I_1_01.json')
        build_template(wfile,
                       slits,
                       lcut,
                       binspec,
                       outroot,
                       lowredux=False,
                       chk=True,
                       normalize=True,
                       subtract_conti=True)

    # ##################################
    # Magellan/MagE
    if flg & (2**13):
        # Load
        mase_path = os.path.join(os.getenv('XIDL_DIR'), 'Magellan', 'MAGE',
                                 'mase', 'Calib')
        sav_file = os.path.join(mase_path, 'MagE_wvguess_jfh.idl')
        mase_dict = readsav(sav_file)
        mase_sol = Table(mase_dict['all_arcfit'])
        # Do it
        all_wave = np.zeros((2048, 15))
        all_flux = np.zeros_like(all_wave)
        for order in np.arange(15):
            all_flux[:, order] = mase_dict['sv_aspec'][order]
            # Build the wavelengths
            wv_air = cheby_val(mase_sol['FFIT'][order], np.arange(2048),
                               mase_sol['NRM'][order], mase_sol['NORD'][order])
            all_wave[:, order] = airtovac(wv_air * units.AA).value
        # Write
        tbl = Table()
        tbl['wave'] = all_wave.T
        tbl['flux'] = all_flux.T
        tbl['order'] = np.arange(20, 5, -1, dtype=int)
        tbl.meta['BINSPEC'] = 1
        # Write
        outroot = 'magellan_mage.fits'
        outfile = os.path.join(template_path, outroot)
        tbl.write(outfile, overwrite=True)
        print("Wrote: {}".format(outfile))

    if flg & (2**14):  # Magellan/MagE Plots
        outpath = os.path.join(resource_filename('pypeit', 'data'),
                               'arc_lines', 'plots')
        new_mage_file = os.path.join(resource_filename('pypeit',
                                                       'data'), 'arc_lines',
                                     'reid_arxiv', 'magellan_mage.fits')
        # Load
        mage_wave = Table.read(new_mage_file)
        llist = waveio.load_line_lists(['ThAr_MagE'])
        #
        for kk in range(mage_wave['wave'].shape[1]):
            wv = mage_wave['wave'][:, kk]
            fx = mage_wave['flux'][:, kk]
            order = 20 - kk
            # Reidentify
            detections, spec_cont_sub, patt_dict = autoid.reidentify(
                fx, fx, wv, llist, 1)
            # Fit
            final_fit = wv_fitting.fit_slit(fx, patt_dict, detections, llist)
            # Output
            outfile = os.path.join(outpath,
                                   'MagE_order{:2d}_IDs.pdf'.format(order))
            autoid.arc_fit_qa(final_fit, outfile=outfile, ids_only=True)
            print("Wrote: {}".format(outfile))
            autoid.arc_fit_qa(final_fit,
                              outfile=os.path.join(
                                  outpath,
                                  'MagE_order{:2d}_full.pdf'.format(order)))

    if flg & (2**15):  # VLT/X-Shooter reid_arxiv
        # VIS
        reid_path = os.path.join(resource_filename('pypeit', 'data'),
                                 'arc_lines', 'reid_arxiv')
        for iroot, iout in zip(
            ['vlt_xshooter_vis1x1.json', 'vlt_xshooter_nir.json'],
            ['vlt_xshooter_vis1x1.fits', 'vlt_xshooter_nir.fits']):
            # Load
            old_file = os.path.join(reid_path, iroot)
            odict, par = waveio.load_reid_arxiv(old_file)

            # Do it
            orders = odict['fit2d']['orders'][::-1].astype(int)  # Flipped
            all_wave = np.zeros((odict['0']['nspec'], orders.size))
            all_flux = np.zeros_like(all_wave)
            for kk, order in enumerate(orders):
                all_flux[:, kk] = odict[str(kk)]['spec']
                if 'nir' in iroot:
                    all_wave[:, kk] = odict[str(kk)]['wave_soln']
                else:
                    all_wave[:, kk] = airtovac(odict[str(kk)]['wave_soln'] *
                                               units.AA).value
            # Write
            tbl = Table()
            tbl['wave'] = all_wave.T
            tbl['flux'] = all_flux.T
            tbl['order'] = orders
            tbl.meta['BINSPEC'] = 1
            # Write
            outfile = os.path.join(reid_path, iout)
            tbl.write(outfile, overwrite=True)
            print("Wrote: {}".format(outfile))

    if flg & (2**16):  # VLT/X-Shooter line list
        line_path = os.path.join(resource_filename('pypeit', 'data'),
                                 'arc_lines', 'lists')
        old_file = os.path.join(line_path, 'ThAr_XSHOOTER_VIS_air_lines.dat')
        # Load
        air_list = waveio.load_line_list(old_file)
        # Vacuum
        vac_wv = airtovac(air_list['wave'] * units.AA).value
        vac_list = air_list.copy()
        vac_list['wave'] = vac_wv
        # Write
        new_file = os.path.join(line_path, 'ThAr_XSHOOTER_VIS_lines.dat')
        vac_list.write(new_file, format='ascii.fixed_width', overwrite=True)
        print("Wrote: {}".format(new_file))

    if flg & (2**17):  # NIRES
        reid_path = os.path.join(resource_filename('pypeit', 'data'),
                                 'arc_lines', 'reid_arxiv')
        iroot = 'keck_nires.json'
        iout = 'keck_nires.fits'
        # Load
        old_file = os.path.join(reid_path, iroot)
        odict, par = waveio.load_reid_arxiv(old_file)

        # Do it
        orders = odict['fit2d']['orders'][::-1].astype(int)  # Flipped
        all_wave = np.zeros((odict['0']['nspec'], orders.size))
        all_flux = np.zeros_like(all_wave)
        for kk, order in enumerate(orders):
            all_flux[:, kk] = odict[str(kk)]['spec']
            if 'nir' in iroot:
                all_wave[:, kk] = odict[str(kk)]['wave_soln']
            else:
                all_wave[:, kk] = airtovac(odict[str(kk)]['wave_soln'] *
                                           units.AA).value
        # Write
        tbl = Table()
        tbl['wave'] = all_wave.T
        tbl['flux'] = all_flux.T
        tbl['order'] = orders
        tbl.meta['BINSPEC'] = 1
        # Write
        outfile = os.path.join(reid_path, iout)
        tbl.write(outfile, overwrite=True)
        print("Wrote: {}".format(outfile))

    if flg & (2**18):  # Gemini/GNIRS
        reid_path = os.path.join(resource_filename('pypeit', 'data'),
                                 'arc_lines', 'reid_arxiv')
        iroot = 'gemini_gnirs.json'
        iout = 'gemini_gnirs.fits'
        # Load
        old_file = os.path.join(reid_path, iroot)
        odict, par = waveio.load_reid_arxiv(old_file)

        # Do it
        orders = odict['fit2d']['orders'][::-1].astype(int)  # Flipped
        all_wave = np.zeros((odict['0']['nspec'], orders.size))
        all_flux = np.zeros_like(all_wave)
        for kk, order in enumerate(orders):
            all_flux[:, kk] = odict[str(kk)]['spec']
            if 'nir' in iroot:
                all_wave[:, kk] = odict[str(kk)]['wave_soln']
            else:
                all_wave[:, kk] = airtovac(odict[str(kk)]['wave_soln'] *
                                           units.AA).value
        # Write
        tbl = Table()
        tbl['wave'] = all_wave.T
        tbl['flux'] = all_flux.T
        tbl['order'] = orders
        tbl.meta['BINSPEC'] = 1
        # Write
        outfile = os.path.join(reid_path, iout)
        tbl.write(outfile, overwrite=True)
        print("Wrote: {}".format(outfile))

    if flg & (2**23):  # WHT/ISIS
        iroot = 'wht_isis_blue_1200_4800.json'
        outroot = 'wht_isis_blue_1200_4800.fits'
        wfile = os.path.join(template_path, 'WHT_ISIS', '1200B', iroot)
        binspec = 2
        slits = [0]
        lcut = [3200.]
        build_template(wfile, slits, lcut, binspec, outroot, lowredux=False)

    if flg & (2**24):  # Magellan/FIRE
        reid_path = os.path.join(resource_filename('pypeit', 'data'),
                                 'arc_lines', 'reid_arxiv')
        iroot = 'magellan_fire_echelle.json'
        iout = 'magellan_fire_echelle.fits'
        # Load
        old_file = os.path.join(reid_path, iroot)
        odict, par = waveio.load_reid_arxiv(old_file)

        # Do it
        orders = odict['fit2d']['orders'][::-1].astype(int)  # Flipped
        all_wave = np.zeros((odict['0']['nspec'], orders.size))
        all_flux = np.zeros_like(all_wave)
        for kk, order in enumerate(orders):
            all_flux[:, kk] = odict[str(kk)]['spec']
            if 'nir' in iroot:
                all_wave[:, kk] = odict[str(kk)]['wave_soln']
            else:
                all_wave[:, kk] = airtovac(odict[str(kk)]['wave_soln'] *
                                           units.AA).value

        # Write
        tbl = Table()
        tbl['wave'] = all_wave.T
        tbl['flux'] = all_flux.T
        tbl['order'] = orders
        tbl.meta['BINSPEC'] = 1
        # Write
        outfile = os.path.join(reid_path, iout)
        tbl.write(outfile, overwrite=True)
        print("Wrote: {}".format(outfile))

    if flg & (2**25):  # FIRE longslit
        binspec = 1
        reid_path = os.path.join(resource_filename('pypeit', 'data'),
                                 'arc_lines', 'reid_arxiv')
        outroot = 'magellan_fire_long.fits'
        xidl_file = os.path.join(os.getenv('FIRE_DIR'), 'LowDispersion',
                                 'NeNeAr_archive_fit.fits')
        spec_file = os.path.join(os.getenv('FIRE_DIR'), 'LowDispersion',
                                 'NeNeAr2.sav')
        fire_sol = Table.read(xidl_file)
        wave = cheby_val(fire_sol['FFIT'].data[0], np.arange(2048),
                         fire_sol['NRM'].data[0], fire_sol['NORD'].data[0])
        wv_vac = airtovac(wave * units.AA)
        xidl_dict = readsav(spec_file)
        flux = xidl_dict['arc1d']
        wvutils.write_template(wv_vac.value,
                               flux,
                               binspec,
                               reid_path,
                               outroot,
                               det_cut=None)

    # Gemini/Flamingos2
    if flg & (2**26):
        reid_path = os.path.join(resource_filename('pypeit', 'data'),
                                 'arc_lines', 'reid_arxiv')
        iroot = ['Flamingos2_JH_JH.json', 'Flamingos2_HK_HK.json']
        outroot = ['Flamingos2_JH_JH.fits', 'Flamingos2_HK_HK.fits']
        binspec = 1
        slits = [0]
        lcut = []
        for ii in range(len(iroot)):
            wfile = os.path.join(reid_path, iroot[ii])
            build_template(wfile,
                           slits,
                           lcut,
                           binspec,
                           outroot[ii],
                           lowredux=False)

    # MDM/OSMOS -- MDM4K
    if flg & (2**28):
        # ArI 4159 -- 6800
        wfile = os.path.join(template_path, 'MDM_OSMOS',
                             'MasterWaveCalib_MDM4K_01.json')
        outroot = 'mdm_osmos_mdm4k.fits'
        binspec = 1
        slits = [0]
        lcut = [3200.]
        build_template(wfile,
                       slits,
                       lcut,
                       binspec,
                       outroot,
                       lowredux=False,
                       chk=True,
                       subtract_conti=True)

    # Keck KCWI
    if flg & (2**29):
        # FeAr BH2
        wfile1 = os.path.join(template_path, 'KCWI', 'BH2',
                              'Keck_KCWI_BH2_4200.json')
        outroot = 'keck_kcwi_BH2_4200.fits'
        binspec = 1
        slits = [1015]
        lcut = [4350.0, 8000.0]
        build_template([wfile1],
                       slits,
                       lcut,
                       binspec,
                       outroot,
                       lowredux=False,
                       normalize=True)
        # FeAr BM
        wfile1 = os.path.join(template_path, 'KCWI', 'BM',
                              'Keck_KCWI_BM_4060.json')
        wfile2 = os.path.join(template_path, 'KCWI', 'BM',
                              'Keck_KCWI_BM_4670.json')
        outroot = 'keck_kcwi_BM.fits'
        binspec = 1
        slits = [1026, 1021]
        lcut = [4350.0, 8000.0]
        build_template([wfile1, wfile2],
                       slits,
                       lcut,
                       binspec,
                       outroot,
                       lowredux=False,
                       normalize=True)

    # P200 DBSP r
    if flg & (2**30):
        # HeNeAr
        wfile = os.path.join(template_path, 'P200_DBSP', 'R316_7500_D55',
                             'P200_DBSP_Red.json')
        outroot = 'p200_dbsp_red_316_7500_d55.fits'
        binspec = 1
        slits = [221]
        lcut = None  # only matters if >1 slit
        build_template([wfile],
                       slits,
                       lcut,
                       binspec,
                       outroot,
                       lowredux=False,
                       normalize=True)

    # P200 DBSP b
    if flg & (2**31):
        # FeAr
        wfile = os.path.join(template_path, 'P200_DBSP', 'B600_4000_D55',
                             'P200_DBSP_Blue.json')
        outroot = 'p200_dbsp_blue_600_4000_d55.fits'
        binspec = 1
        slits = [231]
        lcut = None
        build_template([wfile],
                       slits,
                       lcut,
                       binspec,
                       outroot,
                       lowredux=False,
                       normalize=True)

    # MMT/MMIRS
    if flg & (2**32):
        reid_path = os.path.join(resource_filename('pypeit', 'data'),
                                 'arc_lines', 'reid_arxiv')
        iroot = [
            'mmt_mmirs_HK_zJ.json', 'mmt_mmirs_J_zJ.json',
            'mmt_mmirs_K3000_Kspec.json'
        ]
        outroot = [
            'mmt_mmirs_HK_zJ.fits', 'mmt_mmirs_J_zJ.fits',
            'mmt_mmirs_K3000_Kspec.fits'
        ]
        binspec = 1
        slits = [1020, 1020, 1020]
        lcut = []
        for ii in range(len(iroot)):
            wfile = os.path.join(reid_path, iroot[ii])
            build_template(wfile,
                           slits,
                           lcut,
                           binspec,
                           outroot[ii],
                           lowredux=False)
    # LBT/MODS
    if flg & (2**33):
        reid_path = os.path.join(resource_filename('pypeit', 'data'),
                                 'arc_lines', 'reid_arxiv')
        iroot = ['lbt_mods1r_red.json', 'lbt_mods2r_red.json']
        outroot = ['lbt_mods1r_red.fits', 'lbt_mods2r_red.fits']
        binspec = 1
        slits = [[1557], [1573]]
        lcut = []
        for ii in range(len(iroot)):
            wfile = os.path.join(reid_path, iroot[ii])
            build_template(wfile,
                           slits[ii],
                           lcut,
                           binspec,
                           outroot[ii],
                           lowredux=False)
    # P200 Triplespec
    if flg & (2**34):
        reid_path = os.path.join(resource_filename('pypeit', 'data'),
                                 'arc_lines', 'reid_arxiv')
        iroot = 'p200_triplespec_MasterWaveCalib.fits'
        iout = 'p200_triplespec.fits'
        # Load
        old_file = os.path.join(reid_path, iroot)
        par = io.fits_open(old_file)
        pyp_spec = par[0].header['PYP_SPEC']
        spectrograph = load_spectrograph(pyp_spec)
        orders = spectrograph.orders

        # Do it
        all_wave = np.zeros((par[2].data['spec'].size, orders.size))
        all_flux = np.zeros_like(all_wave)
        for kk, order in enumerate(orders):
            all_flux[:, kk] = par[2 * kk + 2].data['spec']
            all_wave[:, kk] = par[2 * kk + 2].data['wave_soln']
        # Write
        tbl = Table()
        tbl['wave'] = all_wave.T
        tbl['flux'] = all_flux.T
        tbl['order'] = orders
        tbl.meta['BINSPEC'] = 1
        # Write
        outfile = os.path.join(reid_path, iout)
        tbl.write(outfile, overwrite=True)
        print("Wrote: {}".format(outfile))
Example #9
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