def fitsol_fit(self): """Perform a fit to the line identifications """ # Calculate the dispersion # disp = (ids[-1] - ids[0]) / (tcent[idx_str[-1]] - tcent[idx_str[0]]) # final_fit = fitting.iterative_fitting(censpec, tcent, idx_str, ids, # llist, disp, verbose=False, # n_first=2, n_final=self._fitdict["polyorder"]) ord = self._fitdict["polyorder"] gd_det = np.where( (self._lineflg == 1) | (self._lineflg == 2)) # Use the user IDs or acceptable auto IDs only! # Check if there are enough points to perform a fit if gd_det[0].size < ord + 1: msg = "Polynomial order must be >= number of line IDs\n" +\ "Polynomial order = {0:d}, Number of line IDs = {1:d}".format(ord, gd_det[0].size) self.update_infobox(message=msg, yesno=False) else: # Start by performing a basic fit xpix = self._detns[gd_det] / self._fitdict["scale"] ylam = self._lineids[gd_det] self._fitdict["coeff"] = np.polyfit(xpix, ylam, ord) bdisp = self.fitsol_deriv( self.specdata.size / 2) # Angstroms/pixel at the centre of the spectrum # Then try a detailed fit try: final_fit = fitting.iterative_fitting( self.specdata, self._detns, gd_det[0], self._lineids[gd_det[0]], self._line_lists, bdisp, verbose=False, n_first=min(2, self._fitdict["polyorder"]), match_toler=self.par['match_toler'], func=self.par['func'], n_final=self._fitdict["polyorder"], sigrej_first=self.par['sigrej_first'], sigrej_final=self.par['sigrej_final']) # Update the fitdict for key in final_fit: self._fitdict[key] = final_fit[key] except TypeError: # Just stick use the basic fit self._fitdict["fitc"] = None
def get_results(self): """Perform the final wavelength calibration Using the line IDs perform the final fit according to the wavelength calibration parameters set by the user. This routine must be called after the user has manually identified all lines. Returns: wvcalib (dict): Dict of wavelength calibration solutions """ wvcalib = {} # Check that a result exists: if self._fitdict['coeff'] is None: wvcalib[str(self._slit)] = None else: # Perform an initial fit to the user IDs self.fitsol_fit() # Now perform a detailed fit gd_det = np.where((self._lineflg == 1) | (self._lineflg == 2))[0] bdisp = self.fitsol_deriv( self.specdata.size / 2) # Angstroms/pixel at the centre of the spectrum try: n_final = wvutils.parse_param(self.par, 'n_final', self._slit) final_fit = fitting.iterative_fitting( self.specdata, self._detns, gd_det, self._lineids[gd_det], self._line_lists, bdisp, verbose=False, n_first=self.par['n_first'], match_toler=self.par['match_toler'], func=self.par['func'], n_final=n_final, sigrej_first=self.par['sigrej_first'], sigrej_final=self.par['sigrej_final']) except TypeError: wvcalib = None #wvcalib[str(self._slit)] = None else: wvcalib = copy.deepcopy(final_fit) #wvcalib[str(self._slit)] = copy.deepcopy(final_fit) return wvcalib
def reid_in_steps(slit, instr, plot_fil=None, IDtol=1., subpix=None): if instr == '600': wv_dict, template = load_600() fwhm = 4. n_first = 2 nsnippet = 2 elif instr == '300': wv_dict, template = load_300() fwhm = 8. n_first = 3 nsnippet = 2 else: pdb.set_trace() # Template nwwv = template['wave'].data nwspec = template['flux'].data # Full snippet (padded as need be) tspec, mspec, mwv, targ_wv, targ_x, targ_y = target_lines(wv_dict, slit, nwwv, nwspec, fwhm=fwhm, subpix=subpix) # Loop on snippets nsub = tspec.size // nsnippet sv_det, sv_IDs = [], [] for kk in range(nsnippet): # Construct i0 = nsub * kk i1 = min(nsub * (kk + 1), tspec.size) tsnippet = tspec[i0:i1] msnippet = mspec[i0:i1] mwvsnippet = mwv[i0:i1] # Run reidentify detections, spec_cont_sub, patt_dict = autoid.reidentify( tsnippet, msnippet, mwvsnippet, llist, 1, debug_xcorr=False, nonlinear_counts=55000., debug_reid=True, # verbose=True, match_toler=2.5, cc_thresh=0.1, fwhm=fwhm) # Deal with IDs sv_det.append(i0 + detections) sv_IDs.append(patt_dict['IDs']) # Collate and proceed dets = np.concatenate(sv_det) IDs = np.concatenate(sv_IDs) # i1 = np.where(mwv > 0.)[0][0] dwv = mwv[i1 + 1] - mwv[i1] # gd_det = np.where(IDs > 0.)[0] final_fit = fitting.iterative_fitting(tspec, dets, gd_det, IDs[gd_det], llist, dwv, verbose=True, plot_fil=plot_fil, n_first=n_first) return final_fit
def do_it_all(slit, instr, plot_fil=None, IDtol=1., subpix=None): if instr == '600': wv_dict, template = load_600() fwhm = 4. n_order = 3 n_first = 2 elif instr == '300': wv_dict, template = load_300() fwhm = 8. n_order = 3 n_first = 3 else: pdb.set_trace() nwwv = template['wave'].data nwspec = template['flux'].data # Snippet tspec, mspec, mwv, targ_wv, targ_x, targ_y = target_lines(wv_dict, slit, nwwv, nwspec, fwhm=fwhm, subpix=subpix) # Find new lines all_tcent, all_ecent, cut_tcent, icut, arc_cont_sub = wvutils.arc_lines_from_spec( tspec, fwhm=fwhm, debug=True) # Grab initial guess func = 'legendre' sigrej_first = 3. fmin, fmax = 0., 1. xfit = np.arange(mwv.size) yfit = mwv initial_mask = (mwv > targ_wv.min()) & (mwv < targ_wv.max()) i1 = np.where(initial_mask)[0][0] disp = mwv[i1 + 1] - mwv[i1] # mask, fit = utils.robust_polyfit(xfit, yfit, n_order, function=func, sigma=sigrej_first, initialmask=~initial_mask, minx=fmin, maxx=fmax, verbose=True) # , weights=wfit) rms_ang = utils.calc_fit_rms(xfit[mask == 0], yfit[mask == 0], fit, func, minx=fmin, maxx=fmax) # weights=wfit[mask == 0]) rms_pix = rms_ang / disp print("Initial fit: {}; RMS = {}".format(fit, rms_pix)) # Target grid targ_grid = np.outer(targ_wv, np.ones(all_tcent.size)) # Check the loss loss = loss_func(fit[0:2], all_tcent, targ_grid, targ_y, fit, 2) # Bounds bounds = [[fit[0] - 50., fit[0] + 50], [fit[1] * 0.9, fit[1] * 1.1]] #for ifit in fit[2:]: # bounds.append([np.abs(ifit)*-2, np.abs(ifit)*2]) # Differential evolution #diff_result = fitme(bounds, all_tcent, targ_grid, targ_y) diff_result = fitme(bounds, all_tcent, targ_grid, targ_y, fit.copy()) new_fit = fit.copy() new_fit[:len(bounds)] = diff_result.x loss = loss_func(new_fit[0:len(bounds)], all_tcent, targ_grid, targ_y, fit, len(bounds), verbose=True) print("Refined fit: {}".format(diff_result.x)) # Now cut on saturation all_tcent, all_ecent, cut_tcent, icut, arc_cont_sub = wvutils.arc_lines_from_spec( tspec, fwhm=fwhm, nonlinear_counts=55000) #debug=True) final_guess = utils.func_val(new_fit, all_tcent, func, minx=fmin, maxx=fmax) # Match to line list IDs = [] dwv = mwv[i1 + 1] - mwv[i1] lmask = np.zeros(final_guess.size, dtype=bool) for kk, iwv in enumerate(final_guess): imin = np.argmin(np.abs(iwv - llist['wave'])) if np.abs(iwv - llist['wave'][imin]) < dwv * IDtol: lmask[kk] = True IDs.append(llist['wave'][imin]) print("IDs: {}".format(IDs)) # Final fit final_fit = fitting.iterative_fitting(tspec, all_tcent, np.where(lmask)[0], np.array(IDs), llist, dwv, verbose=True, plot_fil=plot_fil, n_first=n_first) # Return return final_fit