示例#1
0
    def id(self, wave, feature):
        # Get closest feature to input value
        lines = scipy.asarray(self.linelist)
        diff = abs(lines - feature)
        if diff.min() < 3.:
            feature = lines[diff.argmin()]

        disp = self.wave[1] - self.wave[0]
        indx = scipy.where(abs(wave - self.wave) < disp)[0][0]
        if indx < 5 or indx > self.wave.size - 4:
            self.lineid(wave, feature)
            return
        fitdata = scipy.empty((11, 2))
        fitdata[:, 0] = self.wave[indx - 5:indx + 6]
        fitdata[:, 1] = self.current[indx - 5:indx + 6]

        fit = scipy.zeros(4)
        fit[1] = self.current[indx]
        fit[2] = wave
        fit[3] = 2.

        fit, chi2 = special_functions.ngaussfit(fitdata, fit)
        if abs(fit[2] - wave) > 5.:
            self.lineid(wave, feature)
        else:
            self.lineid(fit[2], feature)
        self.collect.append(self.z)
示例#2
0
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 get_ap(slit, B, R, apcent, apnum, wid, order):
    xproj = np.median(slit[:, B:R], 1)
    m, s = clip(xproj)

    smooth = ndimage.gaussian_filter(xproj, 1)
    if order == 3.:
        smooth = ndimage.gaussian_filter(xproj[:-30], 1)
    x = np.arange(xproj.size) * 1.
    """ 
    The four parameters immediately below are the initial guesses
    bkgd, amplitude, mean location, and sigma for a Gaussian fit
    """
    fit = np.array([0., smooth.max(), smooth.argmax(), 1.])
    fit = sf.ngaussfit(xproj, fit)[0]

    cent = fit[2] + apcent[apnum] / arcsecperpix[order - 1]
    print cent
    apmax = 0.1 * xproj.max()
    ap = np.where(abs(x - cent) < wid / arcsecperpix[order - 1], 1., 0.)

    if order < 60.:
        plt.subplot(2, 5, order)
        plt.plot(x, apmax * ap)  # Scale the aperture to easily see it
        plt.plot(x, xproj)
        plt.ylim(-apmax, 1.1 * xproj.max())

    ap = ap.repeat(slit.shape[1]).reshape(slit.shape)
    return ap, fit
示例#4
0
def measure(spectrum, num=25):
    """
	measure(spectrum,num=25)

	Deterines the spectral resolution for a spectrum by measuring the width
	  of arc or skylines.

	Inputs:
	  spectrum - 1d spectrum
	  num      - maximum number of lines to measure (not implemented)

	Outputs:
	  median resolution of all lines extracted
	"""

    data = spectrum.astype(scipy.float64)
    size = data.size

    pixels = scipy.arange(size) * 1.

    avg, std = clipped(data, 3.)
    thresh = avg + 30. * std  # Only measure 30 sigma lines
    """ Identify peaks. """
    mask = ndimage.maximum_filter(data, 13)
    mask = scipy.where(mask == data, data, 0)
    lines = scipy.where((mask > thresh) & (mask < 50000.))[0]
    count = 0

    vals = []
    for pos in lines:
        """ Don't use lines near the edges. """
        if pos < 5 or pos + 6 > size:
            continue
        fitdata = scipy.zeros((11, 2))
        fitdata[:, 0] = pixels[pos - 5:pos + 6]
        fitdata[:, 1] = data[pos - 5:pos + 6]

        par = scipy.zeros(4)
        par[1] = data[pos]
        par[2] = pixels[pos]
        par[3] = 1.

        fit, chi2 = special_functions.ngaussfit(fitdata, par)
        fit[2] -= fitdata[0, 0]
        """
		Reject fits that were 'too' wide or narrow, or not near the
		  expected center.
		"""
        if fit[3] > 4. or fit[3] < 0.8 or fit[2] < 2 or fit[2] > 9:
            continue

        vals.append(fit[3])

        count += 1
    vals = scipy.asarray(vals)
    if vals.size == 0:
        return 1.
    return scipy.median(vals)
示例#5
0
def measure(file,num=25):
	f = pyfits.open(file)

	data = f[0].data.astype(scipy.float64)/1000.
	size = data.size
	wave = spectools.wavelength(file)
	sorted = scipy.sort(data)
	zero = sorted[size/20:size/10].mean()
	sigma = sorted[size/20:size/10].std()

	thresh = zero+100*sigma

	count = 0
	search = data.copy()

	vals = scipy.zeros(num)
	place = scipy.zeros(num)
	while count<num:
		max = search.max()
		if max<thresh:
			break

		pos = search.argmax()


		search[pos-5:pos+6] = 0.

		if pos<5 or pos+6>size:
			continue
		fitdata = scipy.zeros((11,2))
		fitdata[:,0] = wave[pos-5:pos+6]
		fitdata[:,1] = data[pos-5:pos+6]

		par = scipy.zeros(4)
		par[1] = max
		par[2] = wave[pos]
		par[3] = wave[pos]-wave[pos-1]

		fit,chi2 = special_functions.ngaussfit(fitdata,par)
		if chi2>4:
			continue
		model = special_functions.ngauss(fitdata[:,0],fit)
		pylab.plot(wave[pos-5:pos+6],model)

		feature = wave[pos]
		width = fit[3]*299800/feature

		vals[count] = width
		place[count] = feature

		count += 1
	args = place.argsort()
	vals = vals[args]
	place = place[args]

	return scipy.median(vals)
示例#6
0
def find_peak(data):
    size = data.shape[0]
    fit_data = scipy.reshape(scipy.arange(0, size, 0.5), (size, 2))
    fit_data[:, 1] = data.copy()

    fit = scipy.zeros(4)
    fit[0] = 0.
    fit[1] = data.max()
    fit[2] = data.argmax()
    fit[3] = 2.
    fit, val = special_functions.ngaussfit(fit_data, fit)

    return fit
示例#7
0
def findlines(x,z,sigma=5.):
	""" Peak finding """
	tmp = ndimage.maximum_filter(z,9)
	peaks = scipy.where(tmp==z,z,0)

	""" Only choose >sigma lines """
	avg = ndimage.percentile_filter(z,30.,55)
	tmp = scipy.where(peaks>0.)[0]
	peaks = []
	for i in tmp:
		start = i-150
		end = i+150
		if start<0:
			start = 0
		if end>z.size:
			end = z.size
		mean,std = clipped_std(z[start:end],3.5)
		if z[i]>avg[i]+sigma*std:
			peaks.append(i)

	""" Centroid the lines, fixing the zeropoint of the gaussians to avg """
	fit = scipy.ones(8)
	fit[4] = 0.
	datalines = []
	for i in peaks:
		if i-14<0 or i+15>x.size:
			continue
		fit[0] = avg[i]
		fit[1] = z[i]
		fit[2] = x[i]
		fit[3] = 1.

		"""
		Deal with saturated lines appropriately (ie skipping the
		  non-linear pixels)
		"""
		if z[i]<SATURATED:
			fitdata = scipy.empty((9,2))
			fitdata[:,0] = x[i-4:i+5].copy()
			fitdata[:,1] = z[i-4:i+5].copy()
		else:
			fitdata = scipy.empty((25,2))
			fitdata[:,0] = x[i-12:i+13].copy()
			fitdata[:,1] = z[i-12:i+13].copy()
			fitdata = fitdata[fitdata[:,1]<SATURATED*0.8]

		""" A simple weighted sum would probably be robust.... """
		gfit,chi2 = special_functions.ngaussfit(fitdata,fit)
		datalines.append(gfit[2])

	return scipy.asarray(datalines)
示例#8
0
def medsubtract(image,outname):
    data = pyfits.open(image)[0].data.copy()
    if data.ndim==3:
        data = data[0].copy()

    tmp = data.copy()
    tmp[numpy.isnan(tmp)] = 0.
    tmp -= numpy.sort(tmp,0)[tmp.shape[0]/5]
    trace = tmp.sum(1)
    peak = trace.argmax()

    center = numpy.empty(data.shape[1])
    w = center.copy()
    for i in range(1+center.size/100):
       b = i*100
       e = b+100
       if e>center.size:
           e = center.size
       if b==e:
           continue
       center[b:e] = tmp[:,b:e].sum(1).argmax()
    bg = center.copy()
    x = numpy.arange(data.shape[0])
    for i in range(center.size):
        d = tmp[:,i].copy()
        peak = center[i]
        if numpy.isnan(d[peak]):
            center[i] = peak
            continue
        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,chi = sf.ngaussfit(input,fit)
        center[i] = fit[2]
        w[i] = fit[3]

    fit = sf.lsqfit(ndimage.median_filter(center,17),'polynomial',5)
    centroid = sf.genfunc(numpy.arange(bg.size),0.,fit)
    w = numpy.median(w)
    for i in range(bg.size):
        d = data[:,i].copy()
        d[centroid[i]-w*4:centroid[i]+w*4] = numpy.nan
        data[:,i] -= stats.nanmedian(d)

    hdu = pyfits.open(image)[0]
    hdu.data = data.copy()
    hdu.writeto(outname,clobber=True)
示例#9
0
def findoffset(scidata,coord,offset,slice=None):

	straight = spectools.resampley(scidata,coord,offset,slice=slice)
	slice = straight.mean(axis=1)

	p = scipy.zeros(4)
	p[0] = slice.min()
	p[1] = slice.max()
	p[2] = slice.argmax()
	p[3] = 1.
	fit,val = special_functions.ngaussfit(slice,p)
	chi2 = val/(slice.size-4.)
	if fit[2]>0 and fit[2]<slice.size:
		return fit[2]
	else:
		return scipy.nan
示例#10
0
    def fitline(self, xpos):
        # Find local maximum to start fitting
        if self.solution == None:
            point = round(xpos)
        else:
            point = sf.genfunc(xpos, 0., self.inverse)
            point = point[0].round()
        print(point)
        center = self.data[point - 5:point + 6].argmax() + point - 5
        print(self.data[point - 5:point + 6])
        print(self.data[point - 5:point + 6].argmax())

        max = self.data[center]
        fit = scipy.empty(4)
        fit[0] = 0.
        fit[1] = max
        fit[2] = 7.
        fit[3] = 2.

        fit, chi = sf.ngaussfit(self.data[center - 7:center + 8], fit)
        centroid = fit[2] + center - 7
        print("Press enter to input wavelength")
        wave = float(input("Wavelength: "))
        max = self.data[centroid - 2:centroid + 3].max()
        try:
            indx = self.lines.index(centroid)
            self.ids[indx] = wave
        except:
            self.lines.append(centroid)
            self.ids.append(wave)
            axis = self.ax.axis()
            fudge = 0.05 * (axis[3] - axis[2])
            if self.solution == None:
                wave = centroid
            else:
                wave = sf.genfunc(centroid, 0., self.solution)
            mark = mpl.patches.Polygon([(wave, max + fudge),
                                        (wave, max + 2 * fudge)])
            self.ax.add_patch(mark)
            self.markers[centroid] = mark
            pylab.draw()
示例#11
0
    def get_ap_oldham(self, slit, apcent, nsig, ordinfo, doplot=True):
        """
        Defines a uniform aperture as in the example ESI extraction scripts
        from Lindsay
        """

        B = ordinfo['pixmin']
        R = ordinfo['pixmax']
        xproj = np.median(slit[:, B:R], 1)
        m, s = df.sigclip(xproj)

        smooth = ndimage.gaussian_filter(xproj, 1)
        if ordinfo['name'] == 'Order 3':
            smooth = ndimage.gaussian_filter(xproj[:-30], 1)
        x = np.arange(xproj.size) * 1.
        """
        The four parameters immediately below are the initial guesses
        bkgd, amplitude, mean location, and sigma for a Gaussian fit
        """
        fit = np.array([0., smooth.max(), smooth.argmax(), 1.])
        fit = sf.ngaussfit(xproj, fit)[0]

        cent = fit[2] + apcent / ordinfo['pixscale']
        apymax = 0.1 * xproj.max()
        ap = np.where(abs(x - cent) < nsig / ordinfo['pixscale'], 1., 0.)
        # slit.apmin = cent - nsig
        # slit.apmax = cent + nsig

        if doplot:
            plt.subplot(2, 5, (ordinfo['order']))
            plt.plot(x, apymax * ap)  # Scale the aperture to easily see it
            plt.plot(x, xproj)
            plt.ylim(-apymax, 1.1 * xproj.max())
            plt.axvline(cent, color='k', ls='dotted')

        ap = ap.repeat(slit.shape[1]).reshape(slit.shape)
        return ap, fit
示例#12
0
def measure(spectrum, wave, nsig=30., num=25, show=False):
    """
    measure(spectrum,num=25)

    Deterines the spectral resolution for a spectrum by measuring the width
      of arc or skylines.

    Inputs:
      spectrum - 1d spectrum
      wave     - array containing wavelengths of points in file
      num      - maximum number of lines to measure (not implemented)

    Outputs:
      median resolution of all lines extracted
    """

    data = spectrum.astype(scipy.float64)
    data[scipy.isnan(data)] = 0.
    size = data.size

    bg = ndimage.percentile_filter(data, 20, 35)
    bg = ndimage.gaussian_filter(bg, 7)
    data -= bg

    avg, std = clipped(data, 2.0)
    thresh = avg + nsig * std  # Only measure 30 sigma lines
    """ Identify isolated peaks. """
    mask = ndimage.maximum_filter(data, 15)
    lines = scipy.where((mask == data) & (mask > thresh) & (mask < 50000.))[0]
    count = 0

    vals = []
    locs = []
    for pos in lines:
        """ Don't use lines near the edges. """
        if pos < 7 or pos + 8 > size:
            continue
        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] = wave[pos]
        par[3] = 1.

        fit, chi2 = special_functions.ngaussfit(fitdata, par)
        """
        Reject fits that were 'too' wide or narrow, or not near the
          expected center.
        """
        pixsize = wave[1] - wave[0]
        if fit[3] > 5. * pixsize or fit[3] < 0.8 * pixsize or abs(
                fit[2] - wave[pos]) > 1.5 * fit[3]:
            continue

        locs.append(fit[2])
        vals.append(fit[2] / fit[3])

        count += 1
    vals = scipy.asarray(vals)

    if vals.size == 0:
        return 1.

    if show:
        import pylab
        pylab.plot(locs, vals)
        pylab.show()

    return scipy.median(vals), vals.size
示例#13
0
def solve(d,orders):
    path = os.path.split(__file__)[0]

    lines = {}
    lines['cuar'] = numpy.loadtxt(path+"/data/cuar.lines")
    lines['hgne'] = numpy.loadtxt(path+"/data/hgne.lines")
    lines['xe'] = numpy.loadtxt(path+"/data/xe.lines")

    #startsoln = numpy.load(path+"/data/test_wavesol.dat",
    #                       allow_pickle=True)
    startsoln = numpy.load(path+"/data/esi_wavesolution.dat",
                           allow_pickle=True)

    #arclist = d.keys() # Under python 3 this does not produce a list
    #                        and so arclist[0] below fails
    arclist = list(d)
    arclist.sort()
    soln = []
    if d[arclist[0]].shape[1]>3000:
        xvals = numpy.arange(4096.)
        cuslice = slice(3860,3940)
        fw1 = 75.
        fw2 = 9
    else:
        xvals = numpy.arange(1.,4096.,2.)
        cuslice = slice(1930,1970)
        fw1 = 37.
        fw2 = 5

    """
    Do a temporary kludge.  In some cases, the finding of the orders
    fails, and only 9 orders are found.  In this case, we need to skip
    the first of the orders
    """
    if len(orders) == 9:
        ordstart = 1
        dord = 1
    else:
        ordstart = 0
        dord = 0
    for i in range(ordstart, 10):
      solution = startsoln[i]
      start,end = orders[(i-dord)]

      peaks = {}
      trace = {}
      fitD = {}
      WIDTH = 4
      import pylab
      for arc in arclist:
          data = numpy.nanmedian(d[arc][start:end],axis=0)
          data[scipy.isnan(data)] = 0.
          if i==0 and arc=='cuar':
              data[cuslice] = numpy.median(data)
          trace[arc] = data.copy()
          bak = ndimage.percentile_filter(data,50.,int(fw1))
          bak = getContinuum(bak,40.)
          data -= bak
          fitD[arc] = data/d[arc][start:end].std(0)
          p = ndimage.maximum_filter(data,fw2)
          std = clip(scipy.trim_zeros(data),3.)[1]
          nsig = ndimage.uniform_filter((data>7.*std)*1.,3)
          peak = scipy.where((nsig==1)&(p>10.*std)&(p==data))[0]
          peaks[arc] = []
          for p in peak:
              if p-WIDTH<0 or p+WIDTH+1>xvals.size:
                  continue
              x = xvals[p-WIDTH:p+WIDTH+1].copy()#-xvals[p]
              f = data[p-WIDTH:p+WIDTH+1].copy()
              fitdata = scipy.array([x,f]).T
              fit = scipy.array([0.,f.max(),xvals[p],1.])
              fit,chi = sf.ngaussfit(fitdata,fit,weight=1)
              peaks[arc].append(fit[2])#+xvals[p])
      for converge in range(15):
        wave = 10**sf.genfunc(xvals,0.,solution)

        refit = []
        corrA = {}
        err = wave[int(wave.size/2)]-wave[int(wave.size/2-1)]
        for arc in arclist:
            corr = []
            p = 10.**sf.genfunc(peaks[arc],0.,solution)
            for k in range(p.size):
                cent = p[k]
                diff = cent-lines[arc]
                corr.append(diff[abs(diff).argmin()])
            corr = numpy.array(corr)
            if corr.size<4:
                continue
            m,s = clip(corr)
            corr = numpy.median(corr[abs(corr-m)<5.*s])
            print(corr)
            corrA[arc] = corr
#        corr = m

        #for arc in arclist:
            p = 10.**sf.genfunc(peaks[arc],0.,solution)
            for k in range(p.size):
                pos = peaks[arc][k]
                cent = p[k]
                diff = abs(cent-lines[arc]-corr)
                if diff.min()<2.*err:
                    refit.append([pos,lines[arc][diff.argmin()]])
        refit = scipy.asarray(refit)
        solution = sf.lsqfit(refit,'polynomial',3)
        refit = []
        err = solution['coeff'][1]
        for arc in arclist:
            data = trace[arc]
            for pos in peaks[arc]:
                cent = sf.genfunc(pos,0.,solution)
                delta = 1e9
                match = None
                for j in lines[arc]:
                    diff = abs(cent-j)
                    if diff<delta and diff<1.*err:
                        delta = diff
                        match = j
                if match is not None:
                    refit.append([pos,match])
        refit = scipy.asarray(refit)
        refit[:,1] = numpy.log10(refit[:,1])
        solution = sf.lsqfit(refit,'chebyshev',3)

        #refit[:,0],refit[:,1] = refit[:,1].copy(),refit[:,0].copy()
        #refit = numpy.array([refit[:,1],refit[:,0]]).T
        #refit = refit[:,::-1]
        solution2 = sf.lsqfit(refit[:,::-1],'chebyshev',3)
        #soln.append([solution,solution2])

        w = 10**sf.genfunc(xvals,0.,solution)
        if (w==wave).all() or converge>8:
            print("Order %d converged in %d iterations"%(i,converge))
            soln.append([solution,solution2])
            break
            for arc in arclist:
                pylab.plot(w,trace[arc])
                pylab.plot(w,fitD[arc])
                pp = 10**sf.genfunc(peaks[arc],0.,solution)
                for p in pp:
                    pylab.axvline(p,c='k')
            for j in 10**refit[:,1]:
                if j>w[0] and j<w[-1]:
                    pylab.axvline(j)
            pylab.show()
            break
    return soln
示例#14
0
def jointSolve(d,orders):
    import pylab
    path = __path__[0]

    lines = {}
    lines['cuar'] = numpy.loadtxt(path+"/data/cuar.lines")
    lines['hgne'] = numpy.loadtxt(path+"/data/hgne.lines")
    lines['xe'] = numpy.loadtxt(path+"/data/xe.lines")

    startsoln = numpy.load(path+"/data/esi_wavesolution.dat")
    startsoln = numpy.load(path+'/data/shao_wave.dat')
    startsoln = [i for i,j in startsoln]
    alldata = d['arc']
    arclist = d.keys()
    arclist.remove('arc')
    soln = []
    if alldata.shape[1]>3000:
        xvals = numpy.arange(4096.)
        resolve = False
        cuslice = slice(3860,3940)
        fw1 = 75.
        fw2 = 9
        WIDTH = 4
    else:
        xvals = numpy.arange(2048.)
        resolve = True
        cuslice = slice(1930,1970)
        fw1 = 37.
        fw2 = 7
        WIDTH = 3
    for i in range(10):
      solution = startsoln[i]
      start,end = orders[i]
      if resolve==True:
        tmp = numpy.arange(0.5,4096.,2.)
        w = sf.genfunc(tmp,0.,solution)
        solution = sf.lsqfit(numpy.array([xvals,w]).T,'chebyshev',3)

      data = numpy.nanmedian(alldata[start:end],axis=0)
      data[numpy.isnan(data)] = 0.
      if i==0:
        data[cuslice] = numpy.median(data)
      bak = ndimage.percentile_filter(data,50.,int(fw1))
      data -= bak

      peaks = []
      p = ndimage.maximum_filter(data,fw2)
      std = clip(numpy.trim_zeros(data),3.)[1]
      peak = numpy.where((p>30.*std)&(p==data))[0]
      for p in peak:
          if p-WIDTH<0 or p+WIDTH+1>xvals.size:
              continue
          x = xvals[p-WIDTH:p+WIDTH+1].copy()
          f = data[p-WIDTH:p+WIDTH+1].copy()
          fitdata = numpy.array([x,f]).T
          fit = numpy.array([0.,f.max(),xvals[p],1.])
          fit,chi = sf.ngaussfit(fitdata,fit,weight=1)
          peaks.append(fit[2])

      for converge in range(10):
        wave = 10**sf.genfunc(xvals,0.,solution)

        refit = []
        corr = []
        err = wave[wave.size/2]-wave[wave.size/2-1]
        p = 10.**sf.genfunc(peaks,0.,solution)
        for arc in arclist:
            for k in range(p.size):
                if i==0 and p[k]>4344.:
                    continue
                cent = p[k]
                diff = cent-lines[arc]
                corr.append(diff[abs(diff).argmin()])
        corr = numpy.array(corr)
        corr = corr[abs(corr)<5*err]
        m,s = clip(corr)
        corr = numpy.median(corr[abs(corr-m)<5.*s])
        for arc in arclist:
            for k in range(p.size):
                if i==0 and p[k]>4344.:
                    continue
                pos = peaks[k]
                cent = p[k]
                diff = abs(cent-lines[arc]-corr)
                if diff.min()<2.*err:
                    refit.append([pos,lines[arc][diff.argmin()]])
        refit = numpy.asarray(refit)
        solution = sf.lsqfit(refit,'polynomial',3)
        refit = []
        err = solution['coeff'][1]
        p = sf.genfunc(peaks,0.,solution)
        for k in range(p.size):
            delta = 1e9
            match = None
            for arc in arclist:
                for j in lines[arc]:
                    if i==0 and j>4344.:
                        continue
                    diff = abs(p[k]-j)
                    if diff<delta and diff<1.*err:
                        delta = diff
                        match = j
            if match is not None:
                refit.append([peaks[k],match])
        refit = numpy.asarray(refit)
        refit[:,1] = numpy.log10(refit[:,1])
        solution = sf.lsqfit(refit,'chebyshev',3)

        solution2 = sf.lsqfit(refit[:,::-1],'chebyshev',3)

        g = 10**sf.genfunc(peaks,0.,solution)
        g2 = 10**sf.genfunc(peak,0.,solution)
        w = 10**sf.genfunc(xvals,0.,solution)
        if (w==wave).all():
            print("Order %d converged in %d iterations"%(i,converge))
            soln.append([solution,solution2])
            break
            pylab.plot(w,data)
            for arc in arclist:
                for j in lines[arc]:
                    if j>w[0] and j<w[-1]:
                        pylab.axvline(j,c='b')
            for j in 10**refit[:,1]:
                if j>w[0] and j<w[-1]:
                    pylab.axvline(j,c='r')
            for j in g:
                pylab.axvline(j,c='g')
            for j in g2:
                pylab.axvline(j,c='c')
            pylab.show()
            break

    return soln
示例#15
0
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
示例#16
0
def extract(data, varimg, fitwidth=10., extractwidth=1.5, thresh=5.):
    """
	extract(data,varimg,width=WIDTH,nsig=NSIG,noise=NOISE)

	From an input 2d array, find and extract spectral traces.

	Inputs:
	  data       - 2d science spectrum
	  varimg     - 2d variance spectrum
	  fitwidth   - width to fit profile to in pixels
	  extractwidth - width to extract (in sigma)
	  thresh       - signal/noise threshold for extraction

	Outputs:
	  a list containing the [profile, extracted spectrum, a smoothed
	    spectrum, the extracted variance spectrum] for each extracted
	    trace
	"""

    WIDTH = fitwidth
    NSIG = extractwidth
    NOISE = thresh
    FILTSIZE = 7

    data = data.copy()
    spectra = []

    # Replace nan with zero
    data[scipy.isnan(data)] = 0.
    varimg[scipy.isnan(varimg)] = 0.
    data[scipy.isinf(data)] = 0.
    varimg[scipy.isinf(varimg)] = 0.

    # Create model of real flux. We ignore the slit ends, which may have
    #  artifacts from the resampling.
    slit = data[:, 8:-8].astype(scipy.float32)
    var = varimg[:, 8:-8]

    # OK...so negative-variance also isn't good; set these pixels to zero
    var[var < 0] = 0

    # Create noise models
    sigmaimg = slit / scipy.sqrt(var)
    highpix = scipy.where(sigmaimg > 1.5, sigmaimg, 0.)
    source_columns = highpix.sum(axis=0)

    # MASKING DISABLED (this would take only columns with lotsa flux...)
    #	mask = scipy.where(source_columns>4.,1.,scipy.nan)
    mask = source_columns * 0.

    # Condition 1, dealing with bad pixels
    if (var == 0).any():
        cond = var == 0
        var[cond] = scipy.nan
        slit[cond] = scipy.nan
        mask = scipy.where(cond, 0, 1)
        flux = scipy.nansum(slit / var, axis=1) / scipy.nansum(1. / var,
                                                               axis=1)
        noise = scipy.sqrt(scipy.nansum(var, axis=1)) / mask.sum(axis=1)
    # Condition 2, no masking
    elif scipy.nansum(mask) == 0:
        flux = (slit / var).sum(axis=1) / (1. / var).sum(axis=1)
        noise = scipy.sqrt(var.sum(axis=1)) / mask.size
    # Condition 3, masking
    else:
        fluxmodel = slit * mask
        noisemodel = var * mask

        noise = scipy.sqrt(scipy.nansum(noisemodel,
                                        axis=1)) / scipy.nansum(mask)
        flux = stats.stats.nanmean(fluxmodel, axis=1)

    # A smooth S/N estimate for the slit
#	sig2noise = ndimage.gaussian_filter1d(flux,1)/noise

    row = scipy.arange(flux.size)
    model = flux.copy()
    nspec = 10  # Maximum number of attempts
    while nspec:
        nspec -= 1

        # Fit a gaussian around the peak of the S/N model
        start = model.argmax() - WIDTH
        end = model.argmax() + WIDTH + 1
        if start < 0:
            start = 0.
        if end > model.size:
            end = model.size

        fitarr = model[start:end]
        p = scipy.zeros(4)
        p[1] = fitarr.max()
        p[2] = fitarr.argmax()
        p[3] = 2.

        fit, val = special_functions.ngaussfit(fitarr, p)
        chi2 = val / (fitarr.size - 3)
        fit[2] += start

        # If the centroid doesn't lie on the slit, get use the edge pix
        midcol = fit[2].round()
        if midcol >= flux.size:
            midcol = flux.size - 1
        elif midcol < 0:
            midcol = 0
        # Require a reasonable S/N and width
        if fit[3] > fitarr.size / 2. or fit[3] < 0.85:
            break
        elif fit[0] > 0 and fit[1] < NOISE * noise[midcol]:
            break
        elif fit[0] < 0 and fit[1] - fit[0] < NOISE * noise[midcol]:
            break
        else:
            fit[1] += fit[0]
            fit[0] = 0.
            # Subtract away a model of the source
            source = special_functions.ngauss(row, fit)
            model -= scipy.where(source > noise, source, 0.)

            # Skip Slits off the edge
            if fit[2] < 0 or fit[2] >= flux.size:
                continue
            # Skip residuals!
            if fit[1] < scipy.sqrt(flux[fit[2]]):
                continue
            fit[1] = 1.
            weight = special_functions.ngauss(row, fit)
            cond = (row > fit[2] - fit[3] * NSIG) & (row <
                                                     fit[2] + fit[3] * NSIG)
            weight = scipy.where(cond, weight, 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, FILTSIZE, varspec)
            smooth[scipy.isnan(smooth)] = 0.
            spectra.append([fit, spec, smooth, varspec])
    return spectra