def test_xspecvar_no_grouping_comparison_xspec(make_data_path,
                                               l, h, ndp, ndof, statval):
    """Compare chi2xspecvar values for a data set to XSPEC.

    The data set has a background. See
    test_xspecvar_no_grouping_no_bg_comparison_xspec

    The XSPEC version used was 12.9.0o.
    """

    dset = create_xspec_comparison_dataset(make_data_path,
                                           keep_background=True)

    # Lazy, so add it to "bad" channels too
    dset.counts += 5
    dset.get_background().counts += 3

    ui.clean()
    ui.set_data(dset)
    ui.subtract()

    ui.set_source(ui.powlaw1d.pl)
    ui.set_par('pl.ampl', 5e-4)

    ui.set_stat('chi2xspecvar')
    ui.set_analysis('energy')

    validate_xspec_result(l, h, ndp, ndof, statval)
    ui.clean()
Exemple #2
0
    def setUp(self):

        self._old_logger_level = logger.getEffectiveLevel()
        logger.setLevel(logging.ERROR)

        ui.set_stat('wstat')

        infile = self.make_path('3c273.pi')
        ui.load_pha(1, infile)

        # Change the backscale value slightly so that the
        # results are different to other runs with this file.
        #
        nbins = ui.get_data(1).get_dep(False).size
        bscal = 0.9 * np.ones(nbins) * ui.get_backscal(1)
        ui.set_backscal(1, backscale=bscal)

        ui.set_source(1, ui.powlaw1d.pl)

        # The powerlaw slope and normalization are
        # intended to be "a reasonable approximation"
        # to the data, just to make sure that any statistic
        # calculation doesn't blow-up too much.
        #
        ui.set_par("pl.gamma", 1.7)
        ui.set_par("pl.ampl", 1.7e-4)
Exemple #3
0
def test_dax_if():
    '''Test script'''
    import sherpa.astro.ui as sherpa
    sherpa.load_arrays(1, [1, 2, 3], [4, 5, 6], sherpa.Data1D)
    sherpa.set_source("polynom1d.ply")
    # DaxModelEditor([ply], "ds9").run()
    DaxModelEditor([ply]).run(sherpa.fit)
Exemple #4
0
def setup_model(make_data_path):
    """Set up a model that is reasonably close to the data.

    Returns the expected statistic values for various filters.
    """

    infile = make_data_path('q1127_src1_grp30.pi')

    ui.clean()
    ui.load_pha(infile)
    ui.subtract()

    ui.set_stat('chi2datavar')
    ui.set_source(ui.powlaw1d.pl)

    pl = ui.get_model_component('pl')
    pl.ampl = 5.28e-4
    pl.gamma = 1.04

    # These statistic values were created using CIAO 4.9 on a
    # Ubuntu machine. The quality=2 values are for high energies
    # (above ~ 10 keV or so), and so a filter of 0.5-8.0 keV should
    # give the same answer with or without ignore_bad.
    #
    return {
        'all': 2716.7086246284807,
        'bad': 2716.682482792285,
        '0.5-8.0': 1127.7165108405597
    }
Exemple #5
0
def make_test_model(nsources=100,
                    npix=500,
                    ampl=100,
                    fwhm=30,
                    random_state='random-seed'):
    """Create a model of several Gaussian sources.

    Parameters
    ----------
    random_state : {int, 'random-seed', 'global-rng', `~numpy.random.RandomState`}
        Defines random number generator initialisation.
        Passed to `~gammapy.utils.random.get_random_state`.
    """
    from sherpa.astro.ui import set_source
    from gammapy.image.models.utils import _set, _name

    # initialise random number generator
    random_state = get_random_state(random_state)

    model = ' + '.join([_name(ii) for ii in range(nsources)])
    set_source(model)
    for ii in range(nsources):
        _set(_name(ii), 'xpos', random_state.uniform(0, npix))
        _set(_name(ii), 'ypos', random_state.uniform(0, npix))
        _set(_name(ii), 'ampl', random_state.uniform(0, ampl))
        _set(_name(ii), 'fwhm', random_state.uniform(0, fwhm))
Exemple #6
0
def test_calc_flux_pha_unabsorbed(make_data_path, clean_astro_ui):
    """Can we calculate an unabsorbed flux?"""

    # The idea is that with a model expression of
    #    const1d.scale * powlaw1d.pl
    # when scale is not 1 (and not integrated) then we can
    # just look to see if the "absorbed" flux is scale * the
    # "unabsorbed" flux.
    #
    infile = make_data_path('3c273.pi')
    ui.load_pha(infile)

    scale = ui.create_model_component('const1d', 'scale')
    pl = ui.create_model_component('powlaw1d', 'pl')

    scale.c0 = 0.8
    scale.integrate = False
    pl.gamma = 1.5
    pl.ampl = 1e-4

    ui.set_source(scale * pl)

    pflux_abs = ui.calc_photon_flux(0.5, 7)
    pflux_unabs = ui.calc_photon_flux(0.5, 7, model=pl)

    eflux_abs = ui.calc_energy_flux(0.5, 7)
    eflux_unabs = ui.calc_energy_flux(0.5, 7, model=pl)

    pflux_scale = pflux_abs / pflux_unabs
    eflux_scale = eflux_abs / eflux_unabs

    assert pflux_scale == pytest.approx(0.8)
    assert eflux_scale == pytest.approx(0.8)
Exemple #7
0
def test_calc_flux_pha_invalid_range(id, func, clean_astro_ui):
    """Ensure an error is raised if lo > hi"""

    x = np.arange(3, 6)
    y = np.ones(x.size - 1)

    ui.load_arrays(id, x[:-1], x[1:], y, ui.Data1DInt)
    mdl = ui.create_model_component('const1d', 'm')

    if id is None:
        ui.set_source(mdl)
    else:
        ui.set_source(id, mdl)

    # Note: really the error message should not include energy since in
    # this case (Data1DInt) there's no energy, and if this were
    # a DataPHA case the message says energy even if analysis=wave
    # or channel.
    #
    emsg = 'the energy range is not consistent, 12 !< 5'
    with pytest.raises(IOErr, match=emsg):
        if id is None:
            func(12, 5)
        else:
            func(12, 5, id=id)
Exemple #8
0
def test_calc_flux_pha_analysis(elo, ehi, setting, lo, hi, make_data_path,
                                clean_astro_ui):
    """Do calc_photon/energy_flux return the expected results: fluxes + analysis setting

    Basic test for different analysis settings: the
    same range (modulo precision of conversion) gives the
    same results.
    """

    infile = make_data_path('3c273.pi')
    pl = ui.create_model_component('powlaw1d', 'pl')

    ui.load_pha(infile)
    ui.set_source(pl)

    pflux = ui.calc_photon_flux(elo, ehi)
    eflux = ui.calc_energy_flux(elo, ehi)

    ui.set_analysis(setting)
    pflux2 = ui.calc_photon_flux(lo, hi)
    eflux2 = ui.calc_energy_flux(lo, hi)

    # use approx here since the bin edges are not guaranteed
    # to line up, and use a large tolerance.
    #
    assert pflux2 == pytest.approx(pflux, rel=1e-2)

    eflux = np.log10(eflux)
    eflux2 = np.log10(eflux2)
    assert eflux2 == pytest.approx(eflux, rel=1e-3)
def test_xspecvar_no_grouping_no_bg_comparison_xspec(make_data_path,
                                                     l, h, ndp, ndof, statval):
    """Compare chi2xspecvar values for a data set to XSPEC.

    The data set has no background.

    See test_cstat_comparison_xspec. Note that at present
    Sherpa and XSPEC treat bins with 0 values in them differently:
    see https://github.com/sherpa/sherpa/issues/356
    so for this test all bins are forced to have at least one
    count in them (source -> 5 is added per channel,background ->
    3 is added per channel).

    The XSPEC version used was 12.9.0o.
    """

    dset = create_xspec_comparison_dataset(make_data_path,
                                           keep_background=False)

    # Lazy, so add it to "bad" channels too
    dset.counts += 5

    ui.clean()
    ui.set_data(dset)

    ui.set_source(ui.powlaw1d.pl)
    ui.set_par('pl.ampl', 5e-4)

    ui.set_stat('chi2xspecvar')
    ui.set_analysis('energy')

    validate_xspec_result(l, h, ndp, ndof, statval)
    ui.clean()
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)
Exemple #11
0
def setup_example_bkg_model(idval):
    """Set up a simple dataset + background for use in the tests.

    This includes a model for the background, unlike
    setup-example_bkg.

    Parameters
    ----------
    idval : None, int, str
        The dataset identifier.

    See Also
    --------
    setup_example_bkg
    """

    d = example_pha_with_bkg_data()
    m = example_model()
    bm = example_bkg_model()
    if idval is None:
        ui.set_data(d)
        ui.set_source(m)
        ui.set_bkg_model(bm)

    else:
        ui.set_data(idval, d)
        ui.set_source(idval, m)
        ui.set_bkg_model(idval, bm)
def test_xspecvar_no_grouping_no_bg_comparison_xspec(make_data_path, l, h, ndp,
                                                     ndof, statval):
    """Compare chi2xspecvar values for a data set to XSPEC.

    The data set has no background.

    See test_cstat_comparison_xspec. Note that at present
    Sherpa and XSPEC treat bins with 0 values in them differently:
    see https://github.com/sherpa/sherpa/issues/356
    so for this test all bins are forced to have at least one
    count in them (source -> 5 is added per channel,background ->
    3 is added per channel).

    The XSPEC version used was 12.9.0o.
    """

    dset = create_xspec_comparison_dataset(make_data_path,
                                           keep_background=False)

    # Lazy, so add it to "bad" channels too
    dset.counts += 5

    ui.clean()
    ui.set_data(dset)

    ui.set_source(ui.powlaw1d.pl)
    ui.set_par('pl.ampl', 5e-4)

    ui.set_stat('chi2xspecvar')
    ui.set_analysis('energy')

    validate_xspec_result(l, h, ndp, ndof, statval)
    ui.clean()
Exemple #13
0
def basic_img(make_data_path):
    """Create a basic image data set/setup"""

    ui.set_default_id(2)
    ui.load_image(make_data_path('img.fits'))
    ui.set_source(ui.gauss2d.gmdl)
    ui.guess()
Exemple #14
0
    def setUp(self):
        ui.dataspace1d(0.01, 11, 0.01, id=1)
        ui.dataspace1d(2, 5, 0.1, id="tst")
        ui.dataspace1d(0.1, 1, 0.1, id="not-used")

        # self.nbins = {}
        # for idval in [1, 'tst']:
        #     self.nbins[idval] = ui.get_data(1).xlo.size
        self.nbins = {1: 1099, 'tst': 30}

        ui.set_source(1, ui.powlaw1d.pl1)
        ui.set_source("tst", ui.powlaw1d.pltst)

        # when gamma=0, weight is the same for each bin (when equally
        # spaced)
        pl1.gamma = 0.0
        pl1.ampl = 1.2
        pltst.gamma = -1.0
        pltst.ampl = 2.1

        arfgrid = np.arange(0.5, 5, 0.02)
        self.arflo = arfgrid[:-1]
        self.arfhi = arfgrid[1:]
        self.flatarf = self.arflo * 0 + 10.1
        amid = (self.arflo + self.arfhi) / 2.0
        self.arf = 10 - (3.0 - amid)**2
def test_cstat_comparison_xspec(make_data_path, l, h, ndp, ndof, statval):
    """Compare CSTAT values for a data set to XSPEC.

    This checks that the "UI layer" works, although ideally there
    should be a file that can be read in rather than having to
    manipulate it (the advantage here is that it means there is
    no messing around with adding a file to the test data set).

    The XSPEC version used was 12.9.0o.
    """

    dset = create_xspec_comparison_dataset(make_data_path,
                                           keep_background=False)

    ui.clean()
    ui.set_data(dset)
    # use powlaw1d rather than xspowerlaw so do not need XSPEC
    ui.set_source(ui.powlaw1d.pl)
    ui.set_par('pl.ampl', 1e-4)

    ui.set_stat('cstat')
    ui.set_analysis('channel')

    validate_xspec_result(l, h, ndp, ndof, statval)
    ui.clean()
def test_save_model_pha_ascii(clean_astro_ui, tmp_path):
    """Can we write out data for save_model? DataPHA and ASCII"""

    ui.load_arrays(1, [1, 2], [5, 10], ui.DataPHA)

    # we need a response
    egrid = np.asarray([0.1, 0.2, 0.4])
    elo = egrid[:-1]
    ehi = egrid[1:]
    rmf = create_delta_rmf(elo, ehi, e_min=elo, e_max=ehi)
    ui.set_rmf(rmf)

    yarf = np.asarray([10, 20])
    arf = create_arf(elo, ehi, yarf)
    ui.set_arf(arf)

    ui.set_source(ui.const1d.cmdl)
    cmdl.c0 = 2

    out = tmp_path / 'model.dat'
    ui.save_model(str(out), ascii=True)

    cts = out.read_text()
    check_output(cts, ['XLO', 'XHI', 'MODEL'],
                 [[0.1, 0.2, 20], [0.2, 0.4, 40]])
def test_save_source_pha_fits(clean_astro_ui, tmp_path):
    """Can we write out data for save_source? DataPHA and FITS
    """

    from sherpa.astro.io import read_table_blocks

    ui.load_arrays(1, [1, 2], [5, 10], ui.DataPHA)

    # we need a response
    egrid = np.asarray([0.1, 0.2, 0.4])
    elo = egrid[:-1]
    ehi = egrid[1:]
    rmf = create_delta_rmf(elo, ehi, e_min=elo, e_max=ehi)
    ui.set_rmf(rmf)

    yarf = np.asarray([10, 20])
    arf = create_arf(elo, ehi, yarf)
    ui.set_arf(arf)

    ui.set_source(ui.const1d.cmdl)
    cmdl.c0 = 2

    out = tmp_path / 'model.dat'
    outfile = str(out)
    ui.save_source(outfile)

    ans = read_table_blocks(outfile)
    blocks = ans[1]
    assert len(blocks) == 2
    check_table(blocks[2], {
        'XLO': [0.1, 0.2],
        'XHI': [0.2, 0.4],
        'SOURCE': [2, 2]
    })
Exemple #18
0
def setup_example(idval):
    """Set up a simple dataset for use in the tests.

    A *very basic* ARF is used, along with an ideal RMF. The
    way this is created means the analysis is in channel space
    by default.

    Parameters
    ----------
    idval : None, int, str
        The dataset identifier.

    See Also
    --------
    setup_example_bkg
    """

    d = example_pha_data()
    m = example_model()
    if idval is None:
        ui.set_data(d)
        ui.set_source(m)

    else:
        ui.set_data(idval, d)
        ui.set_source(idval, m)
Exemple #19
0
    def setUp(self):

        self._old_logger_level = logger.getEffectiveLevel()
        logger.setLevel(logging.ERROR)

        ui.set_stat('wstat')

        infile = self.make_path('3c273.pi')
        ui.load_pha(1, infile)

        # Change the backscale value slightly so that the
        # results are different to other runs with this file.
        #
        nbins = ui.get_data(1).get_dep(False).size
        bscal = 0.9 * np.ones(nbins) * ui.get_backscal(1)
        ui.set_backscal(1, backscale=bscal)

        ui.set_source(1, ui.powlaw1d.pl)

        # The powerlaw slope and normalization are
        # intended to be "a reasonable approximation"
        # to the data, just to make sure that any statistic
        # calculation doesn't blow-up too much.
        #
        ui.set_par("pl.gamma", 1.7)
        ui.set_par("pl.ampl", 1.7e-4)
def test_save_resid_datapha_fits(tmp_path):
    """Residual, DataPHA, FITS"""

    from sherpa.astro.io import read_table_blocks

    ui.load_arrays(1, [1, 2], [5, 10], ui.DataPHA)

    # we need a response
    egrid = np.asarray([0.1, 0.2, 0.4])
    elo = egrid[:-1]
    ehi = egrid[1:]
    rmf = create_delta_rmf(elo, ehi, e_min=elo, e_max=ehi)
    ui.set_rmf(rmf)

    yarf = np.asarray([10, 20])
    arf = create_arf(elo, ehi, yarf)
    ui.set_arf(arf)

    ui.set_source(ui.const1d.cmdl)
    cmdl.c0 = 2

    out = tmp_path / 'resid.out'
    outfile = str(out)
    ui.save_resid(outfile)

    ans = read_table_blocks(outfile)
    blocks = ans[1]
    assert len(blocks) == 2
    check_table(blocks[2], {'X': [0.15, 0.3], 'RESID': [30, 10]})
def test_save_resid_dataimg_fits(tmp_path):
    """Residual, DataIMG, FITS"""

    from sherpa.astro.io import read_image

    y, x = np.mgrid[10:12, 20:23]
    x = x.flatten()
    y = y.flatten()
    z = (x - 11)**2 + (y - 21)**2
    ui.load_arrays(1, x, y, z, (2, 3), ui.DataIMG)

    ui.set_source(1, ui.const2d.cmdl)
    cmdl.c0 = 100

    out = tmp_path / "resid"
    outfile = str(out)
    ui.save_resid(outfile)

    ans = read_image(outfile)
    assert ans.shape == (2, 3)  # Is this correct?

    yl, xl = np.mgrid[1:3, 1:4]
    xl = xl.flatten()
    yl = yl.flatten()
    assert ans.x0 == pytest.approx(xl)
    assert ans.x1 == pytest.approx(yl)
    assert ans.y == pytest.approx(z - 100)
def test_save_resid_datapha(tmp_path):
    """Residual, DataPHA, ASCII"""

    ui.load_arrays(1, [1, 2], [5, 10], ui.DataPHA)

    # we need a response
    egrid = np.asarray([0.1, 0.2, 0.4])
    elo = egrid[:-1]
    ehi = egrid[1:]
    rmf = create_delta_rmf(elo, ehi, e_min=elo, e_max=ehi)
    ui.set_rmf(rmf)

    yarf = np.asarray([10, 20])
    arf = create_arf(elo, ehi, yarf)
    ui.set_arf(arf)

    ui.set_source(ui.const1d.cmdl)
    cmdl.c0 = 2

    out = tmp_path / 'resid.out'
    outfile = str(out)
    ui.save_resid(outfile, ascii=True)

    cts = out.read_text()
    check_output(cts, ['X', 'RESID'], [[0.15, 30], [0.3, 10]])
Exemple #23
0
    def set_source(self, srcmodel='xsphabs*xsapec'):
        """
        Create a source model for each dataset.  A dataset is associated
        with a specific extraction annulus. 

        :param srcmodel: string expression defining source model
        :rtype: None
        """
        self.srcmodel = srcmodel
        self._calc_vol_norm()
        self._create_src_model_components()

        for dataset in self.datasets:
            dataid = dataset['id']
            annulus = dataset['annulus']
            modelexprs = []
            for shell in range(annulus, self.nshell):
                srcmodel = self.srcmodel
                for model_comp in reversed(self.srcmodel_comps):
                    i0 = model_comp['start']
                    i1 = model_comp['end']
                    model_comp_name = '%s_%d' % (model_comp['type'], shell)
                    srcmodel = srcmodel[:i0] + model_comp_name + srcmodel[i1:]
                modelexprs.append('%.5f * %s' % (self.vol_norm[shell, annulus], srcmodel))

            modelexpr = " + ".join(modelexprs)
            print 'Setting source model for dataset %d = %s' % (dataid, modelexpr)
            SherpaUI.set_source(dataid, modelexpr)
Exemple #24
0
def test_fake_pha_multi_file(make_data_path, clean_astro_ui, reset_seed):
    '''Test fake_pha using multiple real input files.

    Note that HEG orders -1 and +1 should really be treated spearately,
    but for this test we just need two files to load.
    '''

    np.random.seed(22349)

    ui.set_source("gauss1d.g1")
    g1 = ui.get_source()
    g1.pos = 3
    g1.FWHM = .5

    ui.fake_pha(None, [
        make_data_path('3c120_heg_-1.arf.gz'),
        make_data_path('3c120_heg_1.arf.gz')
    ], [
        make_data_path('3c120_heg_-1.rmf.gz'),
        make_data_path('3c120_heg_1.rmf.gz')
    ], 500.)
    data = ui.get_data()
    # Even with noise, maximum should be close to 3 keV
    assert np.isclose(data.get_x()[np.argmax(data.counts)], 3., atol=.2)

    # This is not a test from first principles, but at least a check of
    # the current behaviour
    assert data.counts.sum() > 5000
    assert data.counts.sum() < 10000
def test_cstat_comparison_xspec(make_data_path, l, h, ndp, ndof, statval):
    """Compare CSTAT values for a data set to XSPEC.

    This checks that the "UI layer" works, although ideally there
    should be a file that can be read in rather than having to
    manipulate it (the advantage here is that it means there is
    no messing around with adding a file to the test data set).

    The XSPEC version used was 12.9.0o.
    """

    dset = create_xspec_comparison_dataset(make_data_path,
                                           keep_background=False)

    ui.clean()
    ui.set_data(dset)
    # use powlaw1d rather than xspowerlaw so do not need XSPEC
    ui.set_source(ui.powlaw1d.pl)
    ui.set_par('pl.ampl', 1e-4)

    ui.set_stat('cstat')
    ui.set_analysis('channel')

    validate_xspec_result(l, h, ndp, ndof, statval)
    ui.clean()
def _test_can_evaluate_thcompc():
    """Does this redistribute some emission?

    It does not test the result is actualy meaningful, but
    does check it's done something
    """

    ui.clean()

    ui.dataspace1d(0.1, 10, 0.01, id='unconv')
    ui.dataspace1d(0.1, 10, 0.01, id='conv')

    mconv = ui.create_model_component('xsthcompc', 'conv')
    ui.set_source('conv', mconv(ui.xsgaussian.m1))

    m1 = ui.get_model_component('m1')
    ui.set_source('unconv', m1)
    m1.lineE = 5.0
    m1.Sigma = 1.0

    yunconv = ui.get_model_plot('unconv').y.copy()
    yconv = ui.get_model_plot('conv').y.copy()

    assert (yunconv > 0).any()
    assert (yconv > 0).any()

    # not guaranteed the peak will be reduced (depends on what
    # the convolution is doing), and I would hope that flux
    # is at best conserved (ie not created), and that we don't
    # have to worry about numerical artifacts here.
    #
    assert yunconv.max() > yconv.max()
    assert yunconv.sum() >= yconv.sum()
Exemple #27
0
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_xspecvar_no_grouping_comparison_xspec(make_data_path, l, h, ndp, ndof,
                                               statval):
    """Compare chi2xspecvar values for a data set to XSPEC.

    The data set has a background. See
    test_xspecvar_no_grouping_no_bg_comparison_xspec

    The XSPEC version used was 12.9.0o.
    """

    dset = create_xspec_comparison_dataset(make_data_path,
                                           keep_background=True)

    # Lazy, so add it to "bad" channels too
    dset.counts += 5
    dset.get_background().counts += 3

    ui.clean()
    ui.set_data(dset)
    ui.subtract()

    ui.set_source(ui.powlaw1d.pl)
    ui.set_par('pl.ampl', 5e-4)

    ui.set_stat('chi2xspecvar')
    ui.set_analysis('energy')

    validate_xspec_result(l, h, ndp, ndof, statval)
    ui.clean()
Exemple #29
0
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()
Exemple #30
0
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()
Exemple #31
0
def test_fake_pha_background_model(clean_astro_ui, reset_seed):
    """Check we can add a background component.

    See also test_fake_pha_basic.

    For simplicity we use perfect responses.
    """

    np.random.seed(27347)

    id = 'qwerty'
    channels = np.arange(1, 4, dtype=np.int16)
    counts = np.ones(3, dtype=np.int16)
    bcounts = 100 * counts

    ui.load_arrays(id, channels, counts, ui.DataPHA)
    ui.set_exposure(id, 100)
    ui.set_backscal(id, 0.1)

    bkg = ui.DataPHA('bkg', channels, bcounts, exposure=200, backscal=0.4)

    ebins = np.asarray([1.1, 1.2, 1.4, 1.6])
    elo = ebins[:-1]
    ehi = ebins[1:]
    arf = ui.create_arf(elo, ehi)
    rmf = ui.create_rmf(elo, ehi, e_min=elo, e_max=ehi)

    mdl = ui.create_model_component('const1d', 'mdl')
    mdl.c0 = 0
    bkgmdl = ui.create_model_component('const1d', 'mdl')
    bkgmdl.c0 = 2
    ui.set_source(id, mdl)
    ui.set_bkg(id, bkg)
    ui.set_bkg_source(id, bkgmdl)
    ui.set_arf(id, arf, bkg_id=1)
    ui.set_rmf(id, rmf, bkg_id=1)

    ui.fake_pha(id, arf, rmf, 1000.0, bkg='model')

    faked = ui.get_data(id)
    assert faked.exposure == pytest.approx(1000.0)
    assert (faked.channel == channels).all()

    # check we've faked counts (the scaling is such that it is
    # very improbable that this condition will fail)
    assert (faked.counts > counts).all()

    # For reference the predicted source signal is
    #    [200, 400, 400]
    # and the background signal is
    #    [125, 125, 125]
    # so, even with randomly drawn values, the following
    # checks should be robust.
    #
    predicted_by_source = 1000 * mdl(elo, ehi)
    predicted_by_bkg = (1000 / 200) * (0.1 / 0.4) * bcounts
    assert (faked.counts > predicted_by_source).all()
    assert (faked.counts > predicted_by_bkg).all()
Exemple #32
0
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]
Exemple #33
0
def test_calc_flux_pha_density_bin_edges(clean_astro_ui):
    """What happens when filter edges partially overlap bins? flux density

    Later tests may also cover this condition, but here we use
    faked data that is made to make the behavior "obvious".
    """

    chans = np.arange(1, 11, 1, dtype=np.int)
    counts = np.zeros(chans.size, dtype=np.int)

    # "perfect" response
    energies = np.arange(1, 12, 1)
    elo, ehi = energies[:-1], energies[1:]
    flat = np.ones(chans.size, dtype=np.int)

    d = ui.DataPHA('example', chans, counts)
    arf = ui.create_arf(elo, ehi, flat)
    rmf = ui.create_rmf(elo,
                        ehi,
                        e_min=elo,
                        e_max=elo,
                        startchan=1,
                        fname=None)

    d.set_arf(arf)
    d.set_rmf(rmf)
    ui.set_data(1, d)

    ui.set_source(ui.powlaw1d.pl)
    pl.ampl = 1e-4
    pl.gamma = 1.7

    # choose an energy that is not equal to the center of the bin
    # just to check how this is handled
    #
    pdens = ui.calc_photon_flux(2.6)
    edens = ui.calc_energy_flux(2.6)

    enscale = sherpa.astro.utils._charge_e

    # Evaluate the model over the bin 2-3 keV; since the grid
    # has a width of 1 keV we do not need to divide by the bin
    # width when calculating the density.
    #
    ymdl = pl([2], [3])
    expected_pdens = ymdl.sum()
    expected_edens = enscale * 2.5 * expected_pdens

    # Prior to fixing #619, Sherpa returns 0 for both densities
    #
    assert pdens == pytest.approx(expected_pdens)

    # check against log as values ~ 5e-13
    edens = np.log10(edens)
    expected_edens = np.log10(expected_edens)
    assert edens == pytest.approx(expected_edens)
Exemple #34
0
 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_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))
Exemple #36
0
 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)
Exemple #37
0
 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)
Exemple #38
0
 def test_get_stat_info(self):
     fname_3c273 = self.make_path("3c273.pi")
     ui.load_pha(fname_3c273)
     src = ui.xspowerlaw.pl
     ui.set_source(src)
     ui.guess('pl')
     ui.set_stat('wstat')
     stat_info = ui.get_stat_info()[0]
     assert stat_info.dof == 44
     assert stat_info.numpoints == 46
Exemple #39
0
 def test_get_stat_info(self):
     fname_3c273 = self.make_path("3c273.pi")
     ui.load_pha(fname_3c273)
     src = ui.xspowerlaw.pl
     ui.set_source(src)
     ui.guess('pl')
     ui.set_stat('wstat')
     stat_info = ui.get_stat_info()[0]
     assert stat_info.dof == 44
     assert stat_info.numpoints == 46
Exemple #40
0
def make_test_model(nsources=100, npix=500, ampl=100, fwhm=30):
    """Create a model of several Gaussian sources"""
    from numpy.random import random
    from sherpa.astro.ui import set_source
    from morphology.utils import _set, _name
    model = ' + '.join([_name(ii) for ii in range(nsources)])
    set_source(model)
    for ii in range(nsources):
        _set(_name(ii), 'xpos', npix * random())
        _set(_name(ii), 'ypos', npix * random())
        _set(_name(ii), 'ampl', ampl * random())
        _set(_name(ii), 'fwhm', fwhm * random())
Exemple #41
0
 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 run_hspec_fit(self, model, thres_low, thres_high):
        """Run the gammapy.hspec fit

        Parameters
        ----------
        model : str
            Sherpa model
        thres_high : `~gammapy.spectrum.Energy`
            Upper threshold of the spectral fit
        thres_low : `~gammapy.spectrum.Energy`
            Lower threshold of the spectral fit
        """

        log.info("Starting HSPEC")
        import sherpa.astro.ui as sau
        from ..hspec import wstat
        from sherpa.models import PowLaw1D

        if model == 'PL':
            p1 = PowLaw1D('p1')
            p1.gamma = 2.2
            p1.ref = 1e9
            p1.ampl = 6e-19
        else:
            raise ValueError('Desired Model is not defined')

        thres = thres_low.to('keV').value
        emax = thres_high.to('keV').value

        sau.freeze(p1.ref)
        sau.set_conf_opt("max_rstat", 100)

        list_data = []
        for obs in self.observations:
            datid = obs.phafile.parts[-1][7:12]
            sau.load_data(datid, str(obs.phafile))
            sau.notice_id(datid, thres, emax)
            sau.set_source(datid, p1)
            list_data.append(datid)
        wstat.wfit(list_data)
        sau.covar()
        fit_val = sau.get_covar_results()
        fit_attrs = ('parnames', 'parvals', 'parmins', 'parmaxes')
        fit = dict((attr, getattr(fit_val, attr)) for attr in fit_attrs)
        fit = self.apply_containment(fit)
        sau.clean()
        self.fit = fit
Exemple #43
0
    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_can_use_pspc_data(make_data_path):
    """A basic check that we can read in and use the ROSAT PSPC data.

    Unlike the previous tests, that directly access the io module,
    this uses the ui interface.
    """

    # The PSPC PHA file does not have the ANCRFILE/RESPFILE keywords
    # set up, so the responses has to be manually added.
    #
    ui.load_pha(make_data_path(PHAFILE), use_errors=True)
    assert ui.get_analysis() == 'channel'

    ui.load_rmf(make_data_path(RMFFILE))
    assert ui.get_analysis() == 'energy'

    ui.set_source(ui.powlaw1d.pl)
    ui.set_par('pl.gamma', 1.7)
    ui.set_par('pl.ampl', 2e-6)

    s = ui.get_stat_info()[0]
    assert s.numpoints == 63
    assert s.dof == 61

    # Value obtained from XSPEC 12.9.1p; Sherpa returns
    # sexpected = 973.2270845920297
    sexpected = 973.23
    assert_allclose(s.statval, sexpected, rtol=0, atol=0.005)

    # apply an energy filter to remove the "bogus" points
    ui.ignore(None, 0.05)

    s = ui.get_stat_info()[0]
    assert s.numpoints == 62
    assert s.dof == 60
    assert_allclose(s.statval, sexpected, rtol=0, atol=0.005)

    ui.ignore(2.01, None)

    s = ui.get_stat_info()[0]
    assert s.numpoints == 7
    assert s.dof == 5

    assert_allclose(s.statval, sexpected, rtol=0, atol=0.005)
Exemple #45
0
    def setUp(self):

        self._old_logger_level = logger.getEffectiveLevel()
        logger.setLevel(logging.ERROR)

        ui.set_stat('wstat')

        infile1 = self.make_path('3c273.pi')
        infile2 = self.make_path('9774.pi')
        ui.load_pha(1, infile1)
        ui.load_pha(2, infile2)

        # Since 9774.pi isn't grouped, group it. Note that this
        # call groups the background to 20 counts per bin. In this
        # case we do not want that; instead we want to use the same
        # grouping scheme as the source file.
        #
        # Note: this is related to issue 227
        #
        ui.group_counts(2, 20)
        ui.set_grouping(2, bkg_id=1, val=ui.get_grouping(2))

        # There's no need to have the same model in both datasets,
        # but assume the same source model can be used, with a
        # normalization difference.
        #
        ui.set_source(1, ui.powlaw1d.pl1)
        ui.set_source(2, ui.const1d.c2 * ui.get_source(1))

        # The powerlaw slope and normalization are
        # intended to be "a reasonable approximation"
        # to the data, just to make sure that any statistic
        # calculation doesn't blow-up too much.
        #
        # Note: the model values for 3c273 are slighly different
        #       to the single-PHA-file case, so stat results are
        #       slightly different
        #
        ui.set_par("pl1.gamma", 1.7)
        ui.set_par("pl1.ampl", 1.6e-4)
        ui.set_par("c2.c0", 45)
def test_wstat_comparison_xspec(make_data_path, l, h, ndp, ndof, statval):
    """Compare WSTAT values for a data set to XSPEC.

    See test_cstat_comparison_xspec.

    The XSPEC version used was 12.9.0o.
    """

    dset = create_xspec_comparison_dataset(make_data_path,
                                           keep_background=True)

    ui.clean()
    ui.set_data(dset)
    ui.set_source(ui.powlaw1d.pl)
    ui.set_par('pl.ampl', 1e-4)

    ui.set_stat('wstat')
    ui.set_analysis('channel')

    validate_xspec_result(l, h, ndp, ndof, statval)
    ui.clean()
Exemple #47
0
def make_test_model(nsources=100, npix=500, ampl=100, fwhm=30, random_state="random-seed"):
    """Create a model of several Gaussian sources.

    Parameters
    ----------
    random_state : {int, 'random-seed', 'global-rng', `~numpy.random.RandomState`}
        Defines random number generator initialisation.
        Passed to `~gammapy.utils.random.get_random_state`.
    """
    from sherpa.astro.ui import set_source
    from morphology.utils import _set, _name

    # initialise random number generator
    random_state = get_random_state(random_state)

    model = " + ".join([_name(ii) for ii in range(nsources)])
    set_source(model)
    for ii in range(nsources):
        _set(_name(ii), "xpos", random_state.uniform(0, npix))
        _set(_name(ii), "ypos", random_state.uniform(0, npix))
        _set(_name(ii), "ampl", random_state.uniform(0, ampl))
        _set(_name(ii), "fwhm", random_state.uniform(0, fwhm))
Exemple #48
0
    def setUp(self):

        self._old_logger_level = logger.getEffectiveLevel()
        logger.setLevel(logging.ERROR)

        ui.set_stat('wstat')

        infile = self.make_path('9774.pi')
        ui.load_pha(1, infile)

        ui.group_counts(1, 20)

        # Unlike the test_wstat_two_scalar case, the grouping
        # is not copied over.
        # ui.set_grouping(1, bkg_id=1, val=ui.get_grouping(1))

        ui.set_source(1, ui.const1d.c1 * ui.powlaw1d.pl1)

        # These should be the same as test_wstat_two_scalar
        #
        ui.set_par("pl1.gamma", 1.7)
        ui.set_par("pl1.ampl", 1.6e-4)
        ui.set_par("c1.c0", 45)
Exemple #49
0
    def _run_hspec_fit(self):
        """Run the gammapy.hspec fit
        """

        log.info("Starting HSPEC")
        import sherpa.astro.ui as sau
        from ..hspec import wstat

        sau.set_conf_opt("max_rstat", 100)

        thres_lo = self.energy_threshold_low.to('keV').value
        thres_hi = self.energy_threshold_high.to('keV').value
        sau.freeze(self.model.ref)

        list_data = []
        for pha in self.pha:
            datid = pha.parts[-1][7:12]
            sau.load_data(datid, str(pha))
            sau.notice_id(datid, thres_lo, thres_hi)
            sau.set_source(datid, self.model)
            list_data.append(datid)

        wstat.wfit(list_data)
Exemple #50
0
    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)

        ui.set_stat('wstat')

        infile = self.make_path('3c273.pi')
        ui.load_pha(1, infile)

        ui.set_source(1, ui.powlaw1d.pl)

        # The powerlaw slope and normalization are
        # intended to be "a reasonable approximation"
        # to the data, just to make sure that any statistic
        # calculation doesn't blow-up too much.
        #
        ui.set_par("pl.gamma", 1.782)
        ui.set_par("pl.ampl", 1.622e-4)
Exemple #51
0
# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""Compute results with Sherpa"""
from __future__ import print_function, division
import numpy as np
import sherpa.astro.ui as sau

sau.load_data("counts.fits.gz")
sau.set_source("normgauss2d.source + const2d.background")
sau.set_stat("cstat")
# Ask for high-precision results
sau.set_method_opt("ftol", 1e-20)
sau.set_covar_opt("eps", 1e-20)

# Set start parameters close to simulation values to make the fit converge
sau.set_par("source.xpos", 101)
sau.set_par("source.ypos", 101)
sau.set_par("source.ampl", 1.1e3)
sau.set_par("source.fwhm", 10)
sau.set_par("background.c0", 1.1)

# Run fit and covariance estimation
# Results are automatically printed to the screen
sau.fit()
sau.covar()

# Sherpa uses fwhm instead of sigma as extension parameter ... need to convert
# http://cxc.harvard.edu/sherpa/ahelp/gauss2d.html
fwhm_to_sigma = 1.0 / np.sqrt(8 * np.log(2))
cov = sau.get_covar_results()
sigma = fwhm_to_sigma * cov.parvals[0]
sigma_err = fwhm_to_sigma * cov.parmaxes[0]
Exemple #52
0
"""
import sherpa.astro.ui as ui
from kapteyn import wcs, positions
try:
    from astropy.io import fits
except:
    import pyfits as fits

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]))
def test_can_use_swift_data(make_data_path):
    """A basic check that we can read in and use the Swift data.

    Unlike the previous tests, that directly access the io module,
    this uses the ui interface.
    """

    # QUS are there pytest fixtures that ensure the state is
    # clean on entry and exit?
    ui.clean()

    # The Swift PHA file does not have the ANCRFILE/RESPFILE keywords
    # set up, so the responses have to be manually added.
    #
    ui.load_pha(make_data_path(PHAFILE))

    rmffile = make_data_path(RMFFILE)
    with warnings.catch_warnings(record=True) as ws:
        warnings.simplefilter("always")
        ui.load_rmf(rmffile)

    validate_replacement_warning(ws, 'RMF', rmffile)

    arffile = make_data_path(ARFFILE)
    with warnings.catch_warnings(record=True) as ws:
        warnings.simplefilter("always")
        ui.load_arf(arffile)

    validate_replacement_warning(ws, 'ARF', arffile)

    assert ui.get_analysis() == 'energy'

    arf = ui.get_arf()
    rmf = ui.get_rmf()
    assert arf.energ_lo[0] == EMIN
    assert rmf.energ_lo[0] == EMIN
    assert rmf.e_min[0] == 0.0

    ui.set_source(ui.powlaw1d.pl)
    ui.set_par('pl.ampl', 0.0003)

    stat = ui.calc_stat()

    # This check is purely a regression test, so the value has
    # not been externally validated.
    #
    assert_allclose(stat, 58.2813692358182)

    # Pick an energy range which isn't affected by the first
    # bin.
    #
    # Unfortunately, using a range of 0.3-8.0 gives 771 bins
    # in XSPEC - channels 30 to 800 - but 772 bins in Sherpa.
    # If I use ignore(None, 0.3); ignore(8.0, None) instead
    # then the result is 771 bins. This is because the e_min/max
    # of the RMF has channel widths of 0.01 keV, starting at 0,
    # so both 0.3 and 8.0 fall on a bin boundary. So, it's either
    # a difference in < or <= (or > vs >=), or a rounding issue
    # due to floating-point conversion leading to one bin boundary
    # being slightly different in Sherpa vs XSPEC).
    #
    # When using ui.notice(0.3, 8.0); ui.get_indep(filter=True)
    # returns 772 channels, 30 to 801.
    #
    # Using ui.notice(0.3, 7.995) selects channels 30 to 800. So
    # this range is used. Alternatively, channel 801 could have been
    # excluded explicitly.
    #
    # ui.notice(0.3, 8.0)
    ui.notice(0.3, 7.995)

    # XSPEC 12.9.1b calculation of the statistic:
    #   chi sq = 203.88 from 771 bins with 769 dof
    #   cstat  = 568.52
    #
    # There are known differences between XSPEC and Sherpa
    # with chi2xspecvar. This only affects data sets where
    # there is background subtraction, which is not the case
    # here. See https://github.com/sherpa/sherpa/issues/356
    #
    ui.set_stat('chi2xspecvar')
    stat_xvar = ui.get_stat_info()

    assert len(stat_xvar) == 1
    stat_xvar = stat_xvar[0]
    assert stat_xvar.numpoints == 771
    assert stat_xvar.dof == 769
    assert_allclose(stat_xvar.statval, 203.88,
                    rtol=0, atol=0.005)

    ui.set_stat('cstat')
    stat_cstat = ui.get_stat_info()

    assert len(stat_cstat) == 1
    stat_cstat = stat_cstat[0]
    assert stat_cstat.numpoints == 771
    assert stat_cstat.dof == 769
    assert_allclose(stat_cstat.statval, 568.52,
                    rtol=0, atol=0.005)

    ui.clean()
Exemple #54
0
 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()
Exemple #55
0
import numpy as np
import sherpa.astro.ui as sau 

# Define width of the source and the PSF
sigma_psf, sigma_source = 3, 4
# for relation of sigma and fwhm see
# http://cxc.harvard.edu/sherpa/ahelp/gauss2d.html
sigma_to_fwhm = np.sqrt(8 * np.log(2))  # ~ 2.35
sigma = np.sqrt(sigma_psf ** 2 + sigma_source ** 2)
fwhm = sigma_to_fwhm * sigma

# Seed the random number generator to make the output reproducible
np.random.seed(0)

sau.dataspace2d((200, 200))
sau.set_source('normgauss2d.source + const2d.background')
sau.set_par('source.xpos', 100)
sau.set_par('source.ypos', 100)
sau.set_par('source.ampl', 1e3)
sau.set_par('source.fwhm', fwhm)
sau.set_par('background.c0', 1)

sau.fake()
sau.save_model('model.fits.gz', clobber=True)
sau.save_data('counts.fits.gz', clobber=True)

sau.set_source('source')
sau.save_model('source.fits.gz', clobber=True)

sau.set_source('background')
sau.save_model('background.fits.gz', clobber=True)
    def test_chi2(self):

        # Case 1: first ds has no error, second has, chi2-derived (chi2gehrels)
        # statistic. I expect stat.name to be chi2gehrels for ds1, chi2 for
        # ds2, chi2gehrels for ds1,2
        ui.load_data(1, self.data)
        ui.load_data(2, self.data, use_errors=True)

        ui.set_source(1, "gauss1d.g1")
        ui.set_source(2, "gauss1d.g1")

        ui.set_stat("chi2gehrels")

        si = ui.get_stat_info()

        stat1 = si[0].statname
        stat2 = si[1].statname
        stat12 = si[2].statname

        self.assertEqual('chi2gehrels', stat1)
        self.assertEqual('chi2', stat2)
        self.assertEqual('chi2gehrels', stat12)

        # Case 2: first ds has errors, second has not, chi2-derived
        # (chi2gehrels) statistic. I expect stat.name to be chi2 for ds1,
        # chi2gehrels for ds2, chi2gehrels for ds1,2
        ui.load_data(2, self.data)
        ui.load_data(1, self.data, use_errors=True)

        si = ui.get_stat_info()

        stat1 = si[0].statname
        stat2 = si[1].statname
        stat12 = si[2].statname

        self.assertEqual('chi2gehrels', stat2)
        self.assertEqual('chi2', stat1)
        self.assertEqual('chi2gehrels', stat12)

        # Case 3: both datasets have errors, chi2-derived (chi2gehrels)
        # statistic. I expect stat.name to be chi2 for all of them.
        ui.load_data(2, self.data, use_errors=True)
        ui.load_data(1, self.data, use_errors=True)

        si = ui.get_stat_info()

        stat1 = si[0].statname
        stat2 = si[1].statname
        stat12 = si[2].statname

        self.assertEqual('chi2', stat2)
        self.assertEqual('chi2', stat1)
        self.assertEqual('chi2', stat12)

        # Case 4: first ds has errors, second has not, LeastSq statistic
        # I expect stat.name to be leastsq for all of them.
        ui.load_data(2, self.data)
        ui.load_data(1, self.data, use_errors=True)

        ui.set_stat("leastsq")

        si = ui.get_stat_info()

        stat1 = si[0].statname
        stat2 = si[1].statname
        stat12 = si[2].statname

        self.assertEqual('leastsq', stat2)
        self.assertEqual('leastsq', stat1)
        self.assertEqual('leastsq', stat12)

        # Case 5: both ds have errors, LeastSq statistic
        # I expect stat.name to be leastsq for all of them.
        ui.load_data(2, self.data, use_errors=True)
        ui.load_data(1, self.data, use_errors=True)

        ui.set_stat("leastsq")

        si = ui.get_stat_info()

        stat1 = si[0].statname
        stat2 = si[1].statname
        stat12 = si[2].statname

        self.assertEqual('leastsq', stat2)
        self.assertEqual('leastsq', stat1)
        self.assertEqual('leastsq', stat12)

        # Case 6: first ds has errors, second has not, CStat statistic
        # I expect stat.name to be cstat for all of them.
        ui.load_data(2, self.data)
        ui.load_data(1, self.data, use_errors=True)

        ui.set_stat("cstat")

        si = ui.get_stat_info()

        stat1 = si[0].statname
        stat2 = si[1].statname
        stat12 = si[2].statname

        self.assertEqual('cstat', stat2)
        self.assertEqual('cstat', stat1)
        self.assertEqual('cstat', stat12)

        # Case7: select chi2 as statistic. One of the ds does not provide
        # errors. I expect sherpa to raise a StatErr exception.
        ui.set_stat('chi2')

        caught = False

        from sherpa.utils.err import StatErr
        try:
            ui.get_stat_info()
        except StatErr:
            caught = True

        self.assertTrue(caught, msg='StatErr was not caught')

        # Case8: select chi2 as statistic. Both datasets provide errors
        # I expect stat to be 'chi2'
        ui.load_data(2, self.data, use_errors=True)
        si = ui.get_stat_info()

        stat1 = si[0].statname
        stat2 = si[1].statname
        stat12 = si[2].statname

        self.assertEqual('chi2', stat2)
        self.assertEqual('chi2', stat1)
        self.assertEqual('chi2', stat12)
Exemple #57
0
    def set_source(self):
        if self.FN == 'F':
            modelstring = 'empG160M'
        elif self.FN == 'N':
            modelstring = 'tabNUV'
        else:
            raise ValueError('F - FUV/G160M, N - NUV/G285M, not recognized: {0}').format(self.FN)


        modelstring = modelstring + '(const1d.c1'
        for i, line in enumerate(self.H2lines):
            line['source'] = 'lorentz1d.h{0}'.format(i)
            modelstring = modelstring + '+ ' + line['source']
        for i, line in enumerate(self.nonH2lines):
            line['source'] = 'lorentz1d.l{0}'.format(i)
            modelstring = modelstring + '+ ' + line['source']
        modelstring = modelstring + ')'
        print modelstring
        ui.set_source(modelstring)

        # set some reasonable limits for the model parameters
        # to increase the chances of achieving a reasonable fit

        # If there is more than 1 H_2 line, we link the wavelength together
        if len(self.H2lines) > 0:
            wave_base = self.H2lines[0]['wave']
            model_base = ui.get_model_component('h0')
            set_wave(model_base, wave_base)
            model_base.fwhm = 0.07
            model_base.fwhm.min = .04
            model_base.fwhm.max = .09
            model_base.ampl.max = 1e-12
            model_base.ampl = 2e-13
            model_base.ampl.min = 0
            for i, line in enumerate(self.H2lines[1:]):
                modelcomp = ui.get_model_component('h{0}'.format(i+1))
                set_wave(modelcomp, line['wave'])
                modelcomp.pos = model_base.pos + (line['wave'] - wave_base)
                modelcomp.fwhm = 0.07
                modelcomp.fwhm.min = .04
                modelcomp.fwhm.max = .09
                modelcomp.ampl.max = 1e-12
                modelcomp.ampl = 2e-13
                modelcomp.ampl.min = 0

        for i, line in enumerate(self.nonH2lines):
            modelcomp = ui.get_model_component('l{0}'.format(i))
            set_wave(modelcomp, line['wave'])
            modelcomp.fwhm = 0.07
            modelcomp.fwhm.min = .04
            modelcomp.fwhm.max = 1.
            modelcomp.ampl.max = 5e-12
            modelcomp.ampl = 2e-13
            modelcomp.ampl.min = 0
            if line['abs']:
                # The order of these statements is important, because you cannot
                # set a value below the min.
                modelcomp.ampl.min = -2e-12
                modelcomp.ampl = -2e-13
                modelcomp.ampl.max = 0


        # If the input file specified those values, they take precedence
        # over the hard-coded default value
        for line in (self.H2lines + self.nonH2lines):
            for n in ['pos','fwhm','ampl']:
                if n in line:
                    model = ui.get_model_component(line['source'].split('.')[1])
                    _set_val(model, n, line[n])

        model = ui.get_model_component('c1')
        _set_val(model, 'c0', self.const)
Exemple #58
0
 def set_source(self, model):
     """Apply source model to the dataset."""
     sau.set_source(self.name, model)
Exemple #59
0
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)
Exemple #60
0
import sherpa.astro.ui as sau

sau.load_pha("3c273.pi")
sau.set_source(sau.powlaw1d.p1)
sau.guess(p1)
sau.set_stat("wstat")
sau.fit()
stats = sau.get_stat_info()