Skip to content

Commit

Permalink
Save Flux_scalars, the average value of each model spectrum, required…
Browse files Browse the repository at this point in the history
… for absolute flux of models and accurate solid angles.

Note that this is backwards-INCOMPATIBLE.  We have to pass an extra positional argument to many of the classes and methods that are not expecting one.  So trying to use this code with previous versions will fail.  This change is not desirable but the old code was misleading in the solid angle support, so it can be considered a bug fix.
  • Loading branch information
gully committed Apr 4, 2017
1 parent d851492 commit 7b2afc7
Showing 1 changed file with 26 additions and 34 deletions.
60 changes: 26 additions & 34 deletions Starfish/emulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class PCAGrid:
Create and query eigenspectra.
'''

def __init__(self, wl, dv, flux_mean, flux_std, eigenspectra, w, w_hat, gparams):
def __init__(self, wl, dv, flux_mean, flux_std, eigenspectra, w, w_hat, gparams, flux_scalars):
'''
:param wl: wavelength array
Expand All @@ -91,13 +91,16 @@ def __init__(self, wl, dv, flux_mean, flux_std, eigenspectra, w, w_hat, gparams)
:type w: 2D np.array (m, M)
:param gparams: The stellar parameters of the synthetic library
:type gparams: 2D array of parameters (nspec, nparam)
:param flux_scalar: scalar average of each spectrum
:type flux_scalar: 1D np.array (M)
'''
self.wl = wl
self.dv = dv
self.flux_mean = flux_mean
self.flux_std = flux_std
self.eigenspectra = eigenspectra
self.flux_scalars = flux_scalars
self.m = len(self.eigenspectra)
self.w = w
self.w_hat = w_hat
Expand Down Expand Up @@ -136,7 +139,8 @@ def create(cls, interface):

# Normalize all of the fluxes to an average value of 1
# In order to remove uninteresting correlations
fluxes = fluxes/np.average(fluxes, axis=1)[np.newaxis].T
flux_scalars = np.average(fluxes, axis=1)
fluxes = fluxes/flux_scalars[np.newaxis].T

# Subtract the mean from all of the fluxes.
flux_mean = np.average(fluxes, axis=0)
Expand Down Expand Up @@ -184,7 +188,7 @@ def create(cls, interface):
# Calculate w_hat, Eqn 20 Habib
w_hat = get_w_hat(eigenspectra, fluxes, M)

return cls(wl, dv, flux_mean, flux_std, eigenspectra, w, w_hat, gparams)
return cls(wl, dv, flux_mean, flux_std, eigenspectra, w, w_hat, gparams,flux_scalars)

def write(self, filename=Starfish.PCA["path"]):
'''
Expand All @@ -208,6 +212,9 @@ def write(self, filename=Starfish.PCA["path"]):
pdset[2,:] = self.flux_std
pdset[3:, :] = self.eigenspectra

scalarset = hdf5.create_dataset("flux_scalars", (self.M,), compression='gzip', dtype="f8", compression_opts=9)
scalarset[:] = self.flux_scalars

wdset = hdf5.create_dataset("w", (self.m, self.M), compression='gzip',
dtype="f8", compression_opts=9)
wdset[:] = self.w
Expand Down Expand Up @@ -244,13 +251,16 @@ def open(cls, filename=Starfish.PCA["path"]):
wdset = hdf5["w"]
w = wdset[:]

scalarset = hdf5["flux_scalars"]
flux_scalars = scalarset[:]

w_hatdset = hdf5["w_hat"]
w_hat = w_hatdset[:]

gdset = hdf5["gparams"]
gparams = gdset[:]

pcagrid = cls(wl, dv, flux_mean, flux_std, eigenspectra, w, w_hat, gparams)
pcagrid = cls(wl, dv, flux_mean, flux_std, eigenspectra, w, w_hat, gparams, flux_scalars)
hdf5.close()

return pcagrid
Expand Down Expand Up @@ -327,36 +337,6 @@ def reconstruct_all(self):

return recon_fluxes


class F_bol_interp:
'''
Interpolate the F_bol from the grid for any arbitrary stellar parameter
'''
def __init__(self, GridInterface):
'''
Provide the emulation products.
:param pca: object storing the principal components, the eigenpsectra
:type pca: PCAGrid
:param eparams: Optimized GP hyperparameters.
:type eparams: 1D np.array
'''

myHDF5 = HDF5Interface()
n_gps, n_dims = myHDF5.grid_points.shape
F_bol = np.zeros(n_gps)
for i in range(n_gps):
_, hdr = myHDF5.load_flux_hdr(myHDF5.grid_points[i])
F_bol[i] = hdr["F_bol"]
X_grid = myHDF5.grid_points
y_dat = F_bol
ld = LinearNDInterpolator(X_grid, y_dat)
self.ld = ld

def interp(self, grid_pars):
return self.ld(grid_pars)


class Emulator:
def __init__(self, pca, eparams):
'''
Expand Down Expand Up @@ -384,13 +364,18 @@ def __init__(self, pca, eparams):

self.V11 = self.iPhiPhi + Sigma(self.pca.gparams, self.h2params)

self.ld = LinearNDInterpolator(self.pca.gparams, self.pca.flux_scalars)

self._params = None # Where we want to interpolate

self.V12 = None
self.V22 = None
self.mu = None
self.sig = None

# New in v0.3: absolute flux scalar
self.flux_scalar = None

@classmethod
def open(cls, filename=Starfish.PCA["path"]):
'''
Expand Down Expand Up @@ -437,10 +422,17 @@ def params(self, pars):
self.mu.shape = (-1)
self.sig = self.V22 - self.V12.T.dot(np.linalg.solve(self.V11, self.V12))

# Calculate the flux_scalar
self.flux_scalar = self.ld(self._params)

@property
def matrix(self):
return (self.mu, self.sig)

@property
def absolute_flux(self):
return self.flux_scalar

def draw_many_weights(self, params):
'''
:param params: multiple parameters to produce weight draws at.
Expand Down

1 comment on commit 7b2afc7

@iancze
Copy link
Collaborator

@iancze iancze commented on 7b2afc7 Apr 4, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds like a good idea! It does a much more intuitive job of bookkeeping than the previous solutions (which should be considered buggy, as you note). As long as we keep everything to the development branch for now, I am more than OK with backwards-incompatible changes if they make the next release (v2.0?) that much more user-friendly. At that point we'll just need to do a thorough job updating (and perhaps simplifying) the documentation and tutorials.

Please sign in to comment.