def fit(self): dummy_data = np.zeros(1) dummy_times = np.arange(1) ui.load_arrays(1, dummy_times, dummy_data) ui.set_method(self.method) ui.get_method().config.update(sherpa_configs.get(self.method, {})) ui.load_user_model(CalcModel(self.model), 'xijamod') # sets global xijamod ui.add_user_pars('xijamod', self.model.parnames) ui.set_model(1, 'xijamod') calc_stat = CalcStat(self.model, self.child_pipe, self.maxiter) ui.load_user_stat('xijastat', calc_stat, lambda x: np.ones_like(x)) ui.set_stat(xijastat) # Set frozen, min, and max attributes for each xijamod parameter for par in self.model.pars: xijamod_par = getattr(xijamod, par.full_name) xijamod_par.val = par.val xijamod_par.frozen = par.frozen xijamod_par.min = par.min xijamod_par.max = par.max if any(not par.frozen for par in self.model.pars): try: ui.fit(1) calc_stat.message['status'] = 'finished' fit_logger.info('Fit finished normally') except FitTerminated as err: calc_stat.message['status'] = 'terminated' fit_logger.warning('Got FitTerminated exception {}'.format(err)) self.child_pipe.send(calc_stat.message)
def test_est_errors_works_single_parameter(mdlcls, method, getter, clean_ui): """This is issue #1397. Rather than require XSPEC, we create a subclass of the Parameter class to check it works. We are not too concerned with the actual results hence the relatively low tolerance on the numeric checks. """ mdl = mdlcls() ui.load_arrays(1, [1, 2, 3, 4], [4, 2, 1, 3.5]) ui.set_source(mdl) with SherpaVerbosity("ERROR"): ui.fit() # this is where #1397 fails with Const2 method(mdl.con) atol = 1e-4 assert ui.calc_stat() == pytest.approx(0.7651548418626658, abs=atol) results = getter() assert results.parnames == (f"{mdl.name}.con", ) assert results.sigma == pytest.approx(1.0) assert results.parvals == pytest.approx((2.324060647544594, ), abs=atol) # The covar errors are -/+ 1.3704388763054511 # conf -1.3704388763054511 / +1.3704388763054514 # proj -1.3704388762971822 / +1.3704388763135826 # err = 1.3704388763054511 assert results.parmins == pytest.approx((-err, ), abs=atol) assert results.parmaxes == pytest.approx((err, ), abs=atol)
def fit(self, method='simplex'): """Initiate a fit of the model using Sherpa. :param method: Method to be used to fit the model (e.g. simplex, levmar, or moncar) """ dummy_data = np.zeros(1) dummy_times = np.arange(1) ui.load_arrays(1, dummy_times, dummy_data) ui.set_method(method) ui.get_method().config.update(sherpa_configs.get(method, {})) ui.load_user_model(CalcModel(self.model, self.fit_logger), 'xijamod') # sets global xijamod ui.add_user_pars('xijamod', self.model.parnames) ui.set_model(1, 'xijamod') calc_stat = CalcStat(self.model, self.fit_logger) ui.load_user_stat('xijastat', calc_stat, lambda x: np.ones_like(x)) ui.set_stat(xijastat) # Set frozen, min, and max attributes for each xijamod parameter for par in self.model.pars: xijamod_par = getattr(xijamod, par.full_name) xijamod_par.val = par.val xijamod_par.frozen = par.frozen xijamod_par.min = par.min xijamod_par.max = par.max ui.fit(1) self.save_snapshot(fit_stat=calc_stat.min_fit_stat, method=method)
def test_proton_model(): """ test import """ from ..sherpa_models import PionDecay model = PionDecay() model.ampl = 1e36 model.index = 2.1 # point calc output = model.calc([p.val for p in model.pars], energies) # integrated output = model.calc([p.val for p in model.pars], elo, xhi=ehi) # test as well ECPL model.cutoff = 1000 # Perform a fit to fake data ui.load_arrays(1, energies, test_spec_points, test_err_points) ui.set_model(model) ui.guess() # Actual fit is too slow for tests # ui.fit() # test with integrated data ui.load_arrays(1, elo, ehi, test_spec_int, test_err_int, ui.Data1DInt) ui.set_model(model) ui.guess()
def fit_pix_values(t_ccd, esec, id=1): logger = logging.getLogger("sherpa") logger.setLevel(logging.WARN) data_id = id ui.clean() ui.set_method('simplex') ui.load_user_model(dark_scale_model, 'model') ui.add_user_pars('model', ['scale', 'dark_t_ref']) ui.set_model(data_id, 'model') ui.load_arrays( data_id, np.array(t_ccd), np.array(esec), ) ui.set_staterror(data_id, 30 * np.ones(len(t_ccd))) model.scale.val = 0.588 model.scale.min = 0.3 model.scale.max = 1.0 model.dark_t_ref.val = 500 ui.freeze(model.scale) # If more than 5 degrees in the temperature range, # thaw and fit for model.scale. Else just use/return # the fit of dark_t_ref if np.max(t_ccd) - np.min(t_ccd) > 2: # Fit first for dark_t_ref ui.fit(data_id) ui.thaw(model.scale) ui.fit(data_id) return ui.get_fit_results(), ui.get_model(data_id)
def fit(self): dummy_data = np.zeros(1) dummy_times = np.arange(1) ui.load_arrays(1, dummy_times, dummy_data) ui.set_method(self.method) ui.get_method().config.update(sherpa_configs.get(self.method, {})) ui.load_user_model(CalcModel(self.model), 'xijamod') # sets global xijamod ui.add_user_pars('xijamod', self.model.parnames) ui.set_model(1, 'xijamod') calc_stat = CalcStat(self.model, self.child_pipe) ui.load_user_stat('xijastat', calc_stat, lambda x: np.ones_like(x)) ui.set_stat(xijastat) # Set frozen, min, and max attributes for each xijamod parameter for par in self.model.pars: xijamod_par = getattr(xijamod, par.full_name) xijamod_par.val = par.val xijamod_par.frozen = par.frozen xijamod_par.min = par.min xijamod_par.max = par.max if any(not par.frozen for par in self.model.pars): try: ui.fit(1) calc_stat.message['status'] = 'finished' logging.debug('Fit finished normally') except FitTerminated as err: calc_stat.message['status'] = 'terminated' logging.debug('Got FitTerminated exception {}'.format(err)) self.child_pipe.send(calc_stat.message)
def test_show_conf_basic(clean_ui): """Set up a very basic data/model/fit""" ui.load_arrays(1, [1, 2, 4], [3, 5, 5]) ui.set_source(ui.scale1d.mdl) ui.fit() ui.conf() out = StringIO() ui.show_conf(outfile=out) got = out.getvalue().split('\n') assert len(got) == 12 assert got[0] == "Confidence:Dataset = 1" assert got[1] == "Confidence Method = confidence" assert got[2] == "Iterative Fit Method = None" assert got[3] == "Fitting Method = levmar" assert got[4] == "Statistic = chi2gehrels" assert got[5] == "confidence 1-sigma (68.2689%) bounds:" assert got[6] == " Param Best-Fit Lower Bound Upper Bound" assert got[7] == " ----- -------- ----------- -----------" assert got[8] == " mdl.c0 4.19798 -1.85955 1.85955" assert got[9] == "" assert got[10] == "" assert got[11] == ""
def test_show_all_basic(clean_ui): """Set up a very basic data/model/fit""" ui.load_arrays(1, [1, 2, 4], [3, 5, 5]) ui.set_source(ui.scale1d.mdl) ui.fit() ui.conf() ui.proj() ui.covar() def get(value): out = StringIO() getattr(ui, f"show_{value}")(outfile=out) ans = out.getvalue() assert len(ans) > 1 # trim the trailing "\n" return ans[:-1] # All we are really checking is that the show_all output is the # comppsite of the following. We are not checking that the # actual output makes sense for any command. # expected = get("data") + get("model") + get("fit") + get("conf") + \ get("proj") + get("covar") got = get("all") assert expected == got
def test_set_dep_scalar(clean_ui): """What happens if set_dep is called with a scalar?""" x = np.arange(10, 30, 5) ones = np.ones(4) ui.load_arrays(1, x, ones) ui.set_dep(3) assert ui.get_dep() == pytest.approx(3 * ones)
def test_set_dep_array(clean_ui): """What happens if set_dep is called with an array?""" x = np.arange(10, 30, 5) ones = np.ones(4) ui.load_arrays(1, x, ones) ui.set_dep([2, 4, 5, 19]) assert ui.get_dep() == pytest.approx([2, 4, 5, 19])
def test_set_dep_array_wrong(clean_ui): """What happens if set_dep is called with an array with the wrong length?""" x = np.arange(10, 30, 5) ones = np.ones(4) ui.load_arrays(1, x, ones) # this does not error out ui.set_dep([2, 4, 5]) assert ui.get_dep() == pytest.approx([2, 4, 5])
def test_set_dep_none(clean_ui): """What happens if set_dep is called with None?""" x = np.arange(10, 30, 5) y = np.ones(4) ui.load_arrays(1, x, y) ui.set_dep(None) # We get [nan, nan, nan, nan] assert np.isnan(ui.get_dep()) == pytest.approx([1, 1, 1, 1])
def test_err_estimate_errors_on_frozen(method, clean_ui): """Check we error out with frozen par with conf/proj/covar. """ ui.load_arrays(1, [1, 2, 3], [1, 2, 3]) ui.set_source(ui.polynom1d.mdl) with pytest.raises(ParameterErr) as exc: method(mdl.c0, mdl.c1) assert str(exc.value) == "parameter 'mdl.c1' is frozen"
def setUp(clean_ui, hide_logging): x = [-13, -5, -3, 2, 7, 12] y = [102.3, 16.7, -0.6, -6.7, -9.9, 33.2] dy = np.ones(6) * 5 ui.load_arrays(1, x, y, dy) ui.set_source(ui.polynom1d.poly) poly.c1.thaw() poly.c2.thaw() ui.int_proj(poly.c0) ui.fit()
def test_set_filter_unmasked(clean_ui): """What happens when we call set_filter to an unfiltered dataset?""" x = np.asarray([10, 20, 30]) y = np.asarray([2, 3, 4]) ui.load_arrays(1, x, y) data = ui.get_data() assert data.mask ui.set_filter(np.asarray([True, False, True])) assert data.mask == pytest.approx([True, False, True])
def test_set_filter_masked_wrong(clean_ui): """What happens when we call set_filter to a filtered dataset with the wrong size?""" x = np.asarray([10, 20, 30]) y = np.asarray([2, 3, 4]) ui.load_arrays(1, x, y) ui.ignore(lo=15, hi=45) with pytest.raises(DataErr) as err: ui.set_filter(np.asarray([True, False])) assert str(err.value) == "size mismatch between 3 and 2"
def test_set_error_array_wrong(field, clean_ui): """What happens when we set the stat/syserror to an array of the wrong length?""" y = np.asarray([2, 3, 4]) ui.load_arrays(1, np.arange(3), y) ui.set_stat('cstat') setfunc = getattr(ui, f"set_{field}") # this does not error out setfunc(np.asarray([1, 2, 3, 4])) getfunc = getattr(ui, f"get_{field}") assert getfunc() == pytest.approx([1, 2, 3, 4])
def test_guess_warns_no_guess_names_model(caplog, clean_ui): """Do we warn when the named model has no guess""" ui.load_arrays(1, [1, 2, 3], [-3, 4, 5]) cpt = DummyModel('dummy') assert len(caplog.records) == 0 ui.guess(cpt) assert len(caplog.records) == 1 lname, lvl, msg = caplog.record_tuples[0] assert lname == "sherpa.ui.utils" assert lvl == logging.INFO assert msg == "WARNING: No guess found for dummy"
def test_err_estimate_errors_model_all_frozen(method, clean_ui): """Check we error out with frozen model with conf/proj/covar. """ ui.load_arrays(1, [1, 2, 3], [1, 2, 3]) ui.set_source(ui.polynom1d.mdl) for par in mdl.pars: par.freeze() with pytest.raises(ParameterErr) as exc: method(mdl) assert str(exc.value) == "Model 'polynom1d.mdl' has no thawed parameters"
def tst_ui(self, thaw_c1): ui.load_arrays(1, self._x, self._y, self._e) ui.set_source(1, ui.polynom1d.mdl) if thaw_c1: ui.thaw(mdl.c1) ui.thaw(mdl.c2) mdl.c2 = 1 ui.fit() if not thaw_c1: ui.thaw(mdl.c1) ui.fit() ui.conf() result = ui.get_conf_results() self.cmp_results(result)
def test_user_model1d_fit(): """Check can use in a fit.""" mname = "test_model" ui.load_user_model(um_line, mname) ui.add_user_pars(mname, ["slope", "intercept"], parvals = [1.0, 1.0]) mdl = ui.get_model_component(mname) x = numpy.asarray([-2.4, 2.3, 5.4, 8.7, 12.3]) # Set up the data to be scattered around y = -0.2 x + 2.8 # Pick the deltas so that they sum to 0 (except for central # point) # slope = -0.2 intercept = 2.8 dy = numpy.asarray([0.1, -0.2, 0.14, -0.1, 0.2]) ydata = x * slope + intercept + dy ui.load_arrays(1, x, ydata) ui.set_source(mname) ui.ignore(5.0, 6.0) # drop the central bin ui.set_stat('leastsq') ui.set_method('simplex') ui.fit() fres = ui.get_fit_results() assert fres.succeeded assert fres.parnames == ('test_model.slope', 'test_model.intercept') assert fres.numpoints == 4 assert fres.dof == 2 # Tolerance has been adjusted to get the tests to pass on my # machine. It's really just to check that the values have chanegd # from their default values. # assert fres.parvals[0] == pytest.approx(slope, abs=0.01) assert fres.parvals[1] == pytest.approx(intercept, abs=0.05) # Thse should be the same values, so no need to use pytest.approx # (unless there's some internal translation between types done # somewhere?). # assert mdl.slope.val == fres.parvals[0] assert mdl.intercept.val == fres.parvals[1]
def test_set_filter_masked(clean_ui): """What happens when we call set_filter to a filtered dataset?""" x = np.asarray([10, 20, 30, 40, 50]) y = np.asarray([2, 3, 4, 5, 6]) ui.load_arrays(1, x, y) ui.ignore(lo=15, hi=45) data = ui.get_data() assert data.mask == pytest.approx([True, False, False, False, True]) ui.set_filter(np.asarray([True, False, True, False, False])) assert data.mask == pytest.approx([True, False, True, False, True])
def test_guess_warns_no_guess_no_argument(caplog, clean_ui): """Do we warn when the (implied) model has no guess""" ui.load_arrays(1, [1, 2, 3], [-3, 4, 5]) cpt = DummyModel('dummy') ui.set_source(cpt + cpt) assert len(caplog.records) == 0 ui.guess() assert len(caplog.records) == 1 lname, lvl, msg = caplog.record_tuples[0] assert lname == "sherpa.ui.utils" assert lvl == logging.INFO assert msg == "WARNING: No guess found for (dummy + dummy)"
def test_set_syserror_array(clean_ui): """What happens when we set the syserror to an array?""" staterror = 0.1 * np.ones(3) syserror = 0.5 * np.ones(3) combo = np.sqrt(0.01 + 0.25) * np.ones(3) y = np.asarray([2, 3, 4]) ui.load_arrays(1, np.arange(3), y, staterror, None) ui.set_stat('cstat') ui.set_syserror(syserror) assert ui.get_staterror() == pytest.approx(staterror) assert ui.get_syserror() == pytest.approx(syserror) assert ui.get_error() == pytest.approx(combo)
def _fit_poly(fit_data, evt_times, degree, data_id=0): """ Given event data transformed into Y or Z angle positions, and a degree of the desired fit polynomial, fit a polynomial to the data. :param fit_data: event y or z angle position data :param evt_times: times of event/fit_data :param degree: degree of polynomial to use for the fit model :param data_id: sherpa dataset id to use for the fit :returns: (sherpa model plot, sherpa model) """ # Set initial value for fit data position error init_error = 1 ui.clean() ui.load_arrays(data_id, evt_times - evt_times[0], fit_data, np.zeros_like(fit_data) + init_error) v2("Fitting a line to the data to get reduced stat errors") # First just fit a line to get reduced errors on this set ui.polynom1d.line ui.set_model(data_id, 'line') ui.thaw('line.c1') ui.fit(data_id) fit = ui.get_fit_results() calc_error = init_error * np.sqrt(fit.rstat) ui.set_staterror(data_id, calc_error) # Then fit the specified model v2("Fitting a polynomial of degree {} to the data".format(degree)) ui.polynom1d.fitpoly ui.freeze('fitpoly') # Thaw the coefficients requested by the degree of the desired polynomial ui.thaw('fitpoly.c0') fitpoly.c0.val = 0 for deg in range(1, 1 + degree): ui.thaw("fitpoly.c{}".format(deg)) ui.set_model(data_id, 'fitpoly') ui.fit(data_id) # Let's screw up Y on purpose if data_id == 0: fitpoly.c0.val = 0 fitpoly.c1.val = 7.5e-05 fitpoly.c2.val = -1.0e-09 fitpoly.c3.val = 0 fitpoly.c4.val = 0 mp = ui.get_model_plot(data_id) model = ui.get_model(data_id) return mp, model
def test_set_syserror_scalar_no_fractional(clean_ui): """What happens when we set the syserror to a scalar fractional=False?""" staterror = 0.1 * np.ones(3) syserror = 0.5 * np.ones(3) combo = np.sqrt(0.01 + 0.25) * np.ones(3) ui.load_arrays(1, np.arange(3), np.ones(3), staterror, syserror) ui.set_stat('cstat') ui.set_syserror(3) assert ui.get_staterror() == pytest.approx(staterror) assert ui.get_syserror() == pytest.approx(3 * np.ones(3)) combo = np.sqrt(0.01 + 9) * np.ones(3) assert ui.get_error() == pytest.approx(combo)
def setUp(self): # defensive programming (one of the tests has been seen to fail # when the whole test suite is run without this) ui.clean() self._old_logger_level = logger.getEffectiveLevel() logger.setLevel(logging.ERROR) x = [-13, -5, -3, 2, 7, 12] y = [102.3, 16.7, -0.6, -6.7, -9.9, 33.2] dy = np.ones(6) * 5 ui.load_arrays(1, x, y, dy) ui.set_source(ui.polynom1d.poly) poly.c1.thaw() poly.c2.thaw() ui.int_proj(poly.c0) ui.fit()
def ccd_bias(bias): """ Calculate the mean and width of a gaussian fit to the bias histogram. `bias` is a numpy array. """ import sherpa.ui as ui from numpy import histogram, arange values, bins = histogram(bias, bins=arange(bias.min(),bias.max()+1)) ui.load_arrays(1, bins[:-1],values) ui.set_model(ui.gauss1d.g1) g1.pos = bias.mean() g1.fwhm = bias.std() ui.fit() return g1
def test_set_syserror_scalar_fractional(clean_ui): """What happens when we set the syserror to a scalar fractional=True?""" staterror = 0.1 * np.ones(3) syserror = 0.5 * np.ones(3) combo = np.sqrt(0.01 + 0.25) * np.ones(3) y = np.asarray([2, 3, 4]) ui.load_arrays(1, np.arange(3), y, staterror, syserror) ui.set_stat('cstat') ui.set_syserror(0.4, fractional=True) assert ui.get_staterror() == pytest.approx(staterror) assert ui.get_syserror() == pytest.approx(0.4 * y) combo = np.sqrt(0.01 + 0.16 * y * y) assert ui.get_error() == pytest.approx(combo)
def fit_model( model, comm=None, method='simplex', config=None, nofit=None, freeze_pars=freeze_pars, thaw_pars=[], ): dummy_data = np.zeros(1) dummy_times = np.arange(1) ui.load_arrays(1, dummy_times, dummy_data) ui.set_method(method) ui.get_method().config.update(config or sherpa_configs.get(method, {})) ui.load_user_model(CalcModel(model, comm), 'xijamod') ui.add_user_pars('xijamod', model.parnames) ui.set_model(1, 'xijamod') fit_parnames = set() for parname, parval in zip(model.parnames, model.parvals): getattr(xijamod, parname).val = parval fit_parnames.add(parname) if any([re.match(x + '$', parname) for x in freeze_pars]): fit_logger.info('Freezing ' + parname) ui.freeze(getattr(xijamod, parname)) fit_parnames.remove(parname) if any([re.match(x + '$', parname) for x in thaw_pars]): fit_logger.info('Thawing ' + parname) ui.thaw(getattr(xijamod, parname)) fit_parnames.add(parname) if 'tau' in parname: getattr(xijamod, parname).min = 0.1 calc_stat = CalcStat(model, comm) ui.load_user_stat('xijastat', calc_stat, lambda x: np.ones_like(x)) ui.set_stat(xijastat) if fit_parnames and not nofit: ui.fit(1) else: model.calc()
def fit_model(model, comm=None, method='simplex', config=None, nofit=None, freeze_pars=freeze_pars, thaw_pars=[], ): dummy_data = np.zeros(1) dummy_times = np.arange(1) ui.load_arrays(1, dummy_times, dummy_data) ui.set_method(method) ui.get_method().config.update(config or sherpa_configs.get(method, {})) ui.load_user_model(CalcModel(model, comm), 'xijamod') ui.add_user_pars('xijamod', model.parnames) ui.set_model(1, 'xijamod') fit_parnames = set() for parname, parval in zip(model.parnames, model.parvals): getattr(xijamod, parname).val = parval fit_parnames.add(parname) if any([re.match(x + '$', parname) for x in freeze_pars]): fit_logger.info('Freezing ' + parname) ui.freeze(getattr(xijamod, parname)) fit_parnames.remove(parname) if any([re.match(x + '$', parname) for x in thaw_pars]): fit_logger.info('Thawing ' + parname) ui.thaw(getattr(xijamod, parname)) fit_parnames.add(parname) if 'tau' in parname: getattr(xijamod, parname).min = 0.1 calc_stat = CalcStat(model, comm) ui.load_user_stat('xijastat', calc_stat, lambda x: np.ones_like(x)) ui.set_stat(xijastat) if fit_parnames and not nofit: ui.fit(1) else: model.calc()
def test_set_syserror_none(clean_ui): """What happens when we set the syserror to None?""" staterror = 0.1 * np.ones(3) syserror = 0.5 * np.ones(3) combo = np.sqrt(0.01 + 0.25) * np.ones(3) ui.load_arrays(1, np.arange(3), np.ones(3), staterror, syserror) ui.set_stat('cstat') ui.set_syserror(None) assert ui.get_staterror() == pytest.approx(staterror) with pytest.raises(DataErr) as err: ui.get_syserror() assert str(err.value) == "data set '1' does not specify systematic errors" combo = staterror assert ui.get_error() == pytest.approx(combo)
def tst_ui(thaw_c1, setUp, clean_ui): data, mdl = setUp ui.load_arrays(1, data.x, data.y, data.staterror) ui.set_source(1, ui.polynom1d.mdl) if thaw_c1: ui.thaw(mdl.c1) ui.thaw(mdl.c2) mdl.c2 = 1 ui.fit() if not thaw_c1: ui.thaw(mdl.c1) ui.fit() ui.conf() result = ui.get_conf_results() cmp_results(result)
def test_electron_models(): """ test import """ from ..sherpa_models import InverseCompton, Synchrotron, Bremsstrahlung for modelclass in [InverseCompton, Synchrotron, Bremsstrahlung]: model = modelclass() model.ampl = 1e-8 model.index = 2.1 print(model) # point calc output = model.calc([p.val for p in model.pars], energies) # test as well ECPL model.cutoff = 100 # integrated output = model.calc([p.val for p in model.pars], elo, xhi=ehi) if modelclass is InverseCompton: # Perform a fit to fake data ui.load_arrays(1, energies, test_spec_points, test_err_points) ui.set_model(model) ui.guess() ui.fit() # add FIR and NIR components and test verbose model.uNIR.set(1.0) model.uFIR.set(1.0) model.verbose.set(1) # test with integrated data ui.load_arrays(1, elo, ehi, test_spec_int, test_err_int, ui.Data1DInt) ui.set_model(model) ui.guess() ui.fit()
def fit_pix_values(t_ccd, esec, id=1): logger = logging.getLogger("sherpa") logger.setLevel(logging.WARN) data_id = id ui.clean() ui.set_method("simplex") ui.load_user_model(dark_scale_model, "model") ui.add_user_pars("model", ["scale", "dark_t_ref"]) ui.set_model(data_id, "model") ui.load_arrays(data_id, np.array(t_ccd), np.array(esec), 0.1 * np.ones(len(t_ccd))) model.scale.val = 0.70 model.dark_t_ref.val = 500 ui.freeze(model.scale) # If more than 5 degrees in the temperature range, # thaw and fit for model.scale. Else just use/return # the fit of dark_t_ref ui.fit(data_id) ui.thaw(model.scale) ui.fit(data_id) return ui.get_fit_results(), ui.get_model(data_id)
def _fit_poly(fit_data, evt_times, degree, data_id=0): """ Given event data transformed into Y or Z angle positions, and a degree of the desired fit polynomial, fit a polynomial to the data. :param fit_data: event y or z angle position data :param evt_times: times of event/fit_data :param degree: degree of polynomial to use for the fit model :param data_id: sherpa dataset id to use for the fit :returns: (sherpa model plot, sherpa model) """ # Set initial value for fit data position error init_error = 1 ui.clean() ui.load_arrays(data_id, evt_times - evt_times[0], fit_data, np.zeros_like(fit_data) + init_error) v2("Fitting a line to the data to get reduced stat errors") # First just fit a line to get reduced errors on this set ui.polynom1d.line ui.set_model(data_id, 'line') ui.thaw('line.c1') ui.fit(data_id) fit = ui.get_fit_results() calc_error = init_error * np.sqrt(fit.rstat) ui.set_staterror(data_id, calc_error) # Then fit the specified model v2("Fitting a polynomial of degree {} to the data".format(degree)) ui.polynom1d.fitpoly ui.freeze('fitpoly') # Thaw the coefficients requested by the degree of the desired polynomial ui.thaw('fitpoly.c0') fitpoly.c0.val = 0 for deg in range(1, 1 + degree): ui.thaw("fitpoly.c{}".format(deg)) ui.set_model(data_id, 'fitpoly') ui.fit(data_id) mp = ui.get_model_plot(data_id) model = ui.get_model(data_id) return mp, model
def mwl_fit_high_level(): """Use high-level Sherpa API. High-level = session and convenience functions Example: http://cxc.harvard.edu/sherpa/threads/simultaneous/ Example: http://python4astronomers.github.io/fitting/spectrum.html """ import sherpa.ui as ui fermi_data = FermiData() ui.load_arrays(fermi_data.name, fermi_data.x, fermi_data.y, fermi_data.staterror) ui.load_user_stat('fermi_stat', FermiStat.calc_stat, FermiStat.calc_staterror) # TODO: is there a good way to get the stat?? # ui.get_stat('fermi_stat') # fermi_stat = ui._session._get_stat_by_name('fermi_stat') ui.set_stat(fermi_stat) # IPython.embed() iact_data = IACTData() ui.load_arrays(iact_data.name, iact_data.x, iact_data.y, iact_data.staterror) spec_model = ui.logparabola.spec_model spec_model.c1 = 0.5 spec_model.c2 = 0.2 spec_model.ampl = 5e-11 ui.set_source(fermi_data.name, spec_model) ui.set_source(iact_data.name, spec_model) ui.notice(lo=1e-3, hi=None) # IPython.embed() ui.fit() return Bunch(results=ui.get_fit_results(), model=spec_model)
class AstropyToSherpa(object): def __init__(self, model): self.model = model def __call__(self, pars, x): self.model.parameters[:] = pars return self.model(x) ap_model = (models.Gaussian1D(amplitude=1.2, mean=0.9, stddev=0.5) + models.Gaussian1D(amplitude=2.0, mean=-0.9, stddev=0.75)) err = 0.02 x = np.arange(-3, 3, .1) y = ap_model(x) + err * np.random.uniform(size=len(x)) sh_model = AstropyToSherpa(ap_model) ui.load_arrays(1, x, y, err * np.ones_like(x)) ui.load_user_model(sh_model, 'sherpa_model') ui.add_user_pars('sherpa_model', ap_model.param_names, ap_model.parameters) ui.set_model(1, 'sherpa_model') ui.fit(1) ui.plot_fit(1) print() print('Params from astropy model: {}'.format(ap_model.parameters)) plt.show()
def run_fits(obsids, ax, user_pars=None, fixed_pars=None, guess_pars=None, label='model', per_obs_dir='per_obs_nfits', outdir=None, redo=False): if len(obsids) == 0: print "No obsids, nothing to fit" return None if user_pars is None: user_pars = USER_PARS if not os.path.exists(per_obs_dir): os.makedirs(per_obs_dir) obsfits = [] for obsid in obsids: outdir = os.path.join(per_obs_dir, 'obs{:05d}'.format(obsid)) if not os.path.exists(outdir): os.makedirs(outdir) model_file = os.path.join(outdir, '{}.pkl'.format(label)) if os.path.exists(model_file) and not redo: #logger.warn('Using previous fit found in %s' % model_file) print model_file mod_pick = open(model_file, 'r') modelfit = cPickle.load( mod_pick ) mod_pick.close() obsfits.append(modelfit) continue modelfit = {'label': obsid} ui.clean() data_id = 0 obsdir = "%s/obs%05d" % (DATADIR, obsid) tf = open(os.path.join(obsdir,'tilt.pkl'), 'r') tilt = cPickle.load(tf) tf.close() pf = open(os.path.join(obsdir, 'pos.pkl'), 'r') pos = cPickle.load(pf) pf.close() pos_data = pos[ax] point_error = 5 pos_data_mean = np.mean(pos_data) ui.set_method('simplex') # Fit a line to get more reasonable errors init_staterror = np.zeros(len(pos_data))+point_error ui.load_arrays(data_id, pos['time']-pos['time'][0], pos_data-np.mean(pos_data), init_staterror) ui.polynom1d.ypoly ui.set_model(data_id, 'ypoly') ui.thaw(ypoly.c0, ypoly.c1) ui.fit(data_id) fit = ui.get_fit_results() calc_staterror = init_staterror * np.sqrt(fit.rstat) ui.set_staterror(data_id, calc_staterror) # Confirm those errors ui.fit(data_id) fit = ui.get_fit_results() if ( abs(fit.rstat-1) > .2): raise ValueError('Reduced statistic not close to 1 for error calc') # Load up data to do the real model fit fit_times = pos['time'] tm_func = tilt_model(tilt, fit_times, user_pars=user_pars) ui.get_data(data_id).name = str(obsid) ui.load_user_model(tm_func, 'tiltm%d' % data_id) ui.add_user_pars('tiltm%d' % data_id, user_pars) ui.set_method('simplex') ui.set_model(data_id, 'tiltm%d' % (data_id)) ui.set_par('tiltm%d.diam' % data_id, 0) if fixed_pars is not None and ax in fixed_pars: for par in fixed_pars[ax]: ui.set_par('tiltm{}.{}'.format(0, par), fixed_pars[ax][par]) ui.freeze('tiltm{}.{}'.format(0, par)) if guess_pars is not None and ax in guess_pars: for par in guess_pars[ax]: ui.set_par('tiltm{}.{}'.format(0, par), guess_pars[ax][par]) ui.show_all() # Fit the tilt model ui.fit(data_id) fitres = ui.get_fit_results() ui.confidence(data_id) myconf = ui.get_confidence_results() # save_fits(ax=ax, fit=fitres, conf=myconf, outdir=outdir) # plot_fits(ids,outdir=os.path.join(outdir,'fit_plots')) axmod = dict(fit=fitres, conf=myconf) for idx, modpar in enumerate(myconf.parnames): par = modpar.lstrip('tiltm0.') axmod[par] = ui.get_par('tiltm0.%s' % par).val axmod["{}_parmax".format(par)] = myconf.parmaxes[idx] axmod["{}_parmin".format(par)] = myconf.parmins[idx] modelfit[ax] = axmod mod_pick = open(model_file, 'w') cPickle.dump( modelfit, mod_pick) mod_pick.close() obsfits.append(modelfit) plot_fits([dict(obsid=obsid, data_id=data_id, ax=ax)], posdir=obsdir, outdir=outdir) return obsfits
return line #axplot = {} #ftype = 'obc_bad' for ftype in failures: fail_mask = failures[ftype] data_id = figmap[ftype] ui.set_method('simplex') ui.load_user_model(lim_line, '%s_mod' % ftype) ui.add_user_pars('%s_mod' % ftype, ['m', 'b']) ui.set_model(data_id, '%s_mod' % ftype) ui.load_arrays(data_id, times, failures[ftype]) fmod = ui.get_model_component('%s_mod' % ftype) fmod.b.min = 0 fmod.b.max = 1 fmod.m.min = 0 fmod.m.max = 0.5 fmod.b.val=1e-7 ui.load_user_stat("loglike", llh, my_err) ui.set_stat(loglike) # the tricky part here is that the "model" is the probability polynomial # we've defined evaluated at the data x values.
from matplotlib import pyplot as plt import numpy as np from sherpa import ui x1 = np.arange(-5.0, 30, 0.5) x2 = np.arange(1.0, 29.0, 0.2) ui.load_arrays(1, x1, x1 * 0, ui.Data1D) ui.load_arrays(2, x2, x2 * 0, ui.Data1D) ui.set_source(1, ui.box1d.box) box = ui.get_model_component('box') ui.set_source(2, box) box.xlow = 10.0 box.xhi = 20.0 # Copy all the objects just to make sure g1 = ui.gauss1d('g1') g1.fwhm = 3.0 g2 = ui.gauss1d('g2') g2.fwhm = 3.0 ui.load_psf('psf1', g1) ui.load_psf('psf2', g2) ui.set_psf(1, 'psf1') ui.set_psf(2, 'psf2')
wp_min = np.min(warm_frac) warm_frac = warm_frac - wp_min def scaled_warm_frac(pars, x): scaled = pars[1] + warm_frac * pars[0] return scaled data_id = 1 ui.set_method('simplex') ui.set_stat('chi2datavar') #ui.set_stat('leastsq') #ui.load_user_stat("chi2custom", my_chi2, my_err) #ui.set_stat(chi2custom) ui.load_user_model(scaled_warm_frac, 'model') ui.add_user_pars('model', ['scale', 'offset']) ui.set_model(data_id, 'model') ui.load_arrays(data_id, np.array(times), np.array(bad_frac)) fmod = ui.get_model_component('model') fmod.scale.min = 1e-9 fmod.offset.val = 0 ui.freeze(fmod.offset) max_err = np.max([err_high, err_low], axis=0) ui.set_staterror(data_id, max_err) ui.fit(data_id) f = ui.get_fit_results() scale = f.rstat ** .5 ui.set_staterror(data_id, max_err * scale) ui.fit() f = ui.get_fit_results() if f.rstat > 3: raise ValueError