def find_cont(fl, fwhm1=300, fwhm2=200, nchunks=4): """ Given the flux, estimate the continuum. fwhm values are smoothing lengths. """ # smooth flux, with smoothing length much longer than expected # emission line widths. fl = nan2num(fl.astype(float), replace="mean") co = convolve_psf(fl, fwhm1, edge=10) npts = len(fl) indices = np.arange(npts) # throw away top and bottom 2% of data that deviates from # continuum and re-fit new continuum. Go chunk by chunk so that # points are thrown away evenly across the spectrum. nfl = fl / co step = npts // nchunks + 1 ind = range(0, npts, step) + [npts] igood = [] for i0, i1 in zip(ind[:-1], ind[1:]): isort = nfl[i0:i1].argsort() len_isort = len(isort) j0, j1 = int(0.05 * len_isort), int(0.95 * len_isort) igood.extend(isort[j0:j1] + i0) good = np.in1d(indices, igood) sfl = fl.copy() sfl[~good] = np.interp(indices[~good], indices[good], sfl[good]) co = convolve_psf(sfl, fwhm2, edge=10) return co
def cr_reject2(fl, er, nsig=10.0, fwhm=2, grow=1, debug=True): """ interpolate across features that have widths smaller than the expected fwhm resolution. Parameters ---------- fwhm: int Resolution fwhm in pixels fl : array of floats, shape (N,) Flux er : array of floats, shape (N,) Error Returns the interpolated flux and error arrays. """ fl, er = (np.array(a, dtype=float) for a in (fl, er)) # interpolate over bad pixels fl1 = convolve_psf(fl, fwhm) ibad = np.where(np.abs(fl1 - fl) > nsig * er)[0] if debug: print len(ibad) extras1 = np.concatenate([ibad + 1 + i for i in range(grow)]) extras2 = np.concatenate([ibad - 1 - i for i in range(grow)]) ibad = np.union1d(ibad, np.union1d(extras1, extras2)) ibad = ibad[(ibad > -1) & (ibad < len(fl))] igood = np.setdiff1d(np.arange(len(fl1)), ibad) fl[ibad] = np.interp(ibad, igood, fl[igood]) er[ibad] = np.nan return fl, er
def qso_template_uv(wa, z, smooth_fwhmpix=6): """ Return a composite UV QSO spectrum at redshift z. wavelengths must be in Angstroms. """ w, f, e = np.loadtxt(DATAPATH + "templates/qso/telfer_composite_qso.txt", unpack=1) fl = np.interp(wa, w * (1 + z), f) fl = convolve_psf(fl, smooth_fwhmpix) return fl
def update(self): """ Calculates the new continuum, residuals and updates the plots. Updates the following attributes: self.markers self.continuum """ wa,fl,er = (self.spec[key] for key in 'wa fl er'.split()) co = np.empty(len(wa)) co.fill(np.nan) for b0,b1 in zip(self.breaks[:-1], self.breaks[1:]): cpts = [(x,y) for x,y in self.contpoints if b0 <= x <= b1] if len(cpts) == 0: continue spline = AkimaSpline(*zip(*cpts)) i,j = wa.searchsorted([b0,b1]) co[i:j] = spline(wa[i:j]) resid = (fl - co) / er # histogram bins = np.arange(0, 5+0.1, 0.2) w0,w1 = self.fig.axes[1].get_xlim() x,_ = np.histogram(resid[between(wa, w0, w1)], bins=bins) b = np.repeat(bins, 2) X = np.concatenate([[0], np.repeat(x,2), [0]]) Xmax = X.max() X = 0.05 * X / Xmax self.markers['hist_left'].set_data(X, b) self.markers['contpoints'].set_data(zip(*self.contpoints)) nbin = self.nbin self.markers['cont'].set_data(wa[::nbin], co[::nbin]) self.markers['resid'].set_data(wa[::nbin], resid[::nbin]) if self.smoothby is not None: sfl = convolve_psf(fl, self.smoothby) self.art_fl.set_data(wa, sfl) else: self.art_fl.set_data(wa, fl) self.continuum = co saveobj('_knots.sav', self.contpoints, overwrite=True) self.fig.canvas.draw()
def convolve_constant_dv(wa, fl, wa_dv=None, npix=4.0, vfwhm=None): """ Convolve a wavelength array with a gaussian of constant velocity width. If `vfwhm` is specified an intermediate wavelength array with constant velocity pixel width is calculated. Otherwise, both `wa_dv` and `npix` must be given -- this is faster because no intermediate array needs to be calculated. Parameters ---------- fl, wa : arrays of floats, length N The array to be convolved and its wavelengths. vfwhm : float, optional Full width at half maximum in velocity space (km/s) of the gaussian kernel with which to convolve `fl`. npix : float, default 4 Number of pixels corresponding to `vfwhm` in `wa_dv` if given, otherwise `wa` is interpolated to an array with velocity pixel width = vfwhm / npix. wa_dv : array of floats, default `None` Wavelength array with a constant velocity width (this can be generated with make_constant_dv_wa_scale()). Returns ------- fl_out : array of length N fl convolved with the gaussian kernel with the specified FWHM. """ # interpolate to the log-linear scale, convolve, then # interpolate back again. # convolve with the gaussian if vfwhm is not None: wa_dv = make_constant_dv_wa_scale(wa[0], wa[-1], float(vfwhm) / npix) fl_dv = np.interp(wa_dv, wa, fl) fl_dv_smoothed = convolve_psf(fl_dv, npix) fl_out = np.interp(wa, wa_dv, fl_dv_smoothed) return fl_out