def dask_fit_fourier_pl_c(power_spectrum): """ Fits the power law + constant observation model Parameters ---------- power_spectrum : Return ------ """ # Make the random data into a Powerspectrum object ps = Powerspectrum() ps.freq = power_spectrum[0] ps.power = power_spectrum[1] ps.df = ps.freq[1] - ps.freq[0] ps.m = 1 # Define the log-likelihood of the data given the model loglike = PSDLogLikelihood(ps.freq, ps.power, observation_model, m=ps.m) # Parameter estimation object parameter_estimate = PSDParEst(ps, fitmethod="L-BFGS-B", max_post=False) # Estimate the starting parameters ipe = InitialParameterEstimatePlC(ps.freq, ps.power) return parameter_estimate.fit(loglike, [ipe.amplitude, ipe.index, ipe.background], scipy_optimize_options=scipy_optimize_options)
def test_fit_method_returns_optimization_results_object(self): pe = PSDParEst(self.ps) lpost = PSDPosterior(self.ps, self.model, self.priors) t0 = [2.0, 1, 1, 1] res = pe.fit(self.lpost, t0) assert isinstance(res, OptimizationResults), "res must be of type " \ "OptimizationResults"
def test_fit_method_works_with_correct_parameter(self): pe = PSDParEst(self.ps) lpost = PSDPosterior(self.ps.freq, self.ps.power, self.model, self.priors, m=self.ps.m) t0 = [2.0, 1, 1, 1] res = pe.fit(lpost, t0) assert isinstance(res, OptimizationResults), "res must be of type " \ "OptimizationResults" pe.plotfits(res, save_plot=True) assert os.path.exists("test_ps_fit.png") os.unlink("test_ps_fit.png") pe.plotfits(res, save_plot=True, log=True) assert os.path.exists("test_ps_fit.png") os.unlink("test_ps_fit.png") pe.plotfits(res, res2=res, save_plot=True) assert os.path.exists("test_ps_fit.png") os.unlink("test_ps_fit.png") pe.plotfits(res, res2=res, log=True, save_plot=True) assert os.path.exists("test_ps_fit.png") os.unlink("test_ps_fit.png")
def test_simulate_highest_outlier_works(self): m = 1 nfreq = 100000 seed = 100 freq = np.linspace(1, 10, nfreq) rng = np.random.RandomState(seed) noise = rng.exponential(size=nfreq) model = models.Const1D() model.amplitude = 2.0 p = model(freq) power = noise * p ps = Powerspectrum() ps.freq = freq ps.power = power ps.m = m ps.df = freq[1] - freq[0] ps.norm = "leahy" nsim = 10 loglike = PSDLogLikelihood(ps.freq, ps.power, model, m=1) s_all = np.atleast_2d(np.ones(nsim) * 2.0).T pe = PSDParEst(ps) res = pe.fit(loglike, [2.0], neg=True) maxpow_sim = pe.simulate_highest_outlier(s_all, loglike, [2.0], max_post=False, seed=seed) assert maxpow_sim.shape[0] == nsim assert np.all(maxpow_sim > 20.00) and np.all(maxpow_sim < 31.0)
def test_compute_highest_outlier_works(self): mp_ind = 5 max_power = 1000.0 ps = Powerspectrum() ps.freq = np.arange(10) ps.power = np.ones_like(ps.freq) ps.power[mp_ind] = max_power ps.m = 1 ps.df = ps.freq[1]-ps.freq[0] ps.norm = "leahy" model = models.Const1D() p_amplitude = lambda amplitude: \ scipy.stats.norm(loc=1.0, scale=1.0).pdf( amplitude) priors = {"amplitude": p_amplitude} lpost = PSDPosterior(ps.freq, ps.power, model, 1) lpost.logprior = set_logprior(lpost, priors) pe = PSDParEst(ps) res = pe.fit(lpost, [1.0]) res.mfit = np.ones_like(ps.freq) max_y, max_x, max_ind = pe._compute_highest_outlier(lpost, res) assert np.isclose(max_y[0], 2*max_power) assert np.isclose(max_x[0], ps.freq[mp_ind]) assert max_ind == mp_ind
def test_fit_method_returns_optimization_results_object(self): pe = PSDParEst(self.ps) t0 = [2.0, 1, 1, 1] res = pe.fit(self.lpost, t0) assert isinstance(res, OptimizationResults), "res must be of type " \ "OptimizationResults"
def test_fit_method_works_with_correct_parameter(self): pe = PSDParEst(self.ps) lpost = PSDPosterior(self.ps.freq, self.ps.power, self.model, self.priors, m=self.ps.m) t0 = [2.0, 1, 1, 1] res = pe.fit(lpost, t0)
def test_plotfits_log_leahy(self): pe = PSDParEst(self.ps) t0 = [2.0, 1, 1, 1] res = pe.fit(self.lpost, t0) pe.plotfits(res, save_plot=True, log=True) assert os.path.exists("test_ps_fit.png") os.unlink("test_ps_fit.png")
def test_plotfits_leahy(self): pe = PSDParEst(self.ps) t0 = [2.0, 1, 1, 1] lpost = PSDPosterior(self.ps, self.model, self.priors) res = pe.fit(lpost, t0) pe.plotfits(res, save_plot=True) assert os.path.exists("test_ps_fit.png") os.unlink("test_ps_fit.png")
def test_plotfits_leahy(self): pe = PSDParEst(self.ps) t0 = [2.0, 1, 1, 1] lpost = PSDPosterior(self.ps.freq, self.ps.power, self.model, self.priors, m=self.ps.m) res = pe.fit(lpost, t0) pe.plotfits(res, save_plot=True) assert os.path.exists("test_ps_fit.png") os.unlink("test_ps_fit.png")
def test_fitting_with_ties_and_bounds(self, capsys): double_f = lambda model: model.x_0_0 * 2 model = self.model.copy() model = self.model + models.Lorentz1D(amplitude=model.amplitude_0, x_0=model.x_0_0 * 2, fwhm=model.fwhm_0) model.x_0_0 = self.model.x_0_0 model.amplitude_0 = self.model.amplitude_0 model.amplitude_1 = self.model.amplitude_1 model.fwhm_0 = self.model.fwhm_0 model.x_0_2.tied = double_f model.fwhm_0.bounds = [0, 10] model.amplitude_0.fixed = True p = model(self.ps.freq) noise = np.random.exponential(size=len(p)) power = noise * p ps = Powerspectrum() ps.freq = self.ps.freq ps.power = power ps.m = self.ps.m ps.df = self.ps.df ps.norm = "leahy" pe = PSDParEst(ps) llike = PSDLogLikelihood(ps.freq, ps.power, model) true_pars = [ self.amplitude_0, self.x_0_0, self.fwhm_0, self.amplitude_1, model.amplitude_2.value, model.x_0_2.value, model.fwhm_2.value ] res = pe.fit(llike, true_pars) res.print_summary(llike) out, err = capsys.readouterr() assert "100.00000 (Fixed)" in out pattern = \ re.compile(r"5\) Parameter x_0_2\s+: [0-9]\.[0-9]{5}\s+\(Tied\)") assert pattern.search(out) compare_pars = [ self.x_0_0, self.fwhm_0, self.amplitude_1, model.amplitude_2.value, model.fwhm_2.value ] assert np.all(np.isclose(compare_pars, res.p_opt, rtol=0.5))
def test_plotfits_log_pow(self): ps = Powerspectrum() ps.freq = self.ps.freq ps.power = self.ps.power ps.m = self.ps.m ps.df = self.ps.df ps.norm = "none" pe = PSDParEst(ps) t0 = [2.0, 1, 1, 1] res = pe.fit(self.lpost, t0) pe.plotfits(res, res2=res, save_plot=True, log=True) assert os.path.exists("test_ps_fit.png") os.unlink("test_ps_fit.png")
def test_plotfits_pow(self): t0 = [2.0, 1, 1, 1] ps = Powerspectrum() ps.freq = self.ps.freq ps.power = self.ps.power ps.m = self.ps.m ps.df = self.ps.df ps.norm = "none" pe = PSDParEst(ps) lpost = PSDPosterior(self.ps, self.model, self.priors) res = pe.fit(self.lpost, t0) pe.plotfits(res, res2=res, save_plot=True) assert os.path.exists("test_ps_fit.png") os.unlink("test_ps_fit.png")
def test_fitting_with_ties_and_bounds(self, capsys, rebin): double_f = lambda model : model.x_0_0 * 2 model = self.model.copy() model += models.Lorentz1D(amplitude=model.amplitude_0, x_0 = model.x_0_0 * 2, fwhm = model.fwhm_0) model.x_0_0 = self.model.x_0_0 model.amplitude_0 = self.model.amplitude_0 model.amplitude_1 = self.model.amplitude_1 model.fwhm_0 = self.model.fwhm_0 model.x_0_2.tied = double_f model.fwhm_0.bounds = [0, 10] model.amplitude_0.fixed = True p = model(self.ps.freq) noise = np.random.exponential(size=len(p)) power = noise*p ps = Powerspectrum() ps.freq = self.ps.freq ps.power = power ps.m = self.ps.m ps.df = self.ps.df ps.norm = "leahy" if rebin != 0: ps = ps.rebin_log(rebin) pe = PSDParEst(ps, fitmethod="TNC") llike = PSDLogLikelihood(ps.freq, ps.power, model) true_pars = [self.x_0_0, self.fwhm_0, self.amplitude_1, model.amplitude_2.value, model.fwhm_2.value] res = pe.fit(llike, true_pars, neg=True) compare_pars = [self.x_0_0, self.fwhm_0, self.amplitude_1, model.amplitude_2.value, model.fwhm_2.value] assert np.allclose(compare_pars, res.p_opt, rtol=0.5)
def test_fitting_with_ties_and_bounds(self, capsys): double_f = lambda model : model.x_0_0 * 2 model = self.model.copy() model += models.Lorentz1D(amplitude=model.amplitude_0, x_0 = model.x_0_0 * 2, fwhm = model.fwhm_0) model.x_0_0 = self.model.x_0_0 model.amplitude_0 = self.model.amplitude_0 model.amplitude_1 = self.model.amplitude_1 model.fwhm_0 = self.model.fwhm_0 model.x_0_2.tied = double_f model.fwhm_0.bounds = [0, 10] model.amplitude_0.fixed = True p = model(self.ps.freq) noise = np.random.exponential(size=len(p)) power = noise*p ps = Powerspectrum() ps.freq = self.ps.freq ps.power = power ps.m = self.ps.m ps.df = self.ps.df ps.norm = "leahy" pe = PSDParEst(ps, fitmethod="TNC") llike = PSDLogLikelihood(ps.freq, ps.power, model) true_pars = [self.x_0_0, self.fwhm_0, self.amplitude_1, model.amplitude_2.value, model.fwhm_2.value] res = pe.fit(llike, true_pars, neg=True) compare_pars = [self.x_0_0, self.fwhm_0, self.amplitude_1, model.amplitude_2.value, model.fwhm_2.value] assert np.allclose(compare_pars, res.p_opt, rtol=0.5)
ps.freq = freq ps.power = powers ps.df = ps.freq[1] - ps.freq[0] ps.m = 1 # Define the log-likelihood of the data given the model loglike = PSDLogLikelihood(ps.freq, ps.power, observation_model, m=ps.m) # Parameter estimation object parameter_estimate = PSDParEst(ps, fitmethod="L-BFGS-B", max_post=False) # Estimate the starting parameters - will be replaced with a function # starting_parameters = starting_parameter_selector(model_name) starting_pars = [ amplitude, alpha, white_noise, ll_amplitude, ll_log_x_0, ll_fwhm ] # Do the fit and store the results z.append(parameter_estimate.fit(loglike, starting_pars)) t_end = Time.now() print('Time taken ', (t_end - t_start).to(u.s)) # Save the results #sp.save('/Users/Desktop/')
# flat prior for the power law amplitude p_amplitude = lambda amplitude: ((0.01 <= amplitude) & (amplitude <= 10.0)) # normal prior for the white noise parameter p_whitenoise = lambda white_noise: scipy.stats.norm(2.0, 0.1).pdf(white_noise) priors = {} priors["alpha_0"] = p_alpha priors["amplitude_0"] = p_amplitude priors["amplitude_1"] = p_whitenoise starting_pars = [3.0, 1.0, 2.4] lpost = PSDPosterior(ps.freq, ps.power, plc, priors=priors, m=ps.m) parest = PSDParEst(ps, fitmethod='BFGS', max_post=True) res = parest.fit(lpost, starting_pars) sample = parest.sample(lpost, res.p_opt, cov=res.cov, nwalkers=400, niter=100, burnin=200, namestr="psd_modeling_test") max_power, max_freq, max_ind = parest._compute_highest_outlier(lpost, res) print(max_power) pval = parest.calibrate_highest_outlier(lpost, starting_pars, sample=sample, max_post=True,
def test_fit_fails_when_object_is_not_posterior_or_likelihood(self): x = np.ones(10) y = np.ones(10) pe = PSDParEst(self.ps) with pytest.raises(TypeError): res = pe.fit(x, y)
def test_fit_fails_without_t0(self): pe = PSDParEst(self.ps) with pytest.raises(TypeError): res = pe.fit(np.ones(10))
def fit_powerspectrum(ps, model, starting_pars=None, max_post=False, priors=None, fitmethod="L-BFGS-B"): """ Fit a number of Lorentzians to a power spectrum, possibly including white noise. Each Lorentzian has three parameters (amplitude, centroid position, full-width at half maximum), plus one extra parameter if the white noise level should be fit as well. Priors for each parameter can be included in case `max_post = True`, in which case the function will attempt a Maximum-A-Posteriori fit. Priors must be specified as a dictionary with one entry for each parameter. The parameter names are `(amplitude_i, x_0_i, fwhm_i)` for each `i` out of a total of `N` Lorentzians. The white noise level has a parameter `amplitude_(N+1)`. For example, a model with two Lorentzians and a white noise level would have parameters: [amplitude_0, x_0_0, fwhm_0, amplitude_1, x_0_1, fwhm_1, amplitude_2]. Parameters ---------- ps : Powerspectrum A Powerspectrum object with the data to be fit model: astropy.modeling.models class instance The parametric model supposed to represent the data. For details see the astropy.modeling documentation starting_pars : iterable, optional, default None The list of starting guesses for the optimizer. If it is not provided, then default parameters are taken from `model`. See explanation above for ordering of parameters in this list. fit_whitenoise : bool, optional, default True If True, the code will attempt to fit a white noise level along with the Lorentzians. Be sure to include a starting parameter for the optimizer in `starting_pars`! max_post : bool, optional, default False If True, perform a Maximum-A-Posteriori fit of the data rather than a Maximum Likelihood fit. Note that this requires priors to be specified, otherwise this will cause an exception! priors : {dict | None}, optional, default None Dictionary with priors for the MAP fit. This should be of the form {"parameter name": probability distribution, ...} fitmethod : string, optional, default "L-BFGS-B" Specifies an optimization algorithm to use. Supply any valid option for `scipy.optimize.minimize`. Returns ------- parest : PSDParEst object A PSDParEst object for further analysis res : OptimizationResults object The OptimizationResults object storing useful results and quantities relating to the fit Examples -------- We start by making an example power spectrum with three Lorentzians >>> m = 1 >>> nfreq = 100000 >>> freq = np.linspace(1, 1000, nfreq) >>> np.random.seed(100) # set the seed for the random number generator >>> noise = np.random.exponential(size=nfreq) >>> model = models.PowerLaw1D() + models.Const1D() >>> model.x_0_0.fixed = True >>> alpha_0 = 2.0 >>> amplitude_0 = 100.0 >>> amplitude_1 = 2.0 >>> model.alpha_0 = alpha_0 >>> model.amplitude_0 = amplitude_0 >>> model.amplitude_1 = amplitude_1 >>> p = model(freq) >>> power = noise * p >>> ps = Powerspectrum() >>> ps.freq = freq >>> ps.power = power >>> ps.m = m >>> ps.df = freq[1] - freq[0] >>> ps.norm = "leahy" Now we have to guess starting parameters. For each Lorentzian, we have amplitude, centroid position and fwhm, and this pattern repeats for each Lorentzian in the fit. The white noise level is the last parameter. >>> t0 = [80, 1.5, 2.5] Let's also make a model to test: >>> model_to_test = models.PowerLaw1D() + models.Const1D() >>> model_to_test.amplitude_1.fixed = True We're ready for doing the fit: >>> parest, res = fit_powerspectrum(ps, model_to_test, t0) `res` contains a whole array of useful information about the fit, for example the parameters at the optimum: >>> p_opt = res.p_opt """ if not (isinstance(starting_pars, np.ndarray) or isinstance(starting_pars, list)): starting_pars = model.parameters if priors: lpost = PSDPosterior(ps.freq, ps.power, model, priors=priors, m=ps.m) else: lpost = PSDLogLikelihood(ps.freq, ps.power, model, m=ps.m) parest = PSDParEst(ps, fitmethod=fitmethod, max_post=max_post) res = parest.fit(lpost, starting_pars, neg=True) return parest, res
def fit_crossspectrum(cs, model, starting_pars=None, max_post=False, priors=None, fitmethod="L-BFGS-B"): """ Fit a number of Lorentzians to a cross spectrum, possibly including white noise. Each Lorentzian has three parameters (amplitude, centroid position, full-width at half maximum), plus one extra parameter if the white noise level should be fit as well. Priors for each parameter can be included in case `max_post = True`, in which case the function will attempt a Maximum-A-Posteriori fit. Priors must be specified as a dictionary with one entry for each parameter. The parameter names are `(amplitude_i, x_0_i, fwhm_i)` for each `i` out of a total of `N` Lorentzians. The white noise level has a parameter `amplitude_(N+1)`. For example, a model with two Lorentzians and a white noise level would have parameters: [amplitude_0, x_0_0, fwhm_0, amplitude_1, x_0_1, fwhm_1, amplitude_2]. Parameters ---------- cs : Crossspectrum A Crossspectrum object with the data to be fit model: astropy.modeling.models class instance The parametric model supposed to represent the data. For details see the astropy.modeling documentation starting_pars : iterable, optional, default None The list of starting guesses for the optimizer. If it is not provided, then default parameters are taken from `model`. See explanation above for ordering of parameters in this list. max_post : bool, optional, default False If True, perform a Maximum-A-Posteriori fit of the data rather than a Maximum Likelihood fit. Note that this requires priors to be specified, otherwise this will cause an exception! priors : {dict | None}, optional, default None Dictionary with priors for the MAP fit. This should be of the form {"parameter name": probability distribution, ...} fitmethod : string, optional, default "L-BFGS-B" Specifies an optimization algorithm to use. Supply any valid option for `scipy.optimize.minimize`. Returns ------- parest : PSDParEst object A PSDParEst object for further analysis res : OptimizationResults object The OptimizationResults object storing useful results and quantities relating to the fit """ if not (isinstance(starting_pars, np.ndarray) or isinstance(starting_pars, list)): starting_pars = model.parameters if priors: lgauss = GaussianPosterior(cs.freq, np.abs(cs.power), cs.power_err, model, priors) else: lgauss = GaussianLogLikelihood(cs.freq, np.abs(cs.power), model=model, yerr=cs.power_err) parest = PSDParEst(cs, fitmethod=fitmethod, max_post=max_post) res = parest.fit(lgauss, starting_pars, neg=True) return parest, res
def test_fit_fails_without_lpost_or_t0(self): pe = PSDParEst(self.ps) with pytest.raises(TypeError): res = pe.fit()
ps = Powerspectrum() ps.freq = freq ps.power = powers ps.df = ps.freq[1] - ps.freq[0] ps.m = 1 # Define the log-likelihood of the data given the model from stingray.modeling import PSDLogLikelihood loglike = PSDLogLikelihood(ps.freq, ps.power, observation_model, m=ps.m) loglike(true_parameters) # Parameter estimation from stingray.modeling import PSDParEst parest = PSDParEst(ps, fitmethod="L-BFGS-B", max_post=False) starting_pars = true_parameters res = parest.fit(loglike, starting_pars) print(true_parameters) print(res.p_opt) print(res.err) print("AIC: " + str(res.aic)) print("BIC: " + str(res.bic)) res.print_summary(loglike) plt.figure(figsize=(12, 8)) plt.loglog(ps.freq, psd_shape, label="true power spectrum", lw=3) plt.loglog(ps.freq, ps.power, label="simulated data") plt.loglog(ps.freq, res.mfit, label="best fit", lw=3) plt.legend() plt.show()
def test_fit_fails_with_incorrect_number_of_parameters(self): pe = PSDParEst(self.ps) t0 = [1,2] with pytest.raises(ValueError): res = pe.fit(self.lpost, t0)
def fit_powerspectrum(ps, model, starting_pars, max_post=False, priors=None, fitmethod="L-BFGS-B"): """ Fit a number of Lorentzians to a power spectrum, possibly including white noise. Each Lorentzian has three parameters (amplitude, centroid position, full-width at half maximum), plus one extra parameter if the white noise level should be fit as well. Priors for each parameter can be included in case `max_post = True`, in which case the function will attempt a Maximum-A-Posteriori fit. Priors must be specified as a dictionary with one entry for each parameter. The parameter names are `(amplitude_i, x_0_i, fwhm_i)` for each `i` out of a total of `N` Lorentzians. The white noise level has a parameter `amplitude_(N+1)`. For example, a model with two Lorentzians and a white noise level would have parameters: [amplitude_0, x_0_0, fwhm_0, amplitude_1, x_0_1, fwhm_1, amplitude_2]. Parameters ---------- ps : Powerspectrum A Powerspectrum object with the data to be fit model: astropy.modeling.models class instance The parametric model supposed to represent the data. For details see the astropy.modeling documentation starting_pars : iterable The list of starting guesses for the optimizer. See explanation above for ordering of parameters in this list. fit_whitenoise : bool, optional, default True If True, the code will attempt to fit a white noise level along with the Lorentzians. Be sure to include a starting parameter for the optimizer in `starting_pars`! max_post : bool, optional, default False If True, perform a Maximum-A-Posteriori fit of the data rather than a Maximum Likelihood fit. Note that this requires priors to be specified, otherwise this will cause an exception! priors : {dict | None}, optional, default None Dictionary with priors for the MAP fit. This should be of the form {"parameter name": probability distribution, ...} fitmethod : string, optional, default "L-BFGS-B" Specifies an optimization algorithm to use. Supply any valid option for `scipy.optimize.minimize`. Returns ------- parest : PSDParEst object A PSDParEst object for further analysis res : OptimizationResults object The OptimizationResults object storing useful results and quantities relating to the fit Example ------- We start by making an example power spectrum with three Lorentzians >>> m = 1 >>> nfreq = 100000 >>> freq = np.linspace(1, 1000, nfreq) >>> np.random.seed(100) # set the seed for the random number generator >>> noise = np.random.exponential(size=nfreq) >>> model = models.PowerLaw1D() + models.Const1D() >>> model.x_0_0.fixed = True >>> alpha_0 = 2.0 >>> amplitude_0 = 100.0 >>> amplitude_1 = 2.0 >>> model.alpha_0 = alpha_0 >>> model.amplitude_0 = amplitude_0 >>> model.amplitude_1 = amplitude_1 >>> p = model(freq) >>> power = noise * p >>> ps = Powerspectrum() >>> ps.freq = freq >>> ps.power = power >>> ps.m = m >>> ps.df = freq[1] - freq[0] >>> ps.norm = "leahy" Now we have to guess starting parameters. For each Lorentzian, we have amplitude, centroid position and fwhm, and this pattern repeats for each Lorentzian in the fit. The white noise level is the last parameter. >>> t0 = [80, 1.5, 2.5] Let's also make a model to test: >>> model_to_test = models.PowerLaw1D() + models.Const1D() >>> model_to_test.x_0_0.fixed = True We're ready for doing the fit: >>> parest, res = fit_powerspectrum(ps, model_to_test, t0) `res` contains a whole array of useful information about the fit, for example the parameters at the optimum: >>> p_opt = res.p_opt """ if priors: lpost = PSDPosterior(ps, model, priors=priors) else: lpost = PSDLogLikelihood(ps.freq, ps.power, model, m=ps.m) parest = PSDParEst(ps, fitmethod=fitmethod, max_post=max_post) res = parest.fit(lpost, starting_pars, neg=True) return parest, res
powers = psd_shape * np.random.chisquare(2, size=psd_shape.shape[0]) / 2.0 # Make the random data into a Powerspectrum object ps = Powerspectrum() ps.freq = freq ps.power = powers ps.df = ps.freq[1] - ps.freq[0] ps.m = 1 # Define the log-likelihood of the data given the model loglike = PSDLogLikelihood(ps.freq, ps.power, observation_model, m=ps.m) # Parameter estimation object parameter_estimate = PSDParEst(ps, fitmethod="L-BFGS-B", max_post=False) # Estimate the starting parameters - will be replaced with a function # starting_parameters = starting_parameter_selector(model_name) starting_pars = [ll_amplitude / 2.0, -1.0, ll_fwhm / 5.0] # Do the fit and store the results sp.store(i, j, parameter_estimate.fit(loglike, starting_pars)) # Save the results sp.save('/Users/Desktop/')