def setUp(self): data = Data1D('fake', self._x, self._y, self._err) g1 = Gauss1D('g1') g1.fwhm.set(1.0, _tiny, _max, frozen=False) g1.pos.set(1.0, -_max, _max, frozen=False) g1.ampl.set(1.0, -_max, _max, frozen=False) p1 = PowLaw1D('p1') p1.gamma.set(1.0, -10, 10, frozen=False) p1.ampl.set(1.0, 0.0, _max, frozen=False) p1.ref.set(1.0, -_max, _max, frozen=True) model = p1 + g1 method = LevMar() method.config['maxfev'] = 10000 method.config['ftol'] = float(_eps) method.config['epsfcn'] = float(_eps) method.config['gtol'] = float(_eps) method.config['xtol'] = float(_eps) method.config['factor'] = float(100) self.fit = Fit(data, model, Chi2DataVar(), method, Covariance()) results = self.fit.fit() for key in ["succeeded", "numpoints", "nfev"]: assert self._fit_results_bench[key] == int(getattr(results, key)) for key in ["rstat", "qval", "statval", "dof"]: assert numpy.allclose(float(self._fit_results_bench[key]), float(getattr(results, key)), 1.e-7, 1.e-7) for key in ["parvals"]: try: assert numpy.allclose(self._fit_results_bench[key], getattr(results, key), 1.e-4, 1.e-4) except AssertionError: print 'parvals bench: ', self._fit_results_bench[key] print 'parvals fit: ', getattr(results, key) print 'results', results raise covresults = self.fit.est_errors() self.dof = results.dof self.mu = numpy.array(results.parvals) self.cov = numpy.array(covresults.extra_output) self.num = 10
def test_mychi_datahasbkg_modelhasnobkg(self): fit = Fit(self.data, self.model, MyChiNoBkg(), LevMar()) results = fit.fit() self.compare_results(self._fit_mychi_results_bench, results)
def test_mychi_nobkgdata_modelhasbkg(self): data = self.bkg fit = Fit(data, self.model, MyChiWithBkg(), LevMar()) results = fit.fit() self.compare_results(self._fit_mychinobkg_results_bench, results)
def test_mychi_data_and_model_have_bkg(self): fit = Fit(self.data, self.model, MyChiWithBkg(), LevMar()) results = fit.fit() self.compare_results(self._fit_mychi_results_bench, results)
def test_mychi_data_and_model_donothave_bkg(self): data = self.bkg fit = Fit(data, self.model, MyChiNoBkg(), LevMar()) results = fit.fit() self.compare_results(self._fit_mychinobkg_results_bench, results)
def multifit(star_name, data_list, model_list, silent=False): """A function that will fit 2 models to 2 spectra simultaneously. This was created to fit the NaI doublets at ~3300 and ~5890 Angstroms. :param star_name: Name of the target star :type star_name: str :param data_list: List of spectrum data in the form [(wave, flux), (wave, flux),...] :type data_list: tuple :param model_list: A list of unfit spectrum models :type model_list: list :param silent: If true, no plots will generate, defaults to False :type silent: bool :return: models that are fit to the data :rtype: list """ wave1, flux1 = data_list[0] wave2, flux2 = data_list[1] model1 = model_list[0] model2 = model_list[1] name_1 = star_name + " 1" name_2 = star_name + " 2" d1 = Data1D(name_1, wave1, flux1) d2 = Data1D(name_2, wave2, flux2) dall = DataSimulFit("combined", (d1, d2)) mall = SimulFitModel("combined", (model1, model2)) # # ========================================== # # Initial guesses # Dataset 1 dplot1 = DataPlot() dplot1.prepare(d1) if silent is False: dplot1.plot() mplot1 = ModelPlot() mplot1.prepare(d1, model1) if silent is False: dplot1.plot() mplot1.overplot() plt.show() # Dataset 2 dplot2 = DataPlot() dplot2.prepare(d2) if silent is False: dplot2.plot() mplot2 = ModelPlot() mplot2.prepare(d2, model2) if silent is False: dplot2.plot() mplot2.overplot() plt.show() # # ========================================= # # Fitting happens here - don't break please stat = LeastSq() opt = LevMar() opt.verbose = 0 opt.ftol = 1e-15 opt.xtol = 1e-15 opt.gtol = 1e-15 opt.epsfcn = 1e-15 print(opt) vfit = Fit(dall, mall, stat=stat, method=opt) print(vfit) vres = vfit.fit() print() print() print("Did the fit succeed? [bool]") print(vres.succeeded) print() print() print(vres.format()) # # ========================================= # # Plotting after fit if silent is False: # Dataset 1 fplot1 = FitPlot() mplot1.prepare(d1, model1) fplot1.prepare(dplot1, mplot1) fplot1.plot() # residual title = "Data 1" plt.title(title) plt.plot(wave1, flux1 - model1(wave1)) plt.show() # Dataset 2 fplot2 = FitPlot() mplot2.prepare(d2, model2) fplot2.prepare(dplot2, mplot2) fplot2.plot() # residual title = "Data 2" plt.title(title) plt.plot(wave2, flux2 - model2(wave2)) plt.show() # both datasets - no residuals splot = SplitPlot() splot.addplot(fplot1) splot.addplot(fplot2) plt.tight_layout() plt.show() return model_list
def fit(star_name, data, model, silent=False, breakdown=False): """A function that will fit a given multi-part model to a given spectrum. :param star_name: Name of the target star :type star_name: str :param data: Spectrum data in the form (wave, flux) :type data: tuple :param model: An unfit spectrum model :type model: object :param silent: If true, no plots will generate, defaults to False :type silent: bool :return: model that is fit to the data :rtype: object """ wave, flux = data # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% d = Data1D(star_name, wave, flux) # ========================================== # Initial guesses # Dataset 1 dplot = DataPlot() dplot.prepare(d) if silent is False: dplot.plot() mplot = ModelPlot() mplot.prepare(d, model) if silent is False: dplot.plot() mplot.overplot() plt.show() # ========================================= # Fitting happens here - don't break please start = time.time() stat = LeastSq() opt = LevMar() opt.verbose = 0 opt.ftol = 1e-15 opt.xtol = 1e-15 opt.gtol = 1e-15 opt.epsfcn = 1e-15 if silent is False: print(opt) vfit = Fit(d, model, stat=stat, method=opt) if silent is False: print(vfit) vres = vfit.fit() if silent is False: print() print() print(vres.format()) # ========================================= # Plotting after fit # Dataset 1 if silent is False: fplot = FitPlot() mplot.prepare(d, model) fplot.prepare(dplot, mplot) fplot.plot() # residual plt.title(star_name) plt.plot(wave, flux - model(wave)) # plt.xaxis(fontsize = ) plt.xlabel("Wavelength (AA)", fontsize=12) plt.ylabel("Flux", fontsize=12) plt.tick_params(axis="both", labelsize=12) if silent is False: duration = time.time() - start print() print("Time taken: " + str(duration)) print() plt.show() if breakdown is True: params = [] cont = model[0] if silent is False: plt.scatter(wave, flux, marker=".", c="black") plt.plot(wave, model(wave), c="C1") for line in model: if line.name[0] != "(": if line.name == "Cont_flux": if silent is False: print(line) plt.plot(wave, line(wave), linestyle="--") else: params.append(line) if silent is False: print() print(line) plt.plot(wave, line(wave) * cont(wave), linestyle="--") plt.show() return model, params return model
def test_chi2constvar_stat(self): fit = Fit(self.data, self.model, Chi2ConstVar(), LevMar()) results = fit.fit() self.compare_results(self._fit_chi2constvar_results_bench, results)
def test_leastsq_stat(self): fit = Fit(self.data, self.model, LeastSq(), LevMar()) results = fit.fit() self.compare_results(self._fit_leastsq_results_bench, results)
def call(self, niter, seed): pars = {} pars_index = {} index = 0 for par in self.model.pars: if par.frozen is False: name = '%s.%s' % (par.modelname, par.name) pars_index[index] = name pars[name] = [] index += 1 data = self.data y = data.y x = data.x if type(data) == Data1DAsymmetricErrs: y_l = y - data.elo y_h = y + data.ehi elif isinstance(data, (Data1D, )): y_l = data.staterror y_h = data.staterror else: msg = "{0} {1}".format(ReSampleData.__name__, type(data)) raise NotImplementedError(msg) numpy.random.seed(seed) for j in range(niter): ry = [] for i in range(len(y_l)): a = y_l[i] b = y_h[i] r = -1 while r < a or r > b: sigma = b - y[i] u = numpy.random.random_sample() if u < 0.5: sigma = y[i] - a r = numpy.random.normal(loc=y[i], scale=sigma, size=None) if u < 0.5 and r > y[i]: r = -1 if u > 0.5 and r < y[i]: r = -1 ry.append(r) ry = numpy.asarray(ry) # fit is performed for each simulated data point fit = Fit(Data1D('tmp', x, ry), self.model, LeastSq(), LevMar()) fit_result = fit.fit() for index, val in enumerate(fit_result.parvals): name = pars_index[index] pars[name].append(val) result = {} for index, name in pars_index.items(): avg = numpy.average(pars[name]) std = numpy.std(pars[name]) print(name, ': avg =', avg, ', std =', std) result[name] = pars[name] return result
def main(): config = read_config('config.yaml') # ref_cube = make_ref_cube(config) # target_position = SkyCoord(config['model']['ra1'], config['model']['dec1'], unit="deg").galactic cubes = load_cubes(config) print('which available cubes:', cubes) # converting data SkyCube to sherpa-format cube counts = cubes['counts'].to_sherpa_data3d() #dstype='Data3DInt') print('counts: ', counts) # Define a 2D gaussian for the spatial model # spatial_model = NormGauss2DInt('spatial-model') # Define a power law for the spectral model # spectral_model = PowLaw1D('spectral-model') coord = cubes['counts'].sky_image_ref.coordinates(mode="edges") energies = cubes['counts'].energies(mode='edges').to("TeV") print('my energy bins: ', energies) # import IPython; IPython.embed(); # Set up exposure table model exposure = TableModel('exposure') exposure.load(None, cubes['exposure'].data.ravel()) exposure.ampl.freeze() use_psf = config['model']['use_psf'] model_gammapy = get_model_gammapy(config) spectral_model_sherpa = model_gammapy.spectral_model.to_sherpa() spectral_model_sherpa.ampl.thaw() spatial_model_sherpa = model_gammapy.spatial_model.to_sherpa() spatial_model_sherpa.xpos.freeze() spatial_model_sherpa.ypos.freeze() spatial_model_sherpa.r0.freeze() spatial_model_sherpa.width.freeze() source_model = CombinedModel3D( spatial_model=spatial_model_sherpa, spectral_model=spectral_model_sherpa, ) # source_model = CombinedModel3DInt( # spatial_model=spatial_model_sherpa, # spectral_model=spectral_model_sherpa, # exposure=exposure, # coord=coord, # energies=energies, # use_psf=use_psf, # psf=None, # ) print(source_model) # source_model_cube = source_model.evaluate_cube(ref_cube) # model = source_model # + background_model # source_model2 = CombinedModel3DInt( # coord=coord, # energies=energies, # use_psf=False, # exposure=cubes['exposure'], # psf=None, # spatial_model=spatial_model, # spectral_model=spectral_model, # ) model = 1e-9 * exposure * source_model # 1e-9 flux factor fit = Fit( data=counts, model=model, stat=Chi2ConstVar(), method=LevMar(), # estmethod=Covariance(), ) fit_results = fit.fit() print(fit_results.format()) print('------------------------------------ end fitting')
def call(self, niter, seed=None): """Resample the data and fit the model to each iteration. .. versionadded:: 4.12.2 The samples and statistic keys were added to the return value, the parameter values are returned as NumPy arrays rather than as lists, and the seed parameter was made optional. Parameters ---------- niter : int The number of iterations. seed : int or None, optional The seed value. Returns ------- sampled : dict The keys are samples, which contains the resampled data used in the fits as a niter by ndata array, and the free parameters in the fit, containing a NumPy array containing the fit parameter for each iteration (of size niter). Notes ----- The fit for each iteration uses the input values of the model parameters as the starting point. The parameters of the model are not changed by this method. """ # Each fit is reset to this set of values as the starting point orig_pars = self.model.thawedpars pars = {} pars_index = [] for par in self.model.pars: if par.frozen: continue name = par.fullname pars_index.append(name) pars[name] = numpy.zeros(niter) data = self.data y = data.y x = data.x if type(data) == Data1DAsymmetricErrs: y_l = y - data.elo y_h = y + data.ehi elif isinstance(data, (Data1D, )): y_l = data.staterror y_h = data.staterror else: msg = "{0} {1}".format(ReSampleData.__name__, type(data)) raise NotImplementedError(msg) ny = len(y) fake_data = Data1D('tmp', x, numpy.zeros(ny)) numpy.random.seed(seed) ry_all = numpy.zeros((niter, ny), dtype=y_l.dtype) stats = numpy.zeros(niter) for j in range(niter): ry = ry_all[j] for i in range(ny): a = y_l[i] b = y_h[i] r = None while r is None: # Flip between low or hi # u = 0 pick low # u = 1 pick high # # Switching to randint rather than random_sample # leads to different answers, so the tests fail, # so leave as is. # # u = numpy.random.randint(low=0, high=2) # u = numpy.random.random_sample() u = 0 if u < 0.5 else 1 # Rather than dropping this value, we could # reflect it (ie multiply it by -1 if the sign # is wrong). Would this affect the statistical # properties? # dr = numpy.random.normal(loc=0, scale=1, size=None) if u == 0: if dr > 0: continue sigma = y[i] - a else: if dr < 0: continue sigma = b - y[i] r = y[i] + dr * sigma ry[i] = r # fit is performed for each simulated data point, and we # always start at the original best-fit location to # start the fit (by making sure we always reset after a fit). # fake_data.y = ry fit = Fit(fake_data, self.model, LeastSq(), LevMar()) try: fit_result = fit.fit() finally: self.model.thawedpars = orig_pars stats[j] = fit_result.statval for name, val in zip(fit_result.parnames, fit_result.parvals): pars[name][j] = val result = {'samples': ry_all, 'statistic': stats} for name in pars_index: avg = numpy.average(pars[name]) std = numpy.std(pars[name]) info('{} : avg = {} , std = {}'.format(name, avg, std)) result[name] = pars[name] return result
def fit_asymmetric_err(bench, data): model = PowLaw1D('p1') fit = Fit(data, model, Chi2Gehrels(), LevMar()) results = fit.fit() compare(bench, results) return model
def test_wstat(self): fit = Fit(self.data, self.model, WStat(), LevMar()) results = fit.fit() self.compare_results(self._fit_wstat_results_bench, results)