In [ ]:
# Third-party
from astropy.io import ascii, fits
import astropy.coordinates as coord
import astropy.units as u
from astropy.constants import c
import matplotlib as mpl
import matplotlib.pyplot as pl
import numpy as np
from scipy.interpolate import interp1d

pl.style.use('apw-notebook')
%matplotlib inline
# pl.style.use('classic')
# %matplotlib notebook

In [ ]:
data_files = ["../data/apVisit-r5-6994-56770-261.fits", "../data/apVisit-r5-6994-56794-177.fits"]
model_file = "../data/apStar-r5-2M00004994+1621552.fits"

In [ ]:
min_wvln = 15329
max_wvln = 15359

In [ ]:
def load_file(filename, chip):
    hdulist1 = fits.open(filename)
    wvln = hdulist1[4].data[chip]
    ix = (wvln >= min_wvln) & (wvln <= max_wvln)
    
    wvln = wvln[ix]
    flux = hdulist1[1].data[chip,ix]
    flux_err = hdulist1[2].data[chip,ix]
    
    return {'wvln': wvln, 'flux': flux, 'flux_err': flux_err}
    
def load_model_file(filename):
    hdulist1 = fits.open(filename)
    flux = hdulist1[1].data[0]
    flux_err = hdulist1[2].data[0]
    wvln = 10**(hdulist1[0].header['CRVAL1'] + np.arange(flux.size) * hdulist1[0].header['CDELT1'])
    
#     ix = (wvln >= min_wvln) & (wvln <= max_wvln)
    ix = (wvln < 15750) & (wvln > 15150) # HACK: magic numbers
    return {'wvln': wvln[ix], 'flux': flux[ix], 'flux_err': flux_err[ix]}

In [ ]:
d = load_file(fn, chip=2)
d['wvln'].shape

In [ ]:
chip = 2

fig,ax = pl.subplots(1,1,figsize=(12,6))

for fn in data_files:
    d = load_file(fn, chip=chip)
    ax.plot(d['wvln'], d['flux'], drawstyle='steps', marker=None)
    
ref_spec = load_model_file(model_file)
ax.plot(ref_spec['wvln'], 3.2*ref_spec['flux'], drawstyle='steps', marker=None, lw=2.) # HACK: scale up

# _d = 175
# ax.set_xlim(15150.+_d, 15175.+_d)
# ax.set_ylim(10000, 20000)

In [ ]:
all_spectra = [load_file(f, chip=2) for f in files]

In [ ]:
ref_spec['interp'] = interp1d(ref_spec['wvln'], ref_spec['flux'], kind='cubic', bounds_error=False)

In [ ]:
def get_design_matrix(data, ref_spec, v1, v2):
    """
    Note: Positive velocity is a redshift.
    """
    X = np.ones((3, data['wvln'].shape[0]))
    X[1] = ref_spec['interp'](data['wvln'] * (1 + v1/c)) # this is only good to first order in (v/c)
    X[2] = ref_spec['interp'](data['wvln'] * (1 + v2/c))
    return X

In [ ]:
def get_optimal_chisq(data, ref_spec, v1, v2):
    X = get_design_matrix(data, ref_spec, v1, v2)
    return np.linalg.solve( X.dot(X.T), X.dot(data['flux']) )

In [ ]:
spec_i = 1
v1 = 35 * u.km/u.s
v2 = -5 * u.km/u.s
X = get_design_matrix(all_spectra[spec_i], ref_spec, v1, v2)
opt_pars = get_optimal_chisq(all_spectra[spec_i], ref_spec, v1, v2)
opt_pars

In [ ]:
def make_synthetic_spectrum(X, pars):
    return X.T.dot(pars)

def compute_chisq(data, X, opt_pars):
    synth_spec = make_synthetic_spectrum(X, opt_pars)
    return -np.sum((synth_spec - data['flux'])**2)

In [ ]:
# opt_pars = np.array([1.1E+4, 0.5,  0.5])
synth_spec = make_synthetic_spectrum(X, opt_pars)

In [ ]:
pl.plot(all_spectra[spec_i]['wvln'], all_spectra[spec_i]['flux'], marker=None, drawstyle='steps')
pl.plot(all_spectra[spec_i]['wvln'], synth_spec, marker=None, drawstyle='steps')

In [ ]:
_v1_grid = np.linspace(25, 45, 32)
_v2_grid = np.linspace(-15, 5, 32)
shp = (_v1_grid.size, _v2_grid.size)
v_grid = np.vstack(map(np.ravel, np.meshgrid(_v1_grid, _v2_grid))).T
v_grid.shape

In [ ]:
chisq = np.zeros(v_grid.shape[0])
for i in range(v_grid.shape[0]):
    v1,v2 = v_grid[i]
    opt_pars = get_optimal_chisq(all_spectra[spec_i], ref_spec, 
                                 v1*u.km/u.s, v2*u.km/u.s)
    chisq[i] = compute_chisq(all_spectra[spec_i], X, opt_pars)

In [ ]:
fig,ax = pl.subplots(1,1,figsize=(9,8))

cb = ax.pcolormesh(v_grid[:,0].reshape(shp), v_grid[:,1].reshape(shp), 
                   chisq.reshape(shp), cmap='magma')

fig.colorbar(cb)

In [ ]:
fig,ax = pl.subplots(1,1,figsize=(9,8))

cb = ax.pcolormesh(v_grid[:,0].reshape(shp), v_grid[:,1].reshape(shp), 
                   np.exp(chisq-chisq.max()).reshape(shp), cmap='magma')

fig.colorbar(cb)

In [ ]:
fig,ax = pl.subplots(1,1,figsize=(9,8))

cb = ax.pcolormesh(v_grid[:,0].reshape(shp), v_grid[:,1].reshape(shp), 
                   chisq.reshape(shp), cmap='magma')

fig.colorbar(cb)

In [ ]:
fig,ax = pl.subplots(1,1,figsize=(9,8))

cb = ax.pcolormesh(v_grid[:,0].reshape(shp), v_grid[:,1].reshape(shp), 
                   np.exp(chisq-chisq.max()).reshape(shp), cmap='magma')

fig.colorbar(cb)

try using levmar to optimize


In [ ]:
from scipy.optimize import leastsq

In [ ]:
def errfunc(pars, data_spec, ref_spec):
    v1,v2,a,b,c = pars
    X = get_design_matrix(data_spec, ref_spec, v1*u.km/u.s, v2*u.km/u.s)
    synth_spec = make_synthetic_spectrum(X, [a,b,c])
    return (synth_spec - data_spec['flux'])

In [ ]:
levmar_opt_pars,ier = leastsq(errfunc, x0=[35,-5]+opt_pars.tolist(), args=(all_spectra[0], ref_spec))

In [ ]:
levmar_opt_pars

In [ ]:
data_spec = all_spectra[0]
X = get_design_matrix(data_spec, ref_spec, levmar_opt_pars[0]*u.km/u.s, levmar_opt_pars[1]*u.km/u.s)
synth_spec = make_synthetic_spectrum(X, levmar_opt_pars[2:])
pl.plot(data_spec['wvln'], data_spec['flux'], marker=None, drawstyle='steps')
pl.plot(data_spec['wvln'], synth_spec, marker=None, drawstyle='steps')

In [ ]: