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 convolve_psf(a, fwhm, edge="invert", replace_nan=True, debug=False): """ Convolve an array with a gaussian window. Given an array of values `a` and a gaussian full width at half maximum `fwhm` in pixel units, returns the convolution of the array with the normalised gaussian. Parameters ---------- a : array, shape(N,) Array to convolve fwhm : float Gaussian full width at half maximum in pixels. This should be > 2 to sample the gaussian PSF properly. Returns ------- convolved_a : array, shape (N,) Notes ----- The Gaussian kernel is calculated for as many pixels required until it drops to 1% of its peak value. The data will be spoiled at distances `n`/2 (rounding down) from the edges, where `n` is the width of the Gaussian in pixels. """ const2 = 2.354820046 # 2*sqrt(2*ln(2)) const100 = 3.034854259 # sqrt(2*ln(100)) sigma = fwhm / const2 # gaussian drops to 1/100 of maximum value at x = # sqrt(2*ln(100))*sigma, so number of pixels to include from # centre of gaussian is: n = np.ceil(const100 * sigma) if replace_nan: a = nan2num(a, replace="interp") if debug: print "First and last %s pixels of output array will be invalid" % n x = np.linspace(-n, n, 2 * n + 1) # total no. of pixels = 2n+1 gauss = np.exp(-0.5 * (x / sigma) ** 2) return convolve_window(a, gauss, edge=edge)