from astropy import units as u from sherpa.models import ArithmeticModel from sherpa.data import BaseData, Data from sherpa.stats import Likelihood from sherpa.optmethods import LevMar, NelderMead, MonCar, GridSearch __all__ = [ 'SherpaDataWrapper', 'SherpaModelWrapper', 'SherpaStatWrapper', ] SHERPA_OPTMETHODS = OrderedDict() SHERPA_OPTMETHODS['levmar'] = LevMar() SHERPA_OPTMETHODS['simplex'] = NelderMead() SHERPA_OPTMETHODS['moncar'] = MonCar() SHERPA_OPTMETHODS['gridsearch'] = GridSearch() class SherpaDataWrapper(Data): def __init__(self, gp_data, name='GPData'): # sherpa does some magic here: it sets class attributes from constructor # arguments so `gp_data` will be available later on the instance. self._data_dummy = np.empty_like(gp_data.e_ref) BaseData.__init__(self) def to_fit(self, staterr): return self._data_dummy, None, None def eval_model_to_fit(self, model): return self._data_dummy
G1.fwhm = .05 G1.pos = 1083.03 + ref_value * 5 mdl = G1 mplot = ModelPlot() mplot.prepare(d, mdl) dplot = DataPlot() dplot.prepare(d) mplot.overplot() #set error methods, ChiSq() or LeastSq() #Chi square is a way to compare which profile best describes data, ie: is it more gaussian or lorentzian #Least Square says how good the data fits the particular model instance #opt - optimizers improve the fit. Monte Carlo is what I used, it is slow but it is most robust. Many options on sherpas site ustat = LeastSq() opt = MonCar() #LevMar() #NelderMead() # #apply actual Fit f = Fit(d, mdl, stat=ustat, method=opt) res = f.fit() fplot = FitPlot() mplot.prepare(d, mdl) fplot.prepare(dplot, mplot) fplot.plot() #param_errors = f.est_errors() #plotting routine plt.plot(d.x, d.y, "c.", label="Data") plt.plot(d.x, mdl(d.x), linewidth=2, label="Gaussian") plt.legend(loc=2)
def prepare_spectra(nH: float, group: int = 1, add_gal: bool = False, redshift: Optional[float] = None, **kwargs) -> float: """ Fit the spectra using an absorbed powerlaw model using the Wstat statistic. The function also returns a p-value for the gof. :param nH: The galactic absorption column density in units of 10^22 /cm3 :param group: The number of counts per energy bin :param add_gal: Setting this to True would add an intrinsic abrosption column density along side the galactic one :param redshift: The redshift to use in the fit. Only takes effect if add_gal is set to True ... :return: Returns the p-value of the gof. The null hypothesis states that the model and the observation differ while alternate says that the model explains the data """ pha = read_pha("core_spectrum.pi") pha.set_analysis("energy") pha.notice(0.5, 7.0) tabs = ~pha.mask pha.group_counts(group, tabStops=tabs) x = pha.get_x() x = pha.apply_filter(x, pha._middle) y = pha.get_y(filter=True) pha.set_analysis("energy") model = xsphabs.abs1 * powlaw1d.srcp1 print("Fitting the spectrum") zFlag = False if (nH is not None) and (nH > 0.0): if add_gal == 1: model = xsphabs.gal * xszphabs.abs1 * powlaw1d.srcp gal.nH = nH freeze(gal.nH) zFlag = True else: model = xsphabs.abs1 * powlaw1d.srcp1 abs1.nH = nH freeze(abs1.nH) else: model = xszphabs.abs1 * powlaw1d.srcp1 zFlag = True if zFlag is True and add_gal == 1: # print('REDSHIFT',redshift) abs1.redshift = redshift freeze(abs1.redshift) full_model = RSPModelPHA(pha.get_arf(), pha.get_rmf(), pha, pha.exposure * model) print(full_model) fit = Fit(pha, full_model, method=MonCar(), stat=WStat()) res = fit.fit() print(res.format()) print(fit.est_errors()) # calculate the p-value for wstat mplot2 = ModelPlot() mplot2.prepare(pha, full_model) miu = mplot2.y * pha.exposure * 0.0146 obs = y * pha.exposure * 0.0146 c, ce, cv = SpecUtils.estimate_gof_cstat(miu, obs) #print(f"C0={c},C_e={ce},C_v={cv}") zval = (fit.calc_stat() - ce) / np.sqrt(cv) if zval > 0: pval = special.erfc(zval / np.sqrt(2)) else: pval = special.erf(abs(zval) / np.sqrt(2)) print(f"p-value for wstat = {pval}") set_data(pha) set_model(model) save_chart_spectrum("core_flux_chart.dat", elow=0.5, ehigh=7.0) # save_chart_spectrum("core_flux_chart.rdb",format='text/tsv', elow=0.5, ehigh=7.0) SAOTraceUtils.save_spectrum_rdb("core_flux_chart.dat") return pval
def prepare_spectra(group, nH, add_gal, redshift): pha = read_pha("core_spectrum.pi") pha.set_analysis("energy") pha.notice(0.5, 7.0) tabs = ~pha.mask pha.group_counts(group, tabStops=tabs) x = pha.get_x() x = pha.apply_filter(x, pha._middle) y = pha.get_y(filter=True) pha.set_analysis("energy") model = xsphabs.abs1 * powlaw1d.srcp1 print("Fitting the spectrum") zFlag = False if (nH is not None) and (nH > 0.0): if add_gal == 1: model = xsphabs.gal * xszphabs.abs1 * powlaw1d.srcp gal.nH = nH freeze(gal.nH) zFlag = True else: model = xsphabs.abs1 * powlaw1d.srcp1 abs1.nH = nH freeze(abs1.nH) else: model = xszphabs.abs1 * powlaw1d.srcp1 zFlag = True if zFlag is True and add_gal == 1: # print('REDSHIFT',redshift) abs1.redshift = redshift freeze(abs1.redshift) full_model = RSPModelPHA(pha.get_arf(), pha.get_rmf(), pha, pha.exposure * model) print(full_model) fit = Fit(pha, full_model, method=MonCar(), stat=WStat()) res = fit.fit() print(res.format()) print(fit.est_errors()) # calculate the p-value for wstat mplot2 = ModelPlot() mplot2.prepare(pha, full_model) miu = mplot2.y * pha.exposure * 0.0146 obs = y * pha.exposure * 0.0146 c, ce, cv = gof_cstat(miu, obs) print(f"C0={c},C_e={ce},C_v={cv}") zval = (fit.calc_stat() - ce) / np.sqrt(cv) if zval > 0: pval = special.erfc(zval / np.sqrt(2)) else: pval = special.erf(abs(zval) / np.sqrt(2)) print(f"p-value for wstat = {pval}") set_data(pha) set_model(model) save_chart_spectrum("core_flux_chart.dat", elow=0.5, ehigh=7.0) # save_chart_spectrum("core_flux_chart.rdb",format='text/tsv', elow=0.5, ehigh=7.0) save_spectrum_rdb("core_flux_chart.dat")
# Requires sherpa 4.9 import numpy as np from astropy import units as u from sherpa.models import ArithmeticModel, Parameter from sherpa.data import DataND, BaseData, Data from sherpa.stats import Likelihood from sherpa.optmethods import LevMar, NelderMead, MonCar, GridSearch __all__ = ['SherpaDataWrapper', 'SherpaModelWrapper', 'SherpaStatWrapper'] SHERPA_OPTMETHODS = { 'simplex': NelderMead(), 'moncar': MonCar(), 'gridsearch': GridSearch() } class SherpaDataWrapper(Data): def __init__(self, gp_data, name='GPData'): # sherpa does some magic here: it sets class attributes from constructor # arguments so `gp-data` will be available later on the instance. self._data_dummy = np.empty_like(gp_data.e_ref) BaseData.__init__(self) def to_fit(self, staterr): return self._data_dummy, None, None def eval_model_to_fit(self, model): return self._data_dummy