def _bundle_inputs(data, model): """Convert input into SimulFit instances. Convert the inputs into DataSimulFit and SimulFitModel instances. Parameters ---------- data : a Data or DataSimulFit instance The data set, or sets, to use. model : a Model or SimulFitModel instance The model expression, or expressions. If a SimulFitModel is given then it must match the number of data sets in the data parameter. Returns ------- data, model : DataSimulFit instance, SimulFitModel instance If the input was a SimulFit object then this is just the input value. """ if not isinstance(data, DataSimulFit): data = DataSimulFit('simulfit data', (data, )) if not isinstance(model, SimulFitModel): model = SimulFitModel('simulfit model', (model, )) return data, model
def _bundle_inputs(data, model): """Convert input into SimulFit instances. Convert the inputs into `sherpa.data.DataSimulFit` and `sherpa.models.model.SimulFitModel` instances. Parameters ---------- data : `sherpa.data.Data` or `sherpa.data.DataSimulFit` The data set, or sets, to use. model : `sherpa.models.model.Model` or `sherpa.models.model.SimulFitModel` The model expression, or expressions. If a `~sherpa.models.model.SimulFitModel` is given then it must match the number of data sets in the data parameter. Returns ------- data : `sherpa.data.DataSimulFit` If the input was a `~sherpa.data.DataSimulFit` object then this is just the input value. model : `sherpa.models.model.SimulFitModel` If the input was a `~sherpa.models.model.SimulFitModel` object then this is just the input value. """ if not isinstance(data, DataSimulFit): data = DataSimulFit('simulfit data', (data,)) if not isinstance(model, SimulFitModel): model = SimulFitModel('simulfit model', (model,)) return data, model
def mwl_fit_low_level(): """Use high-level Sherpa API. Low-level = no session, classes. Example: http://python4astronomers.github.io/fitting/low-level.html """ fermi_data = FermiData().sherpa_data hess_data = IACTData().sherpa_data # spec_model = PowLaw1D('spec_model') spec_model = LogParabola('spec_model') spec_model.c1 = 0.5 spec_model.c2 = 0.2 spec_model.ampl = 5e-11 data = DataSimulFit(name='global_data', datasets=[fermi_data, hess_data]) # TODO: Figure out how to notice using the low-level API # data.notice(mins=1e-3, maxes=None, axislist=None) model = SimulFitModel(name='global_model', parts=[spec_model, spec_model]) stat = FermiStat() method = LevMar() fit = Fit(data=data, model=model, stat=stat, method=method) result = fit.fit() # IPython.embed() return Bunch(results=result, model=spec_model)
def test_fitresults_multi(method): """Fit multiple datasets""" d1 = Data1D('dx', [1, 2, 3], [4, 2, 2]) d2 = Data1D('dx', [4, 5, 6, 10], [4, 4, 2, 4]) d = DataSimulFit('combined', (d1, d2)) m1 = Const1D() m1.c0 = 3 m = SimulFitModel('silly', (m1, m1)) fr = fit.Fit(d, m, method=method(), stat=LeastSq()).fit() fr.datasets = ['ddx', 'ddy'] r = fr._repr_html_() assert r is not None assert '<summary>Summary (9)</summary>' in r assert '<td>const1d.c0</td>' in r assert '<div class="dataname">Datasets</div><div class="dataval">ddx,ddy</div>' in r assert '<div class="dataname">Method</div><div class="dataval">{}</div>'.format(fr.methodname) in r assert '<div class="dataname">Statistic</div><div class="dataval">leastsq</div>' in r assert '<div class="dataname">Δ statistic</div><div class="dataval">0.142857</div>' in r assert '<div class="dataname">Number of data points</div><div class="dataval">7</div>' in r assert '<div class="dataname">Degrees of freedom</div><div class="dataval">6</div>' in r
def test_simul_stat_fit(stat, hide_logging, reset_xspec, setup_two): data1 = setup_two['data_pi2278'] data2 = setup_two['data_pi2286'] model1 = setup_two['model_pi2278'] model2 = setup_two['model_pi2286'] data = DataSimulFit(name='data1data2', datasets=[data1, data2]) model = SimulFitModel(name='model1model2', parts=[model1, model2]) fit = Fit(data=data, model=model, stat=stat(), method=NelderMead()) result = fit.fit() _fit_simul_datavarstat_results_bench = { 'succeeded': 1, 'numpoints': 18, 'dof': 15, 'istatval': 56609.70689926489, 'statval': 126.1509268988255, 'parvals': numpy.array( [0.8417576197443695, 1.6496933246579941, 0.2383939869443424]) } compare_results(_fit_simul_datavarstat_results_bench, result)
def test_same_cache(self): poly = Polynom1D() poly.pars[1].thaw() sdata = DataSimulFit('d1d2d3', (self.d1, self.d2, self.d3)) smodel = SimulFitModel('same', (poly, poly, poly)) sfit = Fit(sdata, smodel, method=NelderMead(), stat=Cash()) result = sfit.fit() self.compare_results(self._fit_same_poly_bench, result)
def fit(self): """Fit spectrum""" from sherpa.fit import Fit from sherpa.models import ArithmeticModel, SimulFitModel from sherpa.astro.instrument import Response1D from sherpa.data import DataSimulFit # Translate model to sherpa model if necessary if isinstance(self.model, models.SpectralModel): model = self.model.to_sherpa() else: model = self.model if not isinstance(model, ArithmeticModel): raise ValueError('Model not understood: {}'.format(model)) # Make model amplitude O(1e0) val = model.ampl.val * self.FLUX_FACTOR ** (-1) model.ampl = val if self.fit_range is not None: log.info('Restricting fit range to {}'.format(self.fit_range)) fitmin = self.fit_range[0].to('keV').value fitmax = self.fit_range[1].to('keV').value # Loop over observations pha = list() folded_model = list() nobs = len(self.obs_list) for ii in range(nobs): temp = self.obs_list[ii].to_sherpa() if self.fit_range is not None: temp.notice(fitmin, fitmax) if temp.get_background() is not None: temp.get_background().notice(fitmin, fitmax) temp.ignore_bad() if temp.get_background() is not None: temp.get_background().ignore_bad() pha.append(temp) # Forward folding resp = Response1D(pha[ii]) folded_model.append(resp(model) * self.FLUX_FACTOR) data = DataSimulFit('simul fit data', pha) fitmodel = SimulFitModel('simul fit model', folded_model) log.debug(fitmodel) fit = Fit(data, fitmodel, self.statistic) fitresult = fit.fit() log.debug(fitresult) # The model instance passed to the Fit now holds the best fit values covar = fit.est_errors() log.debug(covar) for ii in range(nobs): efilter = pha[ii].get_filter() shmodel = fitmodel.parts[ii] self.result[ii].fit = _sherpa_to_fitresult(shmodel, covar, efilter, fitresult)
def test_gauss_gauss(self): g1, g2 = Gauss1D(), Gauss1D() g1.fwhm = 1.3 g1.pos = 1.5 g2.fwhm = 4. g2.pos = -2.0 sdata = DataSimulFit('d4d5', (self.d4, self.d5)) smodel = SimulFitModel('g1g2', (g1, g2)) sfit = Fit(sdata, smodel, method=LevMar(), stat=LeastSq()) result = sfit.fit() self.compare_results(self._fit_g2g2_bench, result)
def test_diff_cache(self): poly1 = Polynom1D() poly2 = Polynom1D() poly3 = Polynom1D() poly1.pars[1].thaw() poly2.pars[1].thaw() poly3.pars[1].thaw() sdata = DataSimulFit('d123', (self.d1, self.d2, self.d3)) smodel = SimulFitModel('diff', (poly1, poly2, poly3)) sfit = Fit(sdata, smodel, method=NelderMead(), stat=Cash()) result = sfit.fit() self.compare_results(self._fit_diff_poly_bench, result)
def test_simul_stat_fit(self): data1 = self.data_pi2278 data2 = self.data_pi2286 model1 = self.model_mult model2 = self.model_mult data = DataSimulFit(name='data1data2', datasets=[data1, data2]) model = SimulFitModel(name='model1model2', parts=[model1, model2]) fit = Fit(data=data, model=model, stat=MyChiNoBkg(), method=NelderMead()) result = fit.fit() self.compare_results(self._fit_simul_datavarstat_results_bench, result)
def __init__(self, models, tie_list=None): self.model_dict = OrderedDict() try: models.parameters # does it quack self.sherpa_model = self._astropy_to_sherpa_model(models) self.model_dict[models] = self.sherpa_model except AttributeError: for mod in models: self.model_dict[mod] = self._astropy_to_sherpa_model(mod) if tie_list is not None: for par1, par2 in tie_list: getattr(self.model_dict[par1._model], par1.name).link = getattr(self.model_dict[par2._model], par2.name) self.sherpa_model = SimulFitModel("wrapped_fit_model", self.model_dict.values())
def test_errresults_multi(): d1 = Data1D('dx', [1, 2, 3], [4, 2, 2], [1.2, 0.9, 0.9]) d2 = Data1D('dx', [10, 11, 12, 13], [4, 4, 2, 4], [0.8, 1.1, 1.1, 0.9]) d = DataSimulFit('combined', (d1, d2)) m1 = Const1D() m1.c0 = 3 m = SimulFitModel('silly', (m1, m1)) f = fit.Fit(d, m, stat=Chi2()) er = f.est_errors() r = er._repr_html_() assert r is not None assert '<summary>covariance 1σ (68.2689%) bounds</summary>' in r assert '<summary>Summary (2)' in r assert '<td>const1d.c0</td>' in r assert '<div class="dataname">Fitting Method</div><div class="dataval">levmar</div>' in r assert '<div class="dataname">Statistic</div><div class="dataval">chi2</div>' in r assert '<tr><td>const1d.c0</td><td> 3</td><td> -0.362415</td><td> 0.362415</td></tr>' in r
def fit(self): """Fit spectrum""" from sherpa.fit import Fit from sherpa.models import ArithmeticModel, SimulFitModel from sherpa.astro.instrument import Response1D from sherpa.data import DataSimulFit # Reset results self._result = list() # Translate model to sherpa model if necessary if isinstance(self.model, models.SpectralModel): model = self.model.to_sherpa() else: model = self.model if not isinstance(model, ArithmeticModel): raise ValueError('Model not understood: {}'.format(model)) # Make model amplitude O(1e0) val = model.ampl.val * self.FLUX_FACTOR**(-1) model.ampl = val if self.fit_range is not None: log.info('Restricting fit range to {}'.format(self.fit_range)) fitmin = self.fit_range[0].to('keV').value fitmax = self.fit_range[1].to('keV').value # Loop over observations pha = list() folded_model = list() nobs = len(self.obs_list) for ii in range(nobs): temp = self.obs_list[ii].to_sherpa() if self.fit_range is not None: temp.notice(fitmin, fitmax) if temp.get_background() is not None: temp.get_background().notice(fitmin, fitmax) temp.ignore_bad() if temp.get_background() is not None: temp.get_background().ignore_bad() pha.append(temp) log.debug('Noticed channels obs {}: {}'.format( ii, temp.get_noticed_channels())) # Forward folding resp = Response1D(pha[ii]) folded_model.append(resp(model) * self.FLUX_FACTOR) if (len(pha) == 1 and len(pha[0].get_noticed_channels()) == 1): raise ValueError('You are trying to fit one observation in only ' 'one bin, error estimation will fail') data = DataSimulFit('simul fit data', pha) log.debug(data) fitmodel = SimulFitModel('simul fit model', folded_model) log.debug(fitmodel) fit = Fit(data, fitmodel, self.statistic) fitresult = fit.fit() log.debug(fitresult) # The model instance passed to the Fit now holds the best fit values covar = fit.est_errors() log.debug(covar) for ii in range(nobs): efilter = pha[ii].get_filter() # Skip observations not participating in the fit if efilter != '': shmodel = fitmodel.parts[ii] result = _sherpa_to_fitresult(shmodel, covar, efilter, fitresult) result.obs = self.obs_list[ii] else: result = None self._result.append(result) valid_result = np.nonzero(self.result)[0][0] global_result = copy.deepcopy(self.result[valid_result]) global_result.npred = None global_result.obs = None all_fitranges = [_.fit_range for _ in self._result if _ is not None] fit_range_min = min([_[0] for _ in all_fitranges]) fit_range_max = max([_[1] for _ in all_fitranges]) global_result.fit_range = u.Quantity((fit_range_min, fit_range_max)) self._global_result = global_result