def get_line_resolution(line, file): import pyfits from mostools import spectools as st spec = pyfits.open(file)[3].data.copy() wave = st.wavelength(file, 1) data = spec.astype(scipy.float64) data[scipy.isnan(data)] = 0. size = data.size bg = ndimage.percentile_filter(data, 20, 55) bg = ndimage.gaussian_filter(bg, 7) data -= bg pos = abs(wave - line).argmin() fitdata = scipy.zeros((15, 2)) fitdata[:, 0] = wave[pos - 7:pos + 8] fitdata[:, 1] = data[pos - 7:pos + 8] par = scipy.zeros(4) par[1] = data[pos] par[2] = line par[3] = 1. fit, chi2 = special_functions.ngaussfit(fitdata, par) pixsize = wave[pos] - wave[pos - 1] if fit[3] > 5. * pixsize or fit[3] < 0.8 * pixsize or abs( fit[2] - wave[pos]) > 1.5 * fit[3]: print 'Could not fit for resolution of spectral line' print fit return 0 v = fit[2] / fit[3] return 299792. / v
def extract(outname,root,slit,pos,width=1.): """ extract(outname,root,slit,pos,width=1.) Extracts a spectrum from 2d mask and variance images. Inputs: outname - name of output FITS file root - root name of input data (ie ROOTNAME_bgsub.fits) slit - number of slit to extract from (1 = bottom slit) pos - position along slit to extract width - gaussian-sigma width to extract Outputs: FITS file containing extracted spectrum. """ infile = root+"_bgsub.fits" spectools.cutout(infile,outname,slit) wave = spectools.wavelength(outname) data = pyfits.open(outname)[0].data.astype(scipy.float32) os.remove(outname) infile = root+"_var.fits" spectools.cutout(infile,outname,slit) varimg = pyfits.open(outname)[0].data.astype(scipy.float32) os.remove(outname) yvals = scipy.arange(data.shape[0]).astype(scipy.float32) fit = scipy.array([0.,1.,pos,width]) weight = sf.ngauss(yvals,fit) weight[abs(yvals-pos)/width>1.5] = 0. weight /= weight.sum() spec = weight*data.T spec = spec.sum(axis=1) varspec = weight*varimg.T varspec = varspec.sum(axis=1) spec[varspec==0] = 0. smooth = signal.wiener(spec,7,varspec) smooth[scipy.isnan(smooth)] = 0. hdu = pyfits.PrimaryHDU() hdu.header.update('CENTER',pos) hdu.header.update('WIDTH',width) hdulist = pyfits.HDUList([hdu]) crval = wave[0] scale = wave[1]-wave[0] for i in [spec,smooth,varspec]: thdu = pyfits.ImageHDU(i) thdu.header.update('CRVAL1',crval) thdu.header.update('CD1_1',scale) thdu.header.update('CRPIX1',1) thdu.header.update('CRVAL2',1) thdu.header.update('CD2_2',1) thdu.header.update('CRPIX2',1) thdu.header.update('CTYPE1','LINEAR') hdulist.append(thdu) hdulist.writeto(outname)
def get_resolution(file): import pyfits from mostools import spectools as st spec = pyfits.open(file)[3].data.copy() wave = st.wavelength(file, 1) v = measure(spec, wave) if v == 1: print 'No lines fit!' return 0 return 299792. / v[0]
def vegacorr(input, output, size=250): d = pyfits.open(input)[1].data.copy() wave = st.wavelength(input, 1) k = numpy.linspace(wave[0], wave[-1], wave.size / size) twave, trans = cPickle.load(open(dir + 'data/trans.dat')) kernel = (wave[1] - wave[0]) / (1e4 * (twave[1] - twave[0])) trans = ndimage.gaussian_filter(trans, kernel) sky = interpolate.splrep(twave * 1e4, trans, k=3, s=0) swave, star = cPickle.load(open(dir + 'data/vega.dat')) snorm = star.mean() starmodel = interpolate.splrep(swave * 10., star / snorm, k=3, s=0) def dofit(p, wave, star, vega, sky, trans=False): vvel, broad, svel, scale = p vwave = 10**(numpy.log10(wave) * vvel) v = interpolate.splev(vwave, vega) v = ndimage.gaussian_filter(v, broad) swave = 10**(numpy.log10(wave) * svel) s = interpolate.splev(swave, sky)**scale s[swave < 8510.] = 1. mod = interpolate.splrep(wave, star / (v * s), t=k[1:-1], k=3, task=-1) model = s * v * interpolate.splev(wave, mod) if trans: return v / model return model - star pars = [1., 1., 1., 1.] coeff, ier = optimize.leastsq(dofit, pars, (wave, d, starmodel, sky)) model = dofit(coeff, wave, d, starmodel, sky, True) / snorm model = interpolate.splrep(wave, model) f = open(output, 'wb') cPickle.dump(model, f, 2) f.close() return model
def extract(image, varimage, outname, width=2., offset=0., pos=None, minwave=None, maxwave=None, response_image=None, response_model=None, regions=[], centroid=None): if outname.lower().find('fits') < 1: outname = "%s.fits" % outname resp = None respwave = None if response_image is not None: if response_model is None: # print "No response model included; not performing response correction." import cPickle resp = cPickle.load(open(response_image)) else: resp = get_response(response_image, response_model, regions) elif response_model is not None: print "No response image included; not performing response correction." if minwave is None: minwave = -10. if maxwave is None: maxwave = 1e99 data = pyfits.open(image)[0].data.copy() if data.ndim == 3: if data.shape[0] > 1: print "Only working on first image plane of 3D image." data = data[0].copy() wave = st.wavelength(image) indx = scipy.where((wave > minwave) & (wave < maxwave))[0] minx, maxx = indx.min(), indx.max() wave = wave[minx:maxx] data = data[:, minx:maxx] tmp = data.copy() tmp[numpy.isnan(data)] = 0. ospec = wave * 0. ovar = wave * 0. x = numpy.arange(data.shape[0]) if centroid is None: n = tmp.shape[1] / 100 peaks = [] bounds = numpy.linspace(0, tmp.shape[1], n + 1) for i in range(n): a, b = bounds[i], bounds[i + 1] p = tmp[:, a:b].sum(1).argmax() peaks.append([(a + b) / 2., p]) peak = sf.lsqfit(numpy.asarray(peaks), 'polynomial', 3) if pos is not None: peak['coeff'][0] = pos peaks = sf.genfunc(numpy.arange(tmp.shape[1]), 0., peak) center = wave * 0. for i in range(center.size): d = data[:, i].copy() peak = peaks[i] if peak < 0: peak = 0 if peak >= d.shape: peak = d.shape - 1. fit = numpy.array([0., d[peak], peak, 1.]) cond = ~numpy.isnan(d) input = numpy.empty((d[cond].size, 2)) input[:, 0] = x[cond].copy() input[:, 1] = d[cond].copy() fit = sf.ngaussfit(input, fit)[0] center[i] = fit[2] fit = sf.lsqfit(ndimage.median_filter(center, 17), 'polynomial', 5) centroid = sf.genfunc(scipy.arange(wave.size), 0., fit) #import pylab #pylab.plot(center-centroid) #pylab.show() xvals = scipy.arange(data.shape[0]) var = pyfits.open(varimage)[0].data.copy() if var.ndim == 3: var = var[0].copy() var = var[:, minx:maxx] cond = (numpy.isnan(var)) | (numpy.isnan(data)) for i in range(ovar.size): c = centroid[i] + offset wid = width mask = xvals * 0. mask[(xvals - c < wid) & (xvals - c > 0.)] = wid - (xvals[ (xvals - c < wid) & (xvals - c > 0.)] - c) mask[(xvals - c < wid - 1) & (xvals - c > 0.)] = 1. mask[(c - xvals < wid + 1) & (c - xvals > 0.)] = (wid + 1) - ( c - xvals[(c - xvals < wid + 1) & (c - xvals > 0.)]) mask[(c - xvals < wid) & (c - xvals > 0.)] = 1. mask[cond[:, i]] = 0. mask /= mask.sum() ospec[i] = (mask[~cond[:, i]] * data[:, i][~cond[:, i]]).sum() ovar[i] = ((mask[~cond[:, i]]**2) * var[:, i][~cond[:, i]]).sum() badpix = numpy.where(numpy.isnan(ospec))[0] ospec[badpix] = 0. ovar[badpix] = ovar[~numpy.isnan(ovar)].max() * 1e6 med = numpy.median(ospec) ospec /= med ovar /= med**2 if resp is not None: # if respwave is None: # resp = sf.genfunc(wave,0,resp) # else: # resp = interpolate.splrep(respwave,resp) resp = interpolate.splev(wave, resp) ospec *= resp ovar *= resp**2 st.make_spec(ospec, ovar, wave, outname, clobber=True) return centroid
def get_response(image, model, regions): model = numpy.loadtxt(model) mwave = model[:, 0] mspec = model[:, 1] model = interpolate.splrep(mwave, mspec, k=3, s=0) hdu = pyfits.open(image) if len(hdu) == 4: spec = hdu[1].data.copy() wave = st.wavelength(image, 1) else: spec = hdu[0].data.copy() wave = st.wavelength(image) outmodel = interpolate.splev(wave, model) ratio = outmodel / spec badregions = [] cond = ~numpy.isnan(ratio) cond = cond & (~numpy.isinf(ratio)) for lo, hi in regions: badregions.append([lo, hi]) cond = cond & (~((wave > lo) & (wave < hi))) scurrent = 2. * wave[cond].size**0.5 smod = ratio[cond].mean()**2 spmodel = interpolate.splrep(wave[cond], ratio[cond], k=3, s=scurrent * smod) resp = None while resp != 'q' and resp != 'Q': import pylab current = interpolate.splev(wave, spmodel) pylab.plot(wave, current) pylab.plot(wave, ratio) pylab.gca().fmt_xdata = pylab.FormatStrFormatter('%7.2f') pylab.show() resp = raw_input("Enter command (q, m, s, w, h): ") if resp == 'm': region = raw_input("Enter region to mask (eg, 6530,6580): ").split( ',') while len(region) != 2: region = raw_input( "Please input wavelengths joined by a comma: ").split(',') lo, hi = float(region[0]), float(region[1]) badregions.append([lo, hi]) cond = cond & (~((wave > lo) & (wave < hi))) spmodel = interpolate.splrep(wave[cond], ratio[cond], k=3, s=scurrent * smod) elif resp == 's': scurrent = float( raw_input( "Current smoothing factor is %4.2f, enter new smoothing factor: " % scurrent)) spmodel = interpolate.splrep(wave[cond], ratio[cond], k=3, s=scurrent * smod) elif resp == 'h': print "Use q to quit, m to mask, s to set smoothing scale, w to write model to disk" elif resp == 'w': import cPickle outname = raw_input("Name of file to write to: ") f = open(outname, 'wb') cPickle.dump(spmodel, f) f.close() print "Regions masked:", badregions return spmodel