def optimize_region_residual(wl, residuals, sigma, mu): ''' Determine the optimal parameters for the line kernels by fitting a Gaussian directly to the residuals. ''' # Using sigma0, truncate the wavelength vector and residulas to include # only those portions that fall in the range [mu - sigma, mu + sigma] ind = (wl > mu - args.sigma0) & (wl < mu + args.sigma0) wl = wl[ind] R = residuals[ind] sigma = sigma[ind] sigma_mat = phi.sigAmp * sigma**2 * np.eye(len(wl)) max_r = 6.0 * phi.l # [km/s] k_func = make_k_func(phi) # Use the full covariance matrix when doing the likelihood eval CC = get_dense_C(wl, k_func=k_func, max_r=max_r) + sigma_mat factor, flag = cho_factor(CC) logdet = np.sum(2 * np.log((np.diag(factor)))) rr = C.c_kms/mu * np.abs(mu - wl) # Km/s def fprob(p): # The likelihood function # Requires sign about amplitude, so we can't use log. amp, sig = p gauss = amp * np.exp(-0.5 * rr**2/sig**2) r = R - gauss # Create a Gaussian using these parameters, and re-evaluate the residual lnprob = -0.5 * (np.dot(r, cho_solve((factor, flag), r)) + logdet) return lnprob par = Starfish.config["region_params"] p0 = np.array([10**par["logAmp"], par["sigma"]]) f = lambda x: -fprob(x) try: p = fmin(f, p0, maxiter=10000, maxfun=10000, disp=False) # print(p) return p except np.linalg.linalg.LinAlgError: return p0
def update_Phi(self, phi): self.logger.debug("Updating nuisance parameters to {}".format(phi)) # Read off the Chebyshev parameters and update self.chebyshevSpectrum.update(phi.cheb) # Check to make sure the global covariance parameters make sense if phi.sigAmp < 0.1: raise C.ModelError("sigAmp shouldn't be lower than 0.1, something is wrong.") max_r = 6.0 * phi.l # [km/s] # Create a partial function which returns the proper element. k_func = make_k_func(phi) # Store the previous data matrix in case we want to revert later self.data_mat_last = self.data_mat self.data_mat = get_dense_C(self.wl, k_func=k_func, max_r=max_r) + phi.sigAmp*self.sigma_mat + self.region_mat
def fprob(p): logAmp, sigma = p # set phi.regions = p phi.regions = np.array([logAmp, mu, sigma])[np.newaxis, :] max_rr = 4.0 * sigma max_r = max(max_rl, max_rr) k_func = make_k_func(phi) CC = get_dense_C(wl, k_func=k_func, max_r=max_r) + sigma_mat factor, flag = cho_factor(CC) logdet = np.sum(2 * np.log((np.diag(factor)))) lnprob = -0.5 * (np.dot(R, cho_solve((factor, flag), R)) + logdet) # print(p, lnprob) return lnprob
def update_nuisance(self, params): ''' Update the nuisance parameters and data covariance matrix. :param params: large dictionary containing cheb, cov, and regions ''' self.logger.debug("Updating nuisance parameters to {}".format(params)) # Read off the Chebyshev parameters and update self.ChebyshevSpectrum.update(params["cheb"]) # Create the full data covariance matrix. l = params["cov"]["l"] sigAmp = params["cov"]["sigAmp"] # Check to make sure the global covariance parameters make sense if sigAmp < 0.1: raise C.ModelError( "sigAmp shouldn't be lower than 0.1, something is wrong.") max_r = 6.0 * l # [km/s] # Check all regions, take the max if self.nregions > 0: regions = params["regions"] keys = sorted(regions) sigmas = np.array([regions[key]["sigma"] for key in keys]) #km/s #mus = np.array([regions[key]["mu"] for key in keys]) max_reg = 4.0 * np.max(sigmas) #If this is a larger distance than the global length, replace it max_r = max_reg if max_reg > max_r else max_r #print("Max_r now set by regions {}".format(max_r)) # print("max_r is {}".format(max_r)) # Create a partial function which returns the proper element. k_func = make_k_func(params) # Store the previous data matrix in case we want to revert later self.data_mat_last = self.data_mat self.data_mat = get_dense_C(self.wl, k_func=k_func, max_r=max_r) + sigAmp * self.sigma_matrix
def update_Phi(self, p): self.logger.debug("Updating nuisance parameters to {}".format(p)) # Read off the Chebyshev parameters and update ## May 1, 2017-- Turn off the Chebyshev spectrum for SpeX Prism mode. ## See Issue #13 in jammer: ## github.com/BrownDwarf/jammer/issues/13 #self.chebyshevSpectrum.update(p.cheb) # Check to make sure the global covariance parameters make sense #if p.sigAmp < 0.1: # raise C.ModelError("sigAmp shouldn't be lower than 0.1, something is wrong.") max_r = 6.0 * p.l # [km/s] # Create a partial function which returns the proper element. k_func = make_k_func(p) # Store the previous data matrix in case we want to revert later self.data_mat_last = self.data_mat self.data_mat = get_dense_C(self.wl, k_func=k_func, max_r=max_r) + p.sigAmp*self.sigma_mat
def update_nuisance(self, params): ''' Update the nuisance parameters and data covariance matrix. :param params: large dictionary containing cheb, cov, and regions ''' self.logger.debug("Updating nuisance parameters to {}".format(params)) # Read off the Chebyshev parameters and update self.ChebyshevSpectrum.update(params["cheb"]) # Create the full data covariance matrix. l = params["cov"]["l"] sigAmp = params["cov"]["sigAmp"] # Check to make sure the global covariance parameters make sense if sigAmp < 0.1: raise C.ModelError("sigAmp shouldn't be lower than 0.1, something is wrong.") max_r = 6.0 * l # [km/s] # Check all regions, take the max if self.nregions > 0: regions = params["regions"] keys = sorted(regions) sigmas = np.array([regions[key]["sigma"] for key in keys]) #km/s #mus = np.array([regions[key]["mu"] for key in keys]) max_reg = 4.0 * np.max(sigmas) #If this is a larger distance than the global length, replace it max_r = max_reg if max_reg > max_r else max_r #print("Max_r now set by regions {}".format(max_r)) # print("max_r is {}".format(max_r)) # Create a partial function which returns the proper element. k_func = make_k_func(params) # Store the previous data matrix in case we want to revert later self.data_mat_last = self.data_mat self.data_mat = get_dense_C(self.wl, k_func=k_func, max_r=max_r) + sigAmp*self.sigma_matrix
sigma_mat = sigma**2 * np.eye(len(sigma)) fname = Starfish.specfmt.format(spectrum_id, order) + "phi.json" phi = PhiParam.load(fname) if phi.regions is not None: region_func = make_k_func_region(phi) max_r = 4.0 * np.max(phi.regions, axis=0)[2] region_mat = get_dense_C(wl, k_func=region_func, max_r=max_r) else: region_mat = 0.0 max_r = 6.0 * phi.l # [km/s] # Create a partial function which returns the proper element. k_func = make_k_func(phi) data_mat = get_dense_C(wl, k_func=k_func, max_r=max_r) + phi.sigAmp * sigma_mat + region_mat # Get many random draws from data_mat draws = random_draws(data_mat, num=4) min_spec, max_spec = std_envelope(draws) if args.matplotlib: import matplotlib.pyplot as plt fig, ax = plt.subplots(nrows=2, figsize=(10, 8), sharex=True) ax[0].plot(wl, data, "b", label="data") ax[0].plot(wl, model, "r", label="model")
sigma_mat = sigma**2 * np.eye(len(sigma)) fname = Starfish.specfmt.format(spectrum_id, order) + "phi.json" phi = PhiParam.load(fname) if phi.regions is not None: region_func = make_k_func_region(phi) max_r = 4.0 * np.max(phi.regions, axis=0)[2] region_mat = get_dense_C(wl, k_func=region_func, max_r=max_r) else: region_mat = 0.0 max_r = 6.0 * phi.l # [km/s] # Create a partial function which returns the proper element. k_func = make_k_func(phi) data_mat = get_dense_C(wl, k_func=k_func, max_r=max_r) + phi.sigAmp*sigma_mat + region_mat # Get many random draws from data_mat draws = random_draws(data_mat, num=4) min_spec, max_spec = std_envelope(draws) if args.matplotlib: import matplotlib.pyplot as plt fig, ax = plt.subplots(nrows=2, figsize=(10, 8), sharex=True) ax[0].plot(wl, data, "b", label="data") ax[0].plot(wl, model, "r", label="model")