def test_bug_276(make_data_path): ui.load_pha(make_data_path('3c273.pi')) ui.set_model('polynom1d.p1') ui.fit() ui.covar() scal = ui.get_covar_results().parmaxes ui.sample_flux(ui.get_model_component('p1'), 0.5, 1, num=5, correlated=False, scales=scal)
def test_plot_pvalue(make_data_path, clean_astro_ui, hide_log_output): fname = make_data_path("qso.pi") ui.load_pha(fname) ui.set_stat('cstat') ui.set_method("neldermead") ui.group_counts(10) ui.notice(0.3, 8) ui.set_model("xsphabs.abs1*xspowerlaw.p1") ui.set_model("abs1*(p1+gauss1d.g1)") # move the fit close to the best fit to save a small amount # of time. abs1.nh = 0.05 p1.phoindex = 1.28 p1.norm = 2e-4 g1.ampl = 1.8e-5 g1.pos = 3. ui.freeze(g1.pos) g1.fwhm = 0.1 ui.freeze(g1.fwhm) ui.fit() ui.plot_pvalue(p1, p1 + g1, num=100) tmp = ui.get_pvalue_results() assert tmp.null == pytest.approx(210.34566845619273) assert tmp.alt == pytest.approx(207.66618095925094) assert tmp.lr == pytest.approx(2.679487496941789)
def test_wstat_calc_stat_info(hide_logging, make_data_path, clean_astro_ui): "bug #147" ui.load_pha("stat", make_data_path("3c273.pi")) ui.set_source("stat", ui.powlaw1d.p1) ui.set_stat("wstat") ui.fit("stat") ui.get_stat_info()
def test_sherpa_fit(self, tmpdir): # this is to make sure that the written PHA files work with sherpa import sherpa.astro.ui as sau from sherpa.models import PowLaw1D # TODO: this works a little bit, but some info and warnings # from Sherpa remain. Not sure what to do, OK as-is for now. import logging logging.getLogger("sherpa").setLevel("ERROR") for obs in self.obs_list: obs.to_ogip_files(str(tmpdir), use_sherpa=True) filename = tmpdir / "pha_obs23523.fits" sau.load_pha(str(filename)) sau.set_stat("wstat") model = PowLaw1D("powlaw1d.default") model.ref = 1e9 model.ampl = 1 model.gamma = 2 sau.set_model(model * 1e-20) sau.fit() assert_allclose(model.pars[0].val, 2.732, rtol=1e-3) assert_allclose(model.pars[2].val, 4.647, rtol=1e-3)
def fit_coeffs(method='simplex'): method = method dummy_data = np.zeros(100) dummy_times = np.arange(100) ui.load_arrays(1, dummy_times, dummy_data) ui.set_method(method) ui.get_method().config.update(SHERPA_CONFIGS.get(method, {})) calc_model = CalcModel() ui.load_user_model(calc_model, 'axo_mod') # sets global axo_mod parnames = [] for row in range(N_ROWS): for col in range(N_COLS): parnames.append('adj_{}_{}'.format(row, col)) ui.add_user_pars('axo_mod', parnames) ui.set_model(1, 'axo_mod') calc_stat = CalcStat(axo_mod, M_2d, displ_x) ui.load_user_stat('axo_stat', calc_stat, lambda x: np.ones_like(x)) ui.set_stat(axo_stat) calc_model.set_calc_stat(calc_stat) # Set frozen, min, and max attributes for each axo_mod parameter for par in axo_mod.pars: par.val = 0.0 par.min = -5 par.max = 5 ui.fit(1) coeffs = np.array([(par.val) for pars in axo_mod.pars]) return coeffs
def test_user_stat_unit(): given_stat_error = [1.1, 2.2, 3.3] given_sys_error = [10.1, 10.2, 10.3] def calc_stat(data, _model, staterror, syserror=None, weight=None): # Make sure values are being injected correctly np.testing.assert_array_equal(given_stat_error, staterror) np.testing.assert_array_equal(given_sys_error, syserror) return 3.235, np.ones_like(data) xdata = [1, 2, 3] ydata = xdata ui.load_arrays(1, xdata, ydata, None, given_sys_error, Data1D) ui.set_model(1, 'polynom1d.p') ui.load_user_stat('customstat', calc_stat, lambda x: given_stat_error) ui.set_stat(eval('customstat')) try: ui.fit(1) except StatErr: pytest.fail("Call should not be throwing any exception (bug #341)") # Test the result is what we made the user stat return assert 3.235 == ui.get_fit_results().statval
def test_eqwith_err1(make_data_path, restore_xspec_settings): def check1(e0, e1, e2): assert e0 == pytest.approx(0.028335201547206704, rel=1.0e-3) assert e1 == pytest.approx(-0.00744118799274448756, rel=1.0e-3) assert e2 == pytest.approx(0.0706249544851336, rel=1.0e-3) ui.set_xsabund('angr') ui.set_xsxsect('bcmc') ui.load_pha(make_data_path('3c273.pi')) ui.notice(0.5, 7.0) ui.set_stat("chi2datavar") ui.set_method("simplex") ui.set_model('powlaw1d.p1+gauss1d.g1') g1.fwhm = 0.1 g1.pos = 2.0 ui.freeze(g1.pos, g1.fwhm) ui.fit() np.random.seed(2345) e = ui.eqwidth(p1, p1 + g1, error=True, niter=100) check1(e[0], e[1], e[2]) params = e[3] np.random.seed(2345) e = ui.eqwidth(p1, p1 + g1, error=True, params=params, niter=100) check1(e[0], e[1], e[2]) parvals = ui.get_fit_results().parvals assert parvals[0] == pytest.approx(1.9055272902160334, rel=1.0e-3) assert parvals[1] == pytest.approx(0.00017387966749772638, rel=1.0e-3) assert parvals[2] == pytest.approx(1.279415076070516e-05, rel=1.0e-3)
def match_wcs(wcs_img, sky_img, sky_ref, opt_alg='scipy'): """Adjust ``wcs_img`` (CRVAL{1,2} and CD{1,2}_{1,2}) using a rotation and linear offset so that ``coords_img`` matches ``coords_ref``. :param sky_img: list of (world_x, world_y) [aka RA, Dec] coords in input image :param sky_ref: list of reference (world_x, world_y) coords to match :param wcs_img: pywcs WCS object for input image :returns: d_ra, d_dec, d_theta """ pix_img = wcs_img.wcs_sky2pix(sky_img, 1) wcsmodel = WcsModel(wcs_img, sky_ref, pix_img) y = np.array(pix_img).flatten() if opt_alg == 'sherpa': x = np.arange(len(y)) import sherpa.astro.ui as ui ui.load_user_model(wcsmodel.calc_pix, 'wcsmod') ui.add_user_pars('wcsmod', ['d_ra', 'd_dec', 'd_theta']) wcsmod.d_ra = 0.0 wcsmod.d_dec = 0.0 wcsmod.d_theta = 0.0 ui.load_arrays(1, x, y, np.ones(len(y))) ui.set_model(1, wcsmod) ui.set_method('simplex') ui.fit() else: import scipy.optimize x0 = np.array([0.0, 0.0, 0.0]) d_ra, d_dec, d_theta = scipy.optimize.fmin(wcsmodel.calc_resid2, x0) print 'Scipy fit values:', d_ra, d_dec, d_theta return wcsmodel.wcs
def test_eqwith_err1(make_data_path, restore_xspec_settings): def check1(e0, e1, e2): assert e0 == approx(0.028335201547206704, rel=1.0e-3) assert e1 == approx(-0.00744118799274448756, rel=1.0e-3) assert e2 == approx(0.0706249544851336, rel=1.0e-3) ui.set_xsabund('angr') ui.set_xsxsect('bcmc') ui.load_pha(make_data_path('3c273.pi')) ui.notice(0.5, 7.0) ui.set_stat("chi2datavar") ui.set_method("simplex") ui.set_model('powlaw1d.p1+gauss1d.g1') g1.fwhm = 0.1 g1.pos = 2.0 ui.freeze(g1.pos, g1.fwhm) ui.fit() numpy.random.seed(2345) e = ui.eqwidth(p1, p1 + g1, error=True, niter=100) check1(e[0], e[1], e[2]) params = e[3] numpy.random.seed(2345) e = ui.eqwidth(p1, p1 + g1, error=True, params=params, niter=100) check1(e[0], e[1], e[2]) parvals = ui.get_fit_results().parvals assert parvals[0] == approx(1.9055272902160334, rel=1.0e-3) assert parvals[1] == approx(0.00017387966749772638, rel=1.0e-3) assert parvals[2] == approx(1.279415076070516e-05, rel=1.0e-3)
def test_ARFModelPHA(self): from sherpa.astro import ui ui.load_pha(self.make_path("3c120_meg_1.pha")) # remove the RMF to ensure this is an ARF-only analysis # (which is what is needed to trigger the bug that lead to #699) ui.get_data().set_rmf(None) ui.group_counts(20) ui.notice(0.5, 6) ui.subtract() ui.set_model(ui.xsphabs.abs1 * (ui.xsapec.bubble + ui.powlaw1d.p1)) ui.set_xsabund('angr') ui.set_xsxsect('vern') abs1.nh = 0.163 abs1.nh.freeze() p1.ampl = 0.017 p1.gamma = 1.9 bubble.kt = 0.5 bubble.norm = 4.2e-5 tol = 1.0e-2 ui.set_method_opt('ftol', tol) ui.fit() result = ui.get_fit_results() assert result.numpoints == self._fit_using_ARFModelPHA['numpoints'] assert result.dof == self._fit_using_ARFModelPHA['dof']
def fit(self, conf = False): ui.ignore(None, None) ui.notice(self.start, self.stop) self.set_source() ui.fit(1) if conf: ui.conf() res = ui.get_fit_results() for line in (self.H2lines + self.nonH2lines): sourcename = line['source'].split('.')[1] print sourcename for p in ['pos', 'fwhm', 'ampl']: n = '{0}.{1}'.format(sourcename, p) _place_val(line, p, ui.get_par(n).val) self.const = ui.get_par('c1.c0').val self.redchi2 = res.rstat if conf: res = ui.get_conf_results() for line in (self.H2lines + self.nonH2lines): sourcename = line['source'].split('.')[1] for p in ['pos', 'fwhm', 'ampl']: n = '{0}.{1}'.format(sourcename, p) parmin, parmax = _parminmax(res, n) line[p+'_max'] = parmax line[p+'_min'] = parmin # deal with error on const parmin, parmax = _parminmax(res, 'c1.c0') self.const_min = parmin self.const_max = parmax
def fit(self): """ Do a fit of the model parameters using the "onion-peeling" method: - First fit the outside shell model using the outer annulus spectrum - Freeze the model parameters for the outside shell - Fit the next inward shell / annulus and freeze those parameters - Repeat until all datasets have been fit and all shell parameters determined. - Return model parameters to original thawed/frozen status :rtype: None """ thawed = [] # Parameter objects that are not already frozen for annulus in reversed(range(self.nshell)): dataids = [x['id'] for x in self.datasets if x['annulus'] == annulus] print 'Fitting', dataids SherpaUI.fit(*dataids) for model_comp in self.model_comps: name = model_comp['name'] if model_comp['shell'] == annulus: # Remember parameters that are currently thawed for par in [SherpaUI.get_par('%s.%s'%(name, x)) for x in SherpaUI.get_model_pars(name)]: if not par.frozen: thawed.append(par) print 'Freezing', model_comp['name'] SherpaUI.freeze(model_comp['name']) # Unfreeze parameters for par in thawed: print 'Thawing', par.fullname par.thaw()
def test_default_background_issue_fit(clean_astro_ui): """Test issue #943 with fit See https://github.com/sherpa/sherpa/issues/943#issuecomment-696119982 """ ui.set_default_id('x') # use least-square as we don't really care about the fit ui.set_stat('leastsq') ui.load_arrays('x', [1, 2, 3, 4], [5, 4, 3, 4], ui.DataPHA) bkg = ui.DataPHA('bkg', np.asarray([1, 2, 3, 4]), [1, 1, 0, 1]) arf = ui.create_arf(np.asarray([0.1, 0.2, 0.3, 0.4]), np.asarray([0.2, 0.3, 0.4, 0.5])) ui.set_arf(arf) bkg.set_arf(arf) ui.set_bkg(bkg) # The model being fitted is a constant to 1,1,0,1 for # the background, so that should be 0.75 / 0.1 (as the # bin width is constant), and for the source it is # 5,4,3,4 - <0.75> [here ignoring the bin-width], # so [4.25,3.25,2.25,3.25] -> 13 / 4 -> 3.25 # ui.set_source(ui.const1d.mdl1) ui.set_bkg_source(ui.const1d.mdl2) # Prior to #943 this would give a confusing error. # ui.fit() assert mdl1.c0.val == pytest.approx(3.25 / 0.1) assert mdl2.c0.val == pytest.approx(0.75 / 0.1)
def load_data(ui, make_data_path): """ Load dataset before every test. """ ui.load_data(make_data_path("3c273.pi")) ui.set_source("powlaw1d.p") ui.set_bkg_model("const1d.c") ui.fit()
def test_background(): tmpdir = tempfile.mkdtemp() curdir = os.getcwd() os.chdir(tmpdir) kT_sim = 1.0 Z_sim = 0.0 norm_sim = 4.0e-2 nH_sim = 0.04 redshift = 0.01 exp_time = (200., "ks") area = (1000., "cm**2") wcs = create_dummy_wcs() abs_model = WabsModel(nH_sim) events = EventList.create_empty_list(exp_time, area, wcs) spec_model = TableApecModel(0.05, 12.0, 5000, thermal_broad=False) spec = spec_model.return_spectrum(kT_sim, Z_sim, redshift, norm_sim) new_events = events.add_background(spec_model.ebins, spec, prng=prng, absorb_model=abs_model) new_events = ACIS_I(new_events, rebin=False, convolve_psf=False, prng=prng) new_events.write_spectrum("background_evt.pi", clobber=True) os.system("cp %s ." % new_events.parameters["ARF"]) os.system("cp %s ." % new_events.parameters["RMF"]) load_user_model(mymodel, "wapec") add_user_pars("wapec", ["nH", "kT", "metallicity", "redshift", "norm"], [0.01, 4.0, 0.2, redshift, norm_sim*0.8], parmins=[0.0, 0.1, 0.0, -20.0, 0.0], parmaxs=[10.0, 20.0, 10.0, 20.0, 1.0e9], parfrozen=[False, False, False, True, False]) load_pha("background_evt.pi") set_stat("cstat") set_method("simplex") ignore(":0.5, 8.0:") set_model("wapec") fit() set_covar_opt("sigma", 1.6) covar() res = get_covar_results() assert np.abs(res.parvals[0]-nH_sim) < res.parmaxes[0] assert np.abs(res.parvals[1]-kT_sim) < res.parmaxes[1] assert np.abs(res.parvals[2]-Z_sim) < res.parmaxes[2] assert np.abs(res.parvals[3]-norm_sim) < res.parmaxes[3] os.chdir(curdir) shutil.rmtree(tmpdir)
def test_pha1_reg_proj(clean_astro_ui, basic_pha1): """This is potentially a time-consuming test to run, so simplify as much as possible. """ from matplotlib import pyplot as plt pl = ui.get_model_component("pl") ui.set_source(ui.xsphabs.gal * pl) gal = ui.get_model_component("gal") ui.fit() ui.reg_proj("pl.gamma", "gal.nh", min=(1.6, 0), max=(2.5, 0.2), nloop=(3, 3)) ax = plt.gca() assert ax.get_xscale() == 'linear' assert ax.get_yscale() == 'linear' assert ax.get_xlabel() == 'pl.gamma' assert ax.get_ylabel() == 'gal.nH' assert ax.get_title() == 'Region-Projection' xmin, xmax = ax.get_xlim() assert xmin == pytest.approx(1.6) assert xmax == pytest.approx(2.5) ymin, ymax = ax.get_ylim() assert ymin == pytest.approx(0.0) assert ymax == pytest.approx(0.2) assert len(ax.lines) == 1 line = ax.lines[0] assert line.get_xdata().size == 1 x0 = line.get_xdata()[0] y0 = line.get_ydata()[0] assert x0 == pytest.approx(pl.gamma.val) assert y0 == pytest.approx(gal.nh.val) # pylab get_confid_point_defaults() returns # {'symbol': '+', 'color': None} # assert line.get_marker() == '+' # the number depends on the matplotlib version: 2 for 2.2.3 and # 3 for 3.1.1; it's not clear what the "extra" one is in matplotlib 3 # (it isn't obviously visible). DJB guesses that this would be # clearer if we ran with more bins along each axis, but this would # take more time. # ncontours = len(ax.collections) assert ncontours in [2, 3]
def test_background(): tmpdir = tempfile.mkdtemp() curdir = os.getcwd() os.chdir(tmpdir) kT_sim = 1.0 Z_sim = 0.0 norm_sim = 4.0e-2 nH_sim = 0.04 redshift = 0.01 exp_time = (200., "ks") area = (1000., "cm**2") fov = (10.0, "arcmin") prng = 24 agen = ApecGenerator(0.05, 12.0, 5000, broadening=False) spec = agen.get_spectrum(kT_sim, Z_sim, redshift, norm_sim) spec.apply_foreground_absorption(norm_sim) events = make_background(area, exp_time, fov, (30.0, 45.0), spec, prng=prng) events.write_simput_file("bkgnd", overwrite=True) instrument_simulator("bkgnd_simput.fits", "bkgnd_evt.fits", exp_time, "sq_acisi_cy19", [30.0, 45.0], overwrite=True, foreground=False, ptsrc_bkgnd=False, instr_bkgnd=False, prng=prng) write_spectrum("bkgnd_evt.fits", "background_evt.pi", overwrite=True) os.system("cp %s %s ." % (arf.filename, rmf.filename)) load_user_model(mymodel, "wapec") add_user_pars("wapec", ["nH", "kT", "metallicity", "redshift", "norm"], [0.01, 4.0, 0.2, redshift, norm_sim*0.8], parmins=[0.0, 0.1, 0.0, -20.0, 0.0], parmaxs=[10.0, 20.0, 10.0, 20.0, 1.0e9], parfrozen=[False, False, False, True, False]) load_pha("background_evt.pi") set_stat("cstat") set_method("simplex") ignore(":0.5, 8.0:") set_model("wapec") fit() res = get_fit_results() assert np.abs(res.parvals[0]-nH_sim)/nH_sim < 0.1 assert np.abs(res.parvals[1]-kT_sim)/kT_sim < 0.05 assert np.abs(res.parvals[2]-Z_sim) < 0.05 assert np.abs(res.parvals[3]-norm_sim)/norm_sim < 0.05 os.chdir(curdir) shutil.rmtree(tmpdir)
def test_point_source(): tmpdir = tempfile.mkdtemp() curdir = os.getcwd() os.chdir(tmpdir) nH_sim = 0.02 norm_sim = 1.0e-4 alpha_sim = 0.95 redshift = 0.02 exp_time = (100., "ks") area = (3000., "cm**2") spec = Spectrum.from_powerlaw(alpha_sim, redshift, norm_sim, emin=0.1, emax=11.5, nbins=2000) spec.apply_foreground_absorption(nH_sim, model="tbabs") positions = [(30.01, 45.0)] events = make_point_sources(area, exp_time, positions, (30.0, 45.0), spec, prng=prng) events.write_simput_file("ptsrc", overwrite=True) instrument_simulator("ptsrc_simput.fits", "ptsrc_evt.fits", exp_time, "sq_aciss_cy20", [30.0, 45.0], overwrite=True, foreground=False, ptsrc_bkgnd=False, instr_bkgnd=False, prng=prng) write_spectrum("ptsrc_evt.fits", "point_source_evt.pi", overwrite=True) os.system("cp %s %s ." % (arf.filename, rmf.filename)) load_user_model(mymodel, "tplaw") add_user_pars("tplaw", ["nH", "norm", "redshift", "alpha"], [0.02, norm_sim*0.8, redshift, 0.9], parmins=[0.0, 0.0, 0.0, 0.1], parmaxs=[10.0, 1.0e9, 10.0, 10.0], parfrozen=[True, False, True, False]) load_pha("point_source_evt.pi") set_stat("cstat") set_method("simplex") ignore(":0.4, 9.0:") set_model("tplaw") fit() res = get_fit_results() assert np.abs(res.parvals[0]-norm_sim)/norm_sim < 0.05 assert np.abs(res.parvals[1]-alpha_sim)/alpha_sim < 0.05 os.chdir(curdir) shutil.rmtree(tmpdir)
def test_point_source(): tmpdir = tempfile.mkdtemp() curdir = os.getcwd() os.chdir(tmpdir) nH_sim = 0.02 norm_sim = 1.0e-4 alpha_sim = 0.95 redshift = 0.02 exp_time = (100., "ks") area = (3000., "cm**2") spec = Spectrum.from_powerlaw(alpha_sim, redshift, norm_sim, emin=0.1, emax=11.5, nbins=2000) spec.apply_foreground_absorption(nH_sim, model="tbabs") positions = [(30.01, 45.0)] events = make_point_sources(area, exp_time, positions, (30.0, 45.0), spec, prng=prng) events.write_simput_file("ptsrc", overwrite=True) instrument_simulator("ptsrc_simput.fits", "ptsrc_evt.fits", exp_time, "sq_aciss_cy19", [30.0, 45.0], overwrite=True, foreground=False, ptsrc_bkgnd=False, instr_bkgnd=False, prng=prng) write_spectrum("ptsrc_evt.fits", "point_source_evt.pi", overwrite=True) os.system("cp %s %s ." % (arf.filename, rmf.filename)) load_user_model(mymodel, "tplaw") add_user_pars("tplaw", ["nH", "norm", "redshift", "alpha"], [0.02, norm_sim*0.8, redshift, 0.9], parmins=[0.0, 0.0, 0.0, 0.1], parmaxs=[10.0, 1.0e9, 10.0, 10.0], parfrozen=[True, False, True, False]) load_pha("point_source_evt.pi") set_stat("cstat") set_method("simplex") ignore(":0.4, 9.0:") set_model("tplaw") fit() res = get_fit_results() assert np.abs(res.parvals[0]-norm_sim)/norm_sim < 0.05 assert np.abs(res.parvals[1]-alpha_sim)/alpha_sim < 0.05 os.chdir(curdir) shutil.rmtree(tmpdir)
def test_xspec(self): ui.load_arrays(1, self.x, self.y) ui.set_source("xspowerlaw.p") ui.set_method("moncar") ui.set_stat("chi2xspecvar") ui.fit() model = ui.get_model_component("p") expected = [-1.3686404, 0.5687635] observed = [model.PhoIndex.val, model.norm.val] assert_almost_equal(observed, expected)
def test_fit(self): ui.load_arrays(1, self.x, self.y) ui.set_source("polynom1d.p") ui.thaw("p.c1") ui.set_method("levmar") ui.fit() model = ui.get_model_component("p") expected = [0, 1] observed = [model.c0.val, model.c1.val] assert_almost_equal(observed, expected)
def test_fit_profile(model, stat, pars, reset_seed, clean_astro_ui): """Regression test simple 1D fits""" setup_data1d_fit() ui.set_source(model('mdl')) ui.guess() ui.fit() assert ui.calc_stat() == pytest.approx(stat) assert np.asarray(mdl.thawedpars) == pytest.approx(np.asarray(pars))
def test_load_multi_arfsrmfs(make_data_path, clean_astro_ui): """Added in #728 to ensure cache parameter is sent along by MultiResponseSumModel (fix #717). This has since been simplified to switch from xsapec to powlaw1d as it drops the need for XSPEC and is a simpler model, so is less affected by changes in the model code. A fit of the Sherpa powerlaw-model to 3c273.pi with a single response in CIAO 4.11 (background subtracted, 0.5-7 keV) returns gamma = 1.9298, ampl = 1.73862e-4 so doubling the response should halve the amplitude but leave the gamma value the same when using two responses, as below. This is with chi2datavar. """ pha_pi = make_data_path("3c273.pi") ui.load_pha(1, pha_pi) ui.load_pha(2, pha_pi) arf = make_data_path("3c273.arf") rmf = make_data_path("3c273.rmf") ui.load_multi_arfs(1, [arf, arf], [1, 2]) ui.load_multi_arfs(2, [arf, arf], [1, 2]) ui.load_multi_rmfs(1, [rmf, rmf], [1, 2]) ui.load_multi_rmfs(2, [rmf, rmf], [1, 2]) ui.notice(0.5, 7) ui.subtract(1) ui.subtract(2) src = ui.create_model_component('powlaw1d', 'src') ui.set_model(1, src) ui.set_model(2, src) # ensure the test is repeatable by running with a known # statistic and method # ui.set_method('levmar') ui.set_stat('chi2datavar') # Really what we care about for fixing #717 is that # fit does not error out, but it's useful to know that # the fit has changed the parameter values (which were # both 1 before the fit). # ui.fit() fr = ui.get_fit_results() assert fr.succeeded assert fr.datasets == (1, 2) assert src.gamma.val == pytest.approx(1.9298, rel=1.0e-4) assert src.ampl.val == pytest.approx(1.73862e-4 / 2, rel=1.0e-4)
def test_ui(make_data_path): infile = make_data_path('gro_delta.txt') ui.load_ascii_with_errors(1, infile, delta=True) ui.set_stat('leastsq') ui.set_model('powlaw1d.p1') ui.fit() sample = ui.resample_data(1, 10, seed=123) for p in ['p1.gamma', 'p1.ampl']: assert sample[p] == pytest.approx(RESAMPLE_BENCH_10[p], rel=1e-4)
def test_warning(make_data_path): infile = make_data_path('gro.txt') ui.load_ascii_with_errors(1, infile) powlaw1d = PowLaw1D('p1') ui.set_model(powlaw1d) ui.fit() with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") ui.resample_data(1, 3) assert len(w) == 0
def test_ui(self, tol=1.0e-3): # from shepa.astro.ui import * ui.load_ascii_with_errors(1, self.gro_delta_fname, delta=True) ui.set_stat('leastsq') ui.set_model('powlaw1d.p1') ui.fit() sample = ui.resample_data(1, 10, seed=123) self.assertEqualWithinTol(self._resample_bench_10['p1.gamma'], sample['p1.gamma']) self.assertEqualWithinTol(self._resample_bench_10['p1.ampl'], sample['p1.ampl'])
def fit_adjuster_set(coeffs, adj_idxs, method='simplex'): """ Find best fit parameters for an arbitrary subset of adjustors specified by the array ``adj_idxs``. The input ``coeffs`` are the best-fit adjustor coefficients for the last iteration. """ import sherpa.astro.ui as ui dummy_data = np.zeros(100) dummy_times = np.arange(100) ui.load_arrays(1, dummy_times, dummy_data) ui.set_method(method) ui.get_method().config.update(SHERPA_CONFIGS.get(method, {})) calc_model = CalcModel() ui.load_user_model(calc_model, 'axo_mod') # sets global axo_mod parnames = [] for adj_idx in adj_idxs: parnames.append('adj_{}'.format(adj_idx)) ui.add_user_pars('axo_mod', parnames) ui.set_model(1, 'axo_mod') coeffs = coeffs.copy() # Don't modify input coeffs coeffs[coeffs < 0] = 0 # Don't allow negative coeffs # Set frozen, min, and max attributes for each axo_mod parameter for adj_idx, par in zip(adj_idxs, axo_mod.pars): par.min = -1000 par.max = 1000 par.val = coeffs[adj_idx] print 'Setting {} to {}'.format(adj_idx, par.val) # Compute base adjusted displacements assuming all the fitted actuators # have zero drive level. coeffs[adj_idxs] = 0 base_adj_displ = M_2d.dot(coeffs) m_2d = M_2d[:, adj_idxs].copy() print m_2d.shape calc_stat = CalcStat(base_adj_displ, m_2d, DISPL_X) ui.load_user_stat('axo_stat', calc_stat, lambda x: np.ones_like(x)) ui.set_stat(axo_stat) calc_model.set_calc_stat(calc_stat) ui.fit(1) # Update coeffs with the values determined in fitting for adj_idx, par in zip(adj_idxs, axo_mod.pars): coeffs[adj_idx] = abs(par.val) return coeffs, ui.get_fit_results()
def fit_sherpa(): sh.load_data(obs_path) sh.set_source("powlaw1d.model") model.ref = 1e9 # 1 TeV = 1e9 keV model.ampl = 1.23e-20 # in cm**-2 s**-1 keV**-1 model.gamma = 2.8 sh.set_stat("cash") sh.notice(energy_range[0].to("keV").value, energy_range[1].to("keV").value) sh.fit() print(sh.get_fit_results())
def test_fit(self): """ Perform a very simple fit with built-in models, and check that the results make sense. """ ui.load_arrays(1, self.x, self.y) ui.set_source("polynom1d.p") ui.thaw("p.c1") ui.set_method("levmar") ui.fit() model = ui.get_model_component("p") assert_almost_equal(model.c0.val, 0) assert_almost_equal(model.c1.val, 1)
def test_fit(self): """ Perform a very simple fit with built-in models, and check that the results make sense. """ ui.load_arrays(1, self.x, self.y) ui.set_source("polynom1d.p") ui.thaw("p.c1") ui.set_method("levmar") ui.fit() model = ui.get_model_component("p") expected = [0, 1] observed = [model.c0.val, model.c1.val] assert_almost_equal(observed, expected)
def test_missmatch_arf(make_data_path): ui.load_pha(1, make_data_path("source1.pi")) ui.load_bkg(1, make_data_path("back1.pi")) ui.load_arf(1, make_data_path("arf_1024.fits")) ui.load_rmf(1, make_data_path("rmf_1024.fits")) ui.set_method('levmar') ui.set_model(ui.powlaw1d.p1 * ui.xswabs.abs1) ui.set_par('p1.ampl', 0.0001) ui.set_stat('cash') ui.fit() parvals = ui.get_fit_results().parvals assert parvals[0] == approx(1.47969, rel=1.0e-3) assert parvals[1] == approx(0.0019491, rel=1.0e-3) assert parvals[2] == approx(2.35452, rel=1.0e-3)
def test_sherpa_fit(tmpdir): # this is to make sure that the written PHA files work with sherpa pha1 = gammapy_extra.filename("datasets/hess-crab4_pha/pha_obs23592.fits") import sherpa.astro.ui as sau from sherpa.models import PowLaw1D sau.load_pha(pha1) sau.set_stat('wstat') model = PowLaw1D('powlaw1d.default') model.ref = 1e9 model.ampl = 1 model.gamma = 2 sau.set_model(model * 1e-20) sau.fit() assert_allclose(model.pars[0].val, 2.0281484215403616, atol=1e-4) assert_allclose(model.pars[2].val, 2.3528406790143097, atol=1e-4)
def test_numpy_histogram_density_vs_normed(): from sherpa.astro import ui ui.load_arrays(1, [1, 2, 3], [1, 2, 3]) ui.set_source('const1d.c') c = ui.get_model_component('c') ui.fit() res = ui.eqwidth(c, c+c, error=True) ui.plot_pdf(res[4]) plot = ui.get_pdf_plot() expected_x = numpy.linspace(2.5, 3.5, 13) expected_xlo, expected_xhi = expected_x[:-1], expected_x[1:] expected_y = [0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0] assert plot.y == pytest.approx(expected_y) assert plot.xlo == pytest.approx(expected_xlo) assert plot.xhi == pytest.approx(expected_xhi)
def test_sherpa_fit(self, tmpdir): # this is to make sure that the written PHA files work with sherpa import sherpa.astro.ui as sau from sherpa.models import PowLaw1D self.obs_list.write(tmpdir, use_sherpa=True) filename = tmpdir / 'pha_obs23523.fits' sau.load_pha(str(filename)) sau.set_stat('wstat') model = PowLaw1D('powlaw1d.default') model.ref = 1e9 model.ampl = 1 model.gamma = 2 sau.set_model(model * 1e-20) sau.fit() assert_allclose(model.pars[0].val, 2.0881699, rtol=1e-3) assert_allclose(model.pars[2].val, 1.6234222, rtol=1e-3)
def test_sherpa_fit(tmpdir): # this is to make sure that the written PHA files work with sherpa import sherpa.astro.ui as sau from sherpa.models import PowLaw1D filename = gammapy_extra.filename( "datasets/hess-crab4_pha/pha_obs23592.fits") sau.load_pha(filename) sau.set_stat('wstat') model = PowLaw1D('powlaw1d.default') model.ref = 1e9 model.ampl = 1 model.gamma = 2 sau.set_model(model * 1e-20) sau.fit() assert_allclose(model.pars[0].val, 2.0033101181778026) assert_allclose(model.pars[2].val, 2.2991681244938498)
def wfit(dataids=None): listids = () if dataids is None: listids = sau.list_data_ids() else: listids = dataids wstat = w_statistic(listids) sau.load_user_stat("mystat", wstat, wstat.CATstat_err_LV) sau.set_stat(mystat) sau.set_method("neldermead") # set_method("moncar") sau.set_conf_opt("max_rstat", 1000) # We don't use a specific maximum reduced statistic value # since we don't expect the cstat to be anywhere near the # large number limit sau.fit(*listids) sau.conf()
def test_user_model_stat_docs(): """ This test reproduces the documentation shown at: http://cxc.harvard.edu/sherpa4.4/statistics/#userstat and: http://cxc.harvard.edu/sherpa/threads/user_model/ I tried to be as faithful as possible to the original, although the examples in thedocs are not completely self-contained, so some changes were necessary. I changed the numpy reference, as it is imported as `np` here, and added a clean up of the environment before doing anything. For the model, the difference is that I am not importing the function from an external module, plus the dataset is different. Also, the stats docs do not perform a fit. """ def my_stat_func(data, model, staterror, syserror=None, weight=None): # A simple function to replicate χ2 fvec = ((data - model) / staterror)**2 stat = fvec.sum() return (stat, fvec) def my_staterr_func(data): # A simple staterror function return np.sqrt(data) def myline(pars, x): return pars[0]*x + pars[1] x = [1, 2, 3] y = [4, 5, 6.01] ui.clean() ui.load_arrays(1, x, y) ui.load_user_stat("mystat", my_stat_func, my_staterr_func) ui.set_stat(eval('mystat')) ui.load_user_model(myline, "myl") ui.add_user_pars("myl", ["m", "b"]) ui.set_model(eval('myl')) ui.fit() assert ui.get_par("myl.m").val == approx(1, abs=0.01) assert ui.get_par("myl.b").val == approx(3, abs=0.01)
def test_sherpa_fit(self, tmpdir): # this is to make sure that the written PHA files work with sherpa import sherpa.astro.ui as sau from sherpa.models import PowLaw1D self.obs_list.write(tmpdir, use_sherpa=True) filename = tmpdir / 'pha_obs23523.fits' sau.load_pha(str(filename)) sau.set_stat('wstat') model = PowLaw1D('powlaw1d.default') model.ref = 1e9 model.ampl = 1 model.gamma = 2 sau.set_model(model * 1e-20) sau.fit() assert_allclose(model.pars[0].val, 2.0881699260935838) assert_allclose(model.pars[2].val, 1.6234222129479836)
def test_xspec(self): """ Perform a very simple fit with an xspec model. Also check that the results make sense. This test proves that the xspec extension properly works, and that there are no obvious building, linking, or environment issues that would prevent the xspec model from running. """ ui.load_arrays(1, self.x, self.y) ui.set_source("xspowerlaw.p") ui.set_method("moncar") ui.set_stat("chi2xspecvar") ui.fit() model = ui.get_model_component("p") expected = [-1.3686404, 0.5687635] observed = [model.PhoIndex.val, model.norm.val] assert_almost_equal(observed, expected)
def test_eqwith_err(make_data_path, restore_xspec_settings): def check(a0, a1, a2): assert a0 == approx(0.16443033244310976, rel=1e-3) assert a1 == approx(0.09205564216156815, rel=1e-3) assert a2 == approx(0.23933118287470895, rel=1e-3) ui.set_method('neldermead') ui.set_stat('cstat') ui.set_xsabund('angr') ui.set_xsxsect('bcmc') ui.load_data(make_data_path('12845.pi')) ui.notice(0.5, 7) ui.set_model("xsphabs.gal*xszphabs.zabs*(powlaw1d.p1+xszgauss.g1)") ui.set_par(gal.nh, 0.08) ui.freeze(gal) ui.set_par(zabs.redshift, 0.518) ui.set_par(g1.redshift, 0.518) ui.set_par(g1.Sigma, 0.01) ui.freeze(g1.Sigma) ui.set_par(g1.LineE, min=6.0, max=7.0) ui.fit() numpy.random.seed(12345) result = ui.eqwidth(p1, p1 + g1, error=True, niter=100) check(result[0], result[1], result[2]) params = result[3] numpy.random.seed(12345) result = ui.eqwidth(p1, p1 + g1, error=True, params=params, niter=100) check(result[0], result[1], result[2]) parvals = ui.get_fit_results().parvals assert parvals[0] == approx(0.6111340686157877, rel=1.0e-3) assert parvals[1] == approx(1.6409785803466297, rel=1.0e-3) assert parvals[2] == approx(8.960926761312153e-05, rel=1.0e-3) assert parvals[3] == approx(6.620017726014523, rel=1.0e-3) assert parvals[4] == approx(1.9279114810359657e-06, rel=1.0e-3)
def test_sherpa_fit(self, tmpdir): # this is to make sure that the written PHA files work with sherpa import sherpa.astro.ui as sau from sherpa.models import PowLaw1D # TODO: this works a little bit, but some info and warnings # from Sherpa remain. Not sure what to do, OK as-is for now. import logging logging.getLogger("sherpa").setLevel("ERROR") self.obs_list.write(tmpdir, use_sherpa=True) filename = tmpdir / "pha_obs23523.fits" sau.load_pha(str(filename)) sau.set_stat("wstat") model = PowLaw1D("powlaw1d.default") model.ref = 1e9 model.ampl = 1 model.gamma = 2 sau.set_model(model * 1e-20) sau.fit() assert_allclose(model.pars[0].val, 2.732, rtol=1e-3) assert_allclose(model.pars[2].val, 4.647, rtol=1e-3)
def fit_lines(linelist, id = None, delta_lam = .2, plot = False, outfile = None): mymodel = filili.multilinemanager.GaussLines('const1d', id = id, baseline = baseline) linelist['fililiname'] = [''] * len(linelist['linename']) for i in range(len(linelist['linename'])): lname = linelist['linename'][i] lwave = linelist['wave'][i] previouslines = set(mymodel.line_name_list()) mymodel.add_line(linename = filter(lambda x: x.isalnum(), lname), pos = lwave) linenamelist = mymodel.line_name_list() newline = (set(linenamelist) - previouslines).pop() linelist['fililiname'][i] = newline if i ==0: firstline = linenamelist[0] ui.get_model_component(firstline).pos.max = lwave + delta_lam/10. ui.get_model_component(firstline).pos.min = lwave - delta_lam/10. else: dl = lwave - linelist['wave'][0] ui.link(ui.get_model_component(newline).pos, ui.get_model_component(firstline).pos + dl) #ui.set_analysis("wave") ui.ignore(None, None) #ignores all data ui.notice(min(linelist['wave'])-delta_lam, max(linelist['wave']) + delta_lam) ui.fit(id) if plot: ui.plot_fit(id) if has_chips: pychips.set_curve("crv1",["err.*","true"]) pychips.set_plot_title(linelist['name']) if outfile is not None: pychips.print_window(outfile, ['clobber','true']) elif has_mpl: plt.title(linelist['name']) if outfile is not None: plt.savefig(outfile) else: raise NoPlottingSystemError("Neither pychips nor matplotlib are found.")
def test_341(): """ The original reporter of bug #341 had a special implementation that should be captured by this test. The implementation has a proxy model that takes care of updating the actual model when it is evaluated. During a recent refactoring of the Stat and Fit code (PR #287) a regression was introduced by short-circuiting the evaluation of the model. """ class ExampleModel(object): """ Class to define model """ def __init__(self, x, y): self.x = np.array(x) self.y = np.array(y) self.parvals = [1, 2] self.parnames = ("m", "b") def calc_stat(self): return float(np.sum(np.abs(self.y - self.model()))) def model(self): return self.parvals[0] * self.x + self.parvals[1] class CalcModel(object): """ Class to update model parameters """ def __init__(self, model): self.model = model def __call__(self, pars, x): self.model.parvals = pars return np.ones_like(x) class CalcStat(object): """ Class to determine fit statistic """ def __init__(self, model): self.model = model def __call__(self, _data, _model, *args, **kwargs): fit_stat = self.model.calc_stat() return fit_stat, np.ones(1) xdata = [1, 2, 3] ydata = [4, 5, 6] newmodel = ExampleModel(xdata, ydata) dummy_data = np.zeros(1) dummy_times = np.arange(1) ui.load_arrays(1, dummy_times, dummy_data) method = 'simplex' ui.set_method(method) ui.load_user_model(CalcModel(newmodel), 'simplemodel') ui.add_user_pars('simplemodel', newmodel.parnames) ui.set_model(1, 'simplemodel') calc_stat = CalcStat(newmodel) ui.load_user_stat('customstat', calc_stat, lambda x: np.ones_like(x)) ui.set_stat(eval('customstat')) ui.fit(1) assert ui.get_par("simplemodel.m").val == approx(1, abs=0.00001) assert ui.get_par("simplemodel.b").val == approx(3, abs=0.00001)
def test_vapec_beta_model(): bms = BetaModelSource() tmpdir = tempfile.mkdtemp() curdir = os.getcwd() os.chdir(tmpdir) prng = 45 ds = bms.ds A = 30000. exp_time = 1.0e4 redshift = 0.05 nH_sim = 0.02 sphere = ds.sphere("c", (0.5, "Mpc")) kT_sim = bms.kT Z_sim = bms.Z O_sim = bms.O Ca_sim = bms.Ca var_elem = {"O": ("stream", "oxygen"), "Ca": ("stream", "calcium")} thermal_model = ThermalSourceModel("apec", 0.1, 11.5, 20000, var_elem=var_elem, Zmet=("gas","metallicity"), prng=prng) photons = PhotonList.from_data_source(sphere, redshift, A, exp_time, thermal_model) D_A = photons.parameters["fid_d_a"] norm_sim = sphere.quantities.total_quantity("emission_measure") norm_sim *= 1.0e-14/(4*np.pi*D_A*D_A*(1.+redshift)*(1.+redshift)) norm_sim = float(norm_sim.in_cgs()) events = photons.project_photons("z", [30.0, 45.0], absorb_model="tbabs", nH=nH_sim, prng=prng, no_shifting=True) new_events = Lynx_Calorimeter(events, prng=prng) os.system("cp %s %s ." % (arf.filename, rmf.filename)) new_events.write_channel_spectrum("var_abund_beta_model_evt.pha", overwrite=True) load_user_model(mymodel_var, "tbapec") add_user_pars("tbapec", ["nH", "kT", "abund", "redshift", "norm", "O", "Ca"], [nH_sim, 4.0, Z_sim, redshift, norm_sim*0.8, 0.3, 0.5], parmins=[0.0, 0.1, 0.0, -20.0, 0.0, 0.0, 0.0], parmaxs=[10.0, 20.0, 10.0, 20.0, 1.0e9, 10.0, 10.0], parfrozen=[True, False, True, True, False, False, False]) load_pha("var_abund_beta_model_evt.pha") set_stat("cstat") set_method("levmar") ignore(":0.6, 8.0:") set_model("tbapec") fit() res = get_fit_results() assert np.abs(res.parvals[0]-kT_sim)/kT_sim < 0.05 assert np.abs(res.parvals[1]-norm_sim)/norm_sim < 0.05 assert np.abs(res.parvals[2]-O_sim)/O_sim < 0.05 assert np.abs(res.parvals[3]-Ca_sim)/Ca_sim < 0.15 os.chdir(curdir) shutil.rmtree(tmpdir)
filename = 'skymap_ex.fits' nomposstr = '05h34m31.94s 22d00m52.2s' header = fits.getheader(filename) proj = wcs.Projection(header) xc, yc = float(header['NAXIS1']) / 2., float(header['NAXIS2']) / 2. ui.load_image(filename) ui.notice2d('circle({0}, {1}, {2})'.format(xc, yc, float(header['NAXIS2']) / 4.)) ui.set_source(ui.gauss2d.g1 + ui.gauss2d.g2) g1.xpos = xc g1.ypos = yc g2.fwhm = g1.fwhm = 3. ui.link(g2.xpos, g1.xpos) ui.link(g2.ypos, g1.ypos) g2.ampl = 50. g1.ampl = 50. ui.guess() ui.fit() ui.image_fit() ui.covar() conf = ui.get_covar_results() conf_dict = dict([(n,(v, l, h)) for n,v,l,h in zip(conf.parnames, conf.parvals, conf.parmins, conf.parmaxes)]) x, y = proj.toworld((conf_dict['g1.xpos'][0], conf_dict['g1.ypos'][0])) xmin, ymin = proj.toworld((conf_dict['g1.xpos'][0] + conf_dict['g1.xpos'][1], conf_dict['g1.ypos'][0] + conf_dict['g1.ypos'][1])) xmax, ymax = proj.toworld((conf_dict['g1.xpos'][0] + conf_dict['g1.xpos'][2], conf_dict['g1.ypos'][0] + conf_dict['g1.ypos'][2])) nompos = positions.str2pos(nomposstr, proj) print('{0} ({1}-{2}) vs {3}'.format(x, xmin, xmax, nompos[0][0][0])) print('{0} ({1}-{2}) vs {3}'.format(y, ymin, ymax, nompos[0][0][1]))
# Set up the model and load it as a Sherpa model def boxbod_func(pars, x): b1, b2 = pars return BoxBOD.model(x, b1, b2) ui.load_user_model(boxbod_func, "boxbod") ui.add_user_pars("boxbod", ["b1", "b2"]) bb = boxbod ui.set_model(bb) bb.b1, bb.b2 = BoxBOD.p0[0], BoxBOD.p0[1] # Perform fit ui.set_stat('chi2datavar') #ui.set_method('levmar') # ['levmar', 'moncar', 'neldermead', 'simplex'] ui.set_method_opt('xtol', 1e-10) ui.fit() # Compute best-fit parameters ui.set_covar_opt('eps', 1e-5) # @todo: Why does this parameter have no effect ui.covariance() # Compute covariance matrix (i.e. errors) #ui.conf() # Compute profile errors #ui.show_all() # Print a very nice summary of your session to less # Report results fr = ui.get_fit_results() cr = ui.get_covar_results() # Report results (we have to apply the s factor ourselves) popt = np.array(fr.parvals) chi2 = fr.statval s_factor = np.sqrt(chi2 / fr.dof) perr = s_factor * np.array(cr.parmaxes) report_results('sherpa', popt, perr, chi2)
def test_wstat_calc_stat_info(self): ui.load_pha("stat", self.make_path("3c273.pi")) ui.set_source("stat", ui.powlaw1d.p1) ui.set_stat("wstat") ui.fit("stat") ui.get_stat_info()
dummy_data = np.zeros(100) dummy_times = np.arange(100) ui.load_arrays(1, dummy_times, dummy_data) ui.set_method(method) ui.get_method().config.update(SHERPA_CONFIGS.get(method, {})) calc_model = CalcModel() ui.load_user_model(calc_model, "axo_mod") # sets global axo_mod parnames = [] for row in range(N_ROWS): for col in range(N_COLS): parnames.append("adj_{}_{}".format(row, col)) ui.add_user_pars("axo_mod", parnames) ui.set_model(1, "axo_mod") calc_stat = CalcStat(axo_mod, M_2d, displ_x) ui.load_user_stat("axo_stat", calc_stat, lambda x: np.ones_like(x)) ui.set_stat(axo_stat) calc_model.set_calc_stat(calc_stat) # Set frozen, min, and max attributes for each axo_mod parameter for par in axo_mod.pars: par.val = 0.0 # par.frozen = par.frozen par.min = -5 par.max = 5 ui.fit(1)
def fit_draws(draws, parname, nbins=50, params=None, plot=True, verbose=True): """Fit a gaussian to the histogram of the given parameter. Before using this routine you should use get_parameter_info() to extract the parameter info for use by get_draws(). This is because using this routine will invalidate the internal data structures that get_draws() uses when its params argument is None. If params is not None then it should be the return value of get_parameter_info(). If plot is True then a plot of the histogram and fit will be made. If verbose is True then a quick comparison of the fit results will be displayed. """ if parname not in draws["parnames"]: raise RuntimeError, "Unknown parameter '%s'" % parname # Exclude any point with an iteration number of 0 # idx = draws["iteration"] > 0 parvals = draws[parname][idx] (hy, hx) = np.histogram(parvals, bins=nbins, new=True) xlo = hx[:-1] xhi = hx[1:] id = parname ui.load_arrays(id, 0.5 * (xlo + xhi), hy) # We can guess the amplitude and position fairly reliably; # for the FWHM we just use the inter-quartile range of the # X axis. # ui.set_source(id, ui.gauss1d.gparam) gparam.pos = xlo[xlo.size // 2] gparam.ampl = hy[xlo.size // 2] gparam.fwhm = xlo[xlo.size * 3 // 4] - xlo[xlo.size // 4] # Get the best-fit value if available if params != None: p0 = dict(zip(params["parnames"], params["parvals"]))[parname] logger = logging.getLogger("sherpa") olvl = logger.level logger.setLevel(40) ostat = ui.get_stat_name() ui.set_stat("leastsq") ui.fit(id) ui.set_stat(ostat) logger.setLevel(olvl) if plot: # We manually create the plot since we want to use a histogram for the # data and the Sherpa plots use curves. # ##dplot = ui.get_data_plot(id) mplot = ui.get_model_plot(id) chips.lock() try: chips.open_undo_buffer() chips.erase() chips.add_histogram(xlo, xhi, hy) ##chips.add_histogram(xlo, xhi, mplot.y, ["line.color", "red", "line.style", "dot"]) chips.add_curve(mplot.x, mplot.y, ["line.color", "red", "symbol.style", "none"]) if params != None: chips.add_vline(p0, ["line.color", "green", "line.style", "longdash"]) chips.set_plot_xlabel(parname) except: chips.discard_undo_buffer() chips.unlock() raise chips.close_undo_buffer() chips.unlock() sigma = gparam.fwhm.val / (2.0 * np.sqrt(2 * np.log(2))) if verbose: print "" print "Fit to histogram of draws for parameter %s gives" % parname print " mean = %g" % gparam.pos.val print " sigma = %g" % sigma print "" if params != None: idx = params["parnames"] == parname print " best fit = %g" % p0 print " covar sigma = %g" % params["parmaxes"][idx][0] print "" return (gparam.pos.val, sigma, gparam.ampl.val)
def do_beta_model(source, v_field, em_field, axis="z", prng=None): tmpdir = tempfile.mkdtemp() curdir = os.getcwd() os.chdir(tmpdir) if prng is None: prng = source.prng ds = source.ds A = 30000. exp_time = 1.0e4 redshift = 0.05 nH_sim = 0.02 sphere = ds.sphere("c", (0.5, "Mpc")) kT_sim = source.kT Z_sim = source.Z thermal_model = ThermalSourceModel("apec", 0.1, 11.5, 20000, Zmet=Z_sim, prng=prng) photons = PhotonList.from_data_source(sphere, redshift, A, exp_time, thermal_model) D_A = photons.parameters["fid_d_a"] norm_sim = sphere.quantities.total_quantity(em_field) norm_sim *= 1.0e-14/(4*np.pi*D_A*D_A*(1.+redshift)*(1.+redshift)) norm_sim = float(norm_sim.in_cgs()) v1, v2 = sphere.quantities.weighted_variance(v_field, em_field) if isinstance(axis, string_types): if axis == "z": fac = 1.0 else: fac = 0.0 else: axis /= np.sqrt(np.dot(axis, axis)) fac = np.dot(axis, [0.0, 0.0, 1.0]) sigma_sim = fac*float(v1.in_units("km/s")) mu_sim = -fac*float(v2.in_units("km/s")) events = photons.project_photons(axis, [30.0, 45.0], absorb_model="tbabs", nH=nH_sim, prng=prng) events.write_simput_file("beta_model", overwrite=True) instrument_simulator("beta_model_simput.fits", "beta_model_evt.fits", exp_time, "mucal", [30.0, 45.0], overwrite=True, foreground=False, ptsrc_bkgnd=False, instr_bkgnd=False, prng=prng) write_spectrum("beta_model_evt.fits", "beta_model_evt.pi", overwrite=True) os.system("cp %s %s ." % (arf.filename, rmf.filename)) load_user_model(mymodel, "tbapec") add_user_pars("tbapec", ["nH", "kT", "metallicity", "redshift", "norm", "velocity"], [0.02, 4.0, 0.2, 0.04, norm_sim*0.8, 300.0], parmins=[0.0, 0.1, 0.0, -200.0, 0.0, 0.0], parmaxs=[10.0, 20.0, 10.0, 200.0, 1.0e9, 20000.0], parfrozen=[True, False, False, False, False, False]) load_pha("beta_model_evt.pi") set_stat("cstat") set_method("levmar") ignore(":0.6, 8.0:") set_model("tbapec") fit() res = get_fit_results() redshift_sim = (1.0+mu_sim/ckms)*(1.0+redshift) - 1.0 assert np.abs(res.parvals[0]-kT_sim)/kT_sim < 0.05 assert np.abs(res.parvals[1]-Z_sim)/Z_sim < 0.05 assert np.abs(res.parvals[2]-redshift_sim)/redshift_sim < 0.05 assert np.abs(res.parvals[3]-norm_sim) < 0.05 assert np.abs(res.parvals[4]-sigma_sim) < 30.0 os.chdir(curdir) shutil.rmtree(tmpdir)