diff --git a/sherpa/astro/datastack/plot_backend/__init__.py b/sherpa/astro/datastack/plot_backend/__init__.py index 70a676444f..a05bdd8863 100644 --- a/sherpa/astro/datastack/plot_backend/__init__.py +++ b/sherpa/astro/datastack/plot_backend/__init__.py @@ -1,6 +1,7 @@ from __future__ import absolute_import # -# Copyright (C) 2015, 2016, 2019 Smithsonian Astrophysical Observatory +# Copyright (C) 2015, 2016, 2019, 2020 +# Smithsonian Astrophysical Observatory # # # This program is free software; you can redistribute it and/or modify @@ -28,7 +29,6 @@ backend_map = { 'pylab': 'plot_matplotlib', - 'chips': 'plot_chips', 'dummy': 'plot_dummy' } diff --git a/sherpa/astro/datastack/plot_backend/plot_chips.py b/sherpa/astro/datastack/plot_backend/plot_chips.py deleted file mode 100644 index 0923194392..0000000000 --- a/sherpa/astro/datastack/plot_backend/plot_chips.py +++ /dev/null @@ -1,183 +0,0 @@ -# -# Copyright (C) 2010, 2014, 2015 Smithsonian Astrophysical Observatory -# -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# - -""" -Plotting routines for the data stack module provided by ChIPS. - -""" - -import pychips -from sherpa.plot import chips_backend - -name = "chips_backend" - - -def initialize_backend(): - """Ensure that the plotting backend is initialized.""" - - # FIXME We need to make sure ChIPS is initialized. - # As a hack, we just call begin() and end() on the chips backend - # To make sure the backend is initialized before we start - # creating windows. - try: - chips_backend.begin() - finally: - chips_backend.end() - - -def initialize_plot(dataset, ids): - """Create the plot window or figure for the given dataset. - - Parameters - ---------- - dataset : str or int - The dataset. - ids : array_like - The identifier array from the DataStack object. - - See Also - -------- - select_plot - - """ - try: - pychips.add_window(['id', dataset['id']]) - except RuntimeError: - pass - pychips.current_window(str(dataset['id'])) - - -def select_plot(dataset, ids): - """Select the plot window or figure for the given dataset. - - The plot for this dataset is assumed to have been created. - - Parameters - ---------- - dataset : str or int - The dataset. - ids : array_like - The identifier array from the DataStack object. - - See Also - -------- - initialize_plot - - """ - pychips.set_current_window(dataset['id']) - - -def save_plot(*args): - """Save the current plot.""" - pychips.print_window(*args) - -# The original code provided matplotlib-only access to these -# functions. Now also provide ChIPS access too. - -plot_savefig = pychips.print_window -plot_xlabel = pychips.set_plot_xlabel -plot_ylabel = pychips.set_plot_ylabel -plot_title = pychips.set_plot_title - - -# It does not quite match the matplotlib API: -# - no support for the argument being a pair -# - does not return the new limits -# - active data range after calling this may not match -# ChIPS expectations, but okay for here -def plot_xlim(xmin=None, xmax=None): - """Set the limits of the X axis. - If no parameters are set, then return the current limits. - - Parameters - ---------- - xmin - If set, change the minimum value - xmax - If set, change the maximum value - """ - if xmin is None and xmax is None: - return pychips.get_plot_range()[:2] - - if xmin is None: - xmin = pychips.get_plot_range()[0] - - if xmax is None: - xmax = pychips.get_plot_range()[1] - - pychips.limits(pychips.X_AXIS, xmin=xmin, xmax=xmax) - return pychips.get_plot_range()[:2] - - -def plot_ylim(ymin=None, ymax=None): - """Set the limits of the Y axis. - If no parameters are set, then return the current limits. - - Parameters - ---------- - ymin - If set, change the minimum value - ymax - If set, change the maximum value - """ - return_function = lambda: pychips.get_plot_range()[2:] - - if ymin is None and ymax is None: - return return_function() - - if ymin is None: - ymin = pychips.get_plot_range()[2] - - if ymax is None: - ymax = pychips.get_plot_range()[3] - - pychips.limits(pychips.Y_AXIS, ymin=ymin, ymax=ymax) - return return_function() - - -def plot_set_xscale(scale): - """Change the scaling of the X axis. - - Parameters - ---------- - scale : 'log', 'lin', 'logarithmic', 'linear' - """ - lscale = scale.lower() - if lscale in ['log', 'logarithmic']: - pychips.log_scale(pychips.X_AXIS) - elif lscale in ['lin', 'linear']: - pychips.lin_scale(pychips.X_AXIS) - else: - raise ValueError("Unsupported axis scale: {0}".format(scale)) - - -def plot_set_yscale(scale): - """Change the scaling of the Y axis. - - Parameters - ---------- - scale : 'log', 'lin', 'logarithmic', 'linear' - """ - lscale = scale.lower() - if lscale in ['log', 'logarithmic']: - pychips.log_scale(pychips.Y_AXIS) - elif lscale in ['lin', 'linear']: - pychips.lin_scale(pychips.Y_AXIS) - else: - raise ValueError("Unsupported axis scale: {0}".format(scale)) diff --git a/sherpa/astro/ui/tests/test_astro_ui_plot.py b/sherpa/astro/ui/tests/test_astro_ui_plot.py index f3b15fe04f..eb77315411 100644 --- a/sherpa/astro/ui/tests/test_astro_ui_plot.py +++ b/sherpa/astro/ui/tests/test_astro_ui_plot.py @@ -1,5 +1,5 @@ # -# Copyright (C) 2019 Smithsonian Astrophysical Observatory +# Copyright (C) 2019, 2020 Smithsonian Astrophysical Observatory # # # This program is free software; you can redistribute it and/or modify @@ -34,9 +34,8 @@ from sherpa.astro import ui -# the chips plot tests mean that we can't test the plot instances -# (because of the mocking that the chips tests do) -# from sherpa.plot import DataPlot, FitPlot, ModelPlot +from sherpa.astro.plot import ARFPlot, BkgDataPlot, ModelHistogram, \ + SourcePlot from sherpa.utils.err import IdentifierErr from sherpa.utils.testing import requires_data, requires_fits, \ @@ -252,12 +251,6 @@ def setup_example_bkg_model(idval): """ -# The following tests do not check whether returned values are -# of the expected class instance, since the chips plot tests -# use a mock object and so mess-up simple "isinstance(x, ModelPlot)" -# checks. -# - @pytest.mark.usefixtures("clean_astro_ui") @pytest.mark.parametrize("idval", [None, 1, "one", 23]) def test_get_arf_plot(idval): @@ -270,6 +263,8 @@ def test_get_arf_plot(idval): else: ap = ui.get_arf_plot(idval) + assert isinstance(ap, ARFPlot) + assert ap.xlo == pytest.approx(_energies[:-1]) assert ap.xhi == pytest.approx(_energies[1:]) @@ -294,6 +289,8 @@ def test_get_bkg_plot(idval): else: bp = ui.get_bkg_plot(idval) + assert isinstance(bp, BkgDataPlot) + assert bp.x == pytest.approx(_data_chan) # normalise by exposure time and bin width, but bin width here @@ -376,6 +373,8 @@ def test_get_model_plot(idval): else: mp = ui.get_model_plot(idval) + assert isinstance(mp, ModelHistogram) + assert mp.xlo == pytest.approx(_data_chan) assert mp.xhi == pytest.approx(_data_chan + 1) @@ -462,6 +461,8 @@ def test_get_source_plot_energy(idval): ui.set_analysis(idval, 'energy') sp = ui.get_source_plot(idval) + assert isinstance(sp, SourcePlot) + assert sp.xlo == pytest.approx(_energies[:-1]) assert sp.xhi == pytest.approx(_energies[1:]) diff --git a/sherpa/astro/ui/tests/test_chips_unit.py b/sherpa/astro/ui/tests/test_chips_unit.py deleted file mode 100644 index c7ed062ab7..0000000000 --- a/sherpa/astro/ui/tests/test_chips_unit.py +++ /dev/null @@ -1,96 +0,0 @@ -# -# Copyright (C) 2016, 2018, 2019 Smithsonian Astrophysical Observatory -# -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -import pytest -from sherpa.utils.testing import requires_data, requires_fits -import importlib - - -def assert_chips_called(chips): - """ - Just make sure the mock is being called once. At this point we are not too - concerned about the correctness of the calls. We are assuming the code works. - - Parameters - ---------- - chips : the mock object backing the tests - """ - chips.lock.assert_any_call() - chips.unlock.assert_any_call() - - -@pytest.fixture -def chips(mock_chips): - return mock_chips[1] - - -@pytest.fixture(autouse=True) -def ui(mock_chips): - """ - Load and return the sherpa.astro.ui module - """ - from sherpa.astro import ui - - importlib.reload(ui) - return ui - - -@pytest.fixture(autouse=True) -def clean_up(request, ui): - def fin(): - ui.clean() - request.addfinalizer(fin) - - -@pytest.fixture(autouse=True) -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() - - -@requires_data -@requires_fits -@pytest.mark.parametrize("call, args", [ - ("model", ()), - ("arf", ()), - ("source", ()), - ("bkg", ()), - ("bkg_model", ()), - ("bkg_resid", ()), - ("bkg_ratio", ()), - ("bkg_delchi", ()), - ("bkg_chisqr", ()), - ("bkg_fit", ()), - ("bkg_source", ()), - ("energy_flux", ()), - ("photon_flux", ()), - ("bkg_fit_resid", ()), - ("bkg_fit_delchi", ()), - ("source_component", (1, "p")), - ("model_component", (1, "p")), - ("order", (1,)), -]) -def test_plot(call, args, chips, ui): - function = getattr(ui, "plot_" + call) - function(*args) - assert_chips_called(chips) diff --git a/sherpa/conftest.py b/sherpa/conftest.py index 57afd10407..212e1a503f 100644 --- a/sherpa/conftest.py +++ b/sherpa/conftest.py @@ -1,5 +1,6 @@ # -# Copyright (C) 2016, 2017, 2018, 2019 Smithsonian Astrophysical Observatory +# Copyright (C) 2016, 2017, 2018, 2019, 2020 +# Smithsonian Astrophysical Observatory # # # This program is free software; you can redistribute it and/or modify @@ -26,9 +27,6 @@ from sherpa.utils.testing import SherpaTestCase -import importlib -from unittest import mock - try: from astropy.io.fits.verify import VerifyWarning have_astropy = True @@ -285,65 +283,6 @@ def wrapped(arg): return wrapped -@pytest.fixture -def mock_chips(monkeypatch, tmpdir, request): - """ - Fixture for tests mocking chips - - Returns - ------- - The tuple (backend, mock_chips) - """ - - # First, inject a mock chips module in the backend. - chips = mock.MagicMock() - monkeypatch.setitem(sys.modules, name="pychips", value=chips) - - # figure out what IO module we can use - try: - import pycrates - io = "crates" - except ImportError: - io = "pyfits" # Even if this is not available, config code will fall back to dummy - - # Now, write a fake configuration file to a temporary location - config = tmpdir.mkdir("config").join("sherpa.rc") - config.write(""" -[options] -plot_pkg : chips -io_pkg : {} - """.format(io)) - - # Then, inject a function that returns the fake file - def get_config(): - return str(config) - import sherpa - monkeypatch.setattr(sherpa, name="get_config", value=get_config) - - # Force reload of sherpa modules that might have already read the configuration - from sherpa import plot - from sherpa.astro import plot as astro_plot - - importlib.reload(plot) - importlib.reload(astro_plot) - - # Force a reload, to make sure we always return a fresh instance, so we track the correct mock object - from sherpa.plot import chips_backend - importlib.reload(chips_backend) - - def fin(): - monkeypatch.undo() - importlib.reload(sherpa) - importlib.reload(plot) - importlib.reload(astro_plot) - importlib.reload(sherpa.all) - importlib.reload(sherpa.astro.all) # These are required because otherwise Python will not match imported classes. - - request.addfinalizer(fin) - - return chips_backend, chips - - def run_thread_function(name, scriptname, test_data_path): """Run a regression test from the sherpa-test-data submodule. diff --git a/sherpa/plot/chips_backend.py b/sherpa/plot/chips_backend.py deleted file mode 100644 index d44cb38ae1..0000000000 --- a/sherpa/plot/chips_backend.py +++ /dev/null @@ -1,589 +0,0 @@ -# -# Copyright (C) 2007, 2015, 2016, 2019 Smithsonian Astrophysical Observatory -# -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# - -import numpy -import pychips as chips -from sherpa.utils import get_keyword_defaults -from sherpa import get_config -from configparser import ConfigParser, NoSectionError - -config = ConfigParser() -config.read(get_config()) - -__all__ = ('clear_window', 'plot', 'histo', 'contour', 'point', 'set_subplot', - 'get_split_plot_defaults','get_confid_point_defaults', - 'get_plot_defaults','get_point_defaults', 'begin', 'end', - 'get_data_plot_defaults', 'get_model_plot_defaults', - 'get_fit_plot_defaults', 'get_resid_plot_defaults', - 'get_ratio_plot_defaults', 'get_contour_defaults', 'exceptions', - 'get_data_contour_defaults', 'get_model_contour_defaults', - 'get_fit_contour_defaults', 'get_resid_contour_defaults', - 'get_ratio_contour_defaults','get_confid_plot_defaults', - 'get_confid_contour_defaults', 'set_window_redraw', 'set_jointplot', - 'get_histo_defaults', 'get_model_histo_defaults', - 'get_component_plot_defaults', 'get_component_histo_defaults', - 'vline', 'hline', 'get_cdf_plot_defaults', 'get_scatter_plot_defaults', - 'get_latex_for_string') - - -name = 'chips' - - -_initialized = False # Set this True first time begin() is called - -def _chips_wrap(func, *args, **kwargs): - func(*args, **kwargs) - -def _set_window_redraw(redraw): - if chips.info_current() is not None: - if chips.info_current().find('Window') != -1: - chips.advanced.set_window_redraw(redraw) - - -def _clear_window(): - if chips.info_current() is not None: - if chips.info_current().find('Frame') != -1: - chips.erase() - else: - chips.add_frame() - - if chips.info() is None: - chips.add_window() - - -def _point(x, y, overplot=True, clearwindow=False, - style=chips.chips_plus, - color=None, - size=None, - angle=None, - fill=None): - - if (not overplot) and clearwindow: - _clear_window() - - chips.add_point(x, y) - - for var in ('style','color', 'size', 'angle', 'fill'): - val = locals()[var] - if val is not None: - if 'color' in var: - val = _check_hex_color(val) - getattr(chips.advanced, 'set_point_' + var)(val) - - -_attr_map = { - 'linecolor' : 'color', - 'linestyle' : 'style', - 'linewidth' : 'thickness', - } - -_linestyle_map = { - - 'noline' : chips.chips_noline, - 'solid' : chips.chips_solid, - 'dot' : chips.chips_shortdash, - 'dash' : chips.chips_longdash, - 'dotdash' : chips.chips_dotlongdash, - } - - -def _check_hex_color(val): - if type(val) in (str, numpy.string_) and val.startswith('0x'): - val = str(val).replace('0x','').rjust(6,'0') - return val - -def _vline(x, ymin=0, ymax=1, - linecolor=None, - linestyle=None, - linewidth=None, - overplot=False, clearwindow=True): - - if (not overplot) and clearwindow: - _clear_window() - - chips.add_vline(x) - - for var in ('linecolor', 'linestyle', 'linewidth'): - val = locals()[var] - if val is not None: - if 'color' in var: - val = _check_hex_color(val) - elif 'style' in var: - val = _linestyle_map[val] - getattr(chips.advanced, 'set_line_' + _attr_map[var])(val) - - -def _hline(y, xmin=0, xmax=1, - linecolor=None, - linestyle=None, - linewidth=None, - overplot=False, clearwindow=True): - - if (not overplot) and clearwindow: - _clear_window() - - chips.add_hline(y) - - for var in ('linecolor', 'linestyle', 'linewidth'): - val = locals()[var] - if val is not None: - if 'color' in var: - val = _check_hex_color(val) - elif 'style' in var: - val = _linestyle_map[val] - getattr(chips.advanced, 'set_line_' + _attr_map[var])(val) - - - - -def _plot(x, y, yerr=None, xerr=None, title=None, xlabel=None, ylabel=None, - overplot=False, clearwindow=True, - xerrorbars=False, - yerrorbars=False, - errstyle=None, - errcolor=None, - errthickness=None, - xlog=False, - ylog=False, - linestyle=chips.chips_solid, - linecolor=None, - symbolstyle=chips.chips_none, - symbolcolor=None, - symbolsize=None, - symbolfill=True, - linethickness=None, - xaxis=False, - ratioline=False): - - - if (not overplot) and clearwindow: - _clear_window() - - if yerrorbars and (yerr is not None) and xerrorbars and (xerr is not None): - xerr = xerr / 2. - chips.add_curve(x, y, (yerr, yerr, xerr, xerr) ) - elif yerrorbars and (yerr is not None): - chips.add_curve(x, y, yerr) - else: - chips.add_curve(x, y) - - for var in ('errstyle', 'errcolor', 'errthickness', 'linestyle', - 'linecolor', 'symbolstyle', 'symbolcolor', 'symbolsize', - 'symbolfill', 'linethickness'): - val = locals()[var] - if val is not None: - if 'color' in var: - val = _check_hex_color(val) - getattr(chips.advanced, 'set_curve_' + var)(val) - - if not overplot: - for log_axis, axis_id in zip((xlog, ylog), - (chips.X_AXIS, chips.Y_AXIS)): - if log_axis: - chips.log_scale(axis_id) - else: - chips.linear_scale(axis_id) - - if title: - ttl = title.replace('_', '\\_') - chips.set_plot_title(ttl) - if xlabel: - xlbl = xlabel.replace('_', '\\_') - chips.set_plot_xlabel(xlbl) - if ylabel: - ylbl = ylabel.replace('_', '\\_') - chips.set_plot_ylabel(ylbl) - - if xaxis: - chips.add_hline(0); - - if ratioline: - chips.add_hline(1); - - #chips.limits(chips.X_AXIS, 'AUTO', 'AUTO') - - -def _histogram(xlo, xhi, y, yerr=None, title=None, xlabel=None, ylabel=None, - overplot=False, clearwindow=True, - yerrorbars=False, - errstyle=None, - errcolor=None, - errthickness=None, - fillcolor=None, - fillopacity=None, - fillstyle=None, - xlog=False, - ylog=False, - linestyle=chips.chips_solid, - linecolor=None, - linethickness=None, - symbolangle=None, - symbolcolor=None, - symbolfill=None, - symbolsize=None, - symbolstyle=chips.chips_none): - - if (not overplot) and clearwindow: - _clear_window() - - if yerrorbars and yerr is not None: - chips.add_histogram(xlo, xhi, y, yerr) - else: - chips.add_histogram(xlo, xhi, y) - - for var in ('errstyle', 'errcolor', 'errthickness', - 'fillcolor', 'fillopacity', 'fillstyle', - 'linestyle', 'linecolor', 'linethickness', - 'symbolangle', 'symbolcolor', 'symbolfill', 'symbolsize', - 'symbolstyle'): - val = locals()[var] - if val is not None: - if 'color' in var: - val = _check_hex_color(val) - getattr(chips.advanced, 'set_histogram_' + var)(val) - - if not overplot: - for log_axis, axis_id in zip((xlog, ylog), - (chips.X_AXIS, chips.Y_AXIS)): - if log_axis: - chips.log_scale(axis_id) - else: - chips.linear_scale(axis_id) - - if title: - ttl = title.replace('_', '\\_') - chips.set_plot_title(ttl) - if xlabel: - xlbl = xlabel.replace('_', '\\_') - chips.set_plot_xlabel(xlbl) - if ylabel: - ylbl = ylabel.replace('_', '\\_') - chips.set_plot_ylabel(ylbl) - - #chips.limits(chips.X_AXIS, 'AUTO', 'AUTO') - - -def _contour(x0, x1, y, levels=None, title=None, xlabel=None, ylabel=None, - overcontour=False, clearwindow=True, - xlog=False, - ylog=False, - style=None, - color=None, - thickness=None, - axis_pad=0.05): - - if (not overcontour) and clearwindow: - _clear_window() - - # Catch NANs before sending to ChIPS - bad = list(numpy.where(numpy.isnan(y)==True)).pop(0) - bad_vals = numpy.array(y[bad]) - y[bad] = 0.0 - - if levels is None: - chips.add_contour(x0, x1, y) - else: - levels = numpy.asarray(levels, numpy.float_) - chips.add_contour(x0, x1, y, levels) - - y[bad] = bad_vals - - for var in ('style', 'color', 'thickness'): - val = locals()[var] - if val is not None: - if 'color' in var: - val = _check_hex_color(val) - getattr(chips.advanced, 'set_contour_' + var)(val) - - chips.advanced.set_axis_pad(axis_pad) - - chips.set_data_aspect_ratio() - chips.limits(chips.X_AXIS, x0.min(), x0.max()) - chips.limits(chips.Y_AXIS, x1.min(), x1.max()) - - if not overcontour: - for log_axis, axis_id in zip((xlog, ylog), - (chips.X_AXIS, chips.Y_AXIS)): - if log_axis: - chips.log_scale(axis_id) - else: - chips.linear_scale(axis_id) - - if title: - ttl = title.replace('_', '\\_') - chips.set_plot_title(ttl) - if xlabel: - xlbl = xlabel.replace('_', '\\_') - chips.set_plot_xlabel(xlbl) - if ylabel: - ylbl = ylabel.replace('_', '\\_') - chips.set_plot_ylabel(ylbl) - - -def _set_subplot(row, col, nrows, ncols, clearaxes=True, - xgap=0.18, - ygap=0.18): - - chips.add_plot() - chips.grid_objects(ncols, nrows, xgap, ygap) - - -def _set_jointplot(row, col, nrows, ncols, clearaxes=True, - top=1, - ratio=2): - - # FIXME: misuse of kwarg clearaxes - if not clearaxes: - chips.strip_chart(nrows*ncols) - chips.adjust_grid_yrelsize(top,ratio) - else: - chips.set_current_plot('plot2') - -def init(): - # This function now a no-op; structure kept in case - # we want init to do something in future. - pass - -def begin(): - global _initialized - - chips.lock() - chips.advanced.open_undo_buffer() - if _initialized is False: - try: - overrides = config.items('chips') - for item in overrides: - chips.set_preference(item[0], item[1]) - # OL: No apparent reason to call add_window() here. - # ChIPS is smart enough to open a window if none are available, - # plus this code only gets executed if the user has a [chips] section in sherpa.rc - # which is the exception rather than the rule. - # chips.add_window() # Have Sherpa talk to its own - # chips window - except NoSectionError: - chips.unlock() - except: - chips.unlock() - raise - _initialized = True - -def end(): - # Don't need to call redraw here ourselves, the - # ChIPS undo buffer does what we need. - chips.advanced.close_undo_buffer() - chips.unlock() - -def exceptions(): - chips.advanced.discard_undo_buffer() - chips.erase() - chips.unlock() - -def clear_window(*args, **kwargs): - _chips_wrap( _clear_window, *args, **kwargs) - - -def set_window_redraw(*args, **kwargs): - _chips_wrap( _set_window_redraw, *args, **kwargs) - - -def point(*args, **kwargs): - _chips_wrap(_point, *args, **kwargs) - -def vline(*args, **kwargs): - _chips_wrap(_vline, *args, **kwargs) - -def hline(*args, **kwargs): - _chips_wrap(_hline, *args, **kwargs) - -def plot(*args, **kwargs): - _chips_wrap(_plot, *args, **kwargs) - - -def histo(*args, **kwargs): - _chips_wrap(_histogram, *args, **kwargs) - - -def contour(*args, **kwargs): - _chips_wrap(_contour, *args, **kwargs) - - -def set_subplot(*args, **kwargs): - _chips_wrap(_set_subplot, *args, **kwargs) - - -def set_jointplot(*args, **kwargs): - _chips_wrap(_set_jointplot, *args, **kwargs) - - -def get_split_plot_defaults(): - return get_keyword_defaults(_set_subplot, 3) - - -def get_plot_defaults(): - return get_keyword_defaults(_plot, 7) - - -def get_point_defaults(): - return get_keyword_defaults(_point, 2) - - -def get_histo_defaults(): - return get_keyword_defaults(_histogram, 6) - - -def get_confid_point_defaults(): - d = get_point_defaults() - d['style'] = chips.chips_plus - d['size'] = 7 - return d - - -def get_data_plot_defaults(): - d = get_plot_defaults() - - d['yerrorbars'] = True - d['errstyle'] = 'line' - d['linestyle'] = chips.chips_noline - d['symbolstyle'] = chips.chips_circle - d['symbolsize'] = 3 - d['symbolfill'] = False - - return d - - -def get_model_plot_defaults(): - d = get_plot_defaults() - - d['linestyle'] = chips.chips_solid - d['linethickness'] = 3 - d['linecolor'] = 'red' - d['symbolstyle'] = chips.chips_none - - return d - - -def get_confid_plot_defaults(): - d = get_plot_defaults() - - d['linestyle'] = chips.chips_solid - d['symbolstyle'] = chips.chips_none - d['linethickness'] = 3 - d['linecolor'] = 'skyblue' - return d - - -def get_fit_plot_defaults(): - return {} - - -def get_resid_plot_defaults(): - d = get_data_plot_defaults() - d['xerrorbars'] = True - d['errstyle'] = 'line' - d['symbolstyle'] = chips.chips_diamond - d['xaxis'] = True - d['symbolsize'] = 3 - return d - - -def get_ratio_plot_defaults(): - d = get_data_plot_defaults() - d['xerrorbars'] = True - d['errstyle'] = 'line' - d['symbolstyle'] = chips.chips_diamond - d['ratioline'] = True - d['symbolsize'] = 3 - return d - - -def get_contour_defaults(): - return get_keyword_defaults(contour, 6) - -get_data_contour_defaults = get_contour_defaults - -def get_model_contour_defaults(): - d = get_contour_defaults() - d['style'] = None - d['color'] = 'red' - d['thickness'] = 3 - return d - -def get_confid_contour_defaults(): - d = get_contour_defaults() - d['style'] = None - d['color'] = 'skyblue' - d['thickness'] = 3 - d['axis_pad'] = 0.0 - return d - - -def get_fit_contour_defaults(): - return {} - - -get_resid_contour_defaults = get_data_contour_defaults -get_ratio_contour_defaults = get_data_contour_defaults - -def get_model_histo_defaults(): - d = get_histo_defaults() -# d['linestyle'] = chips.chips_solid - d['linethickness'] = 2 - d['linecolor'] = 'red' - - return d - -def get_component_plot_defaults(): - d = get_model_plot_defaults() - d['linecolor'] = 'orange' - return d - -def get_component_histo_defaults(): - d = get_model_histo_defaults() - d['linecolor'] = 'orange' - return d - -def get_cdf_plot_defaults(): - d = get_model_plot_defaults() - d['linecolor'] = 'red' - return d - -def get_scatter_plot_defaults(): - d = get_data_plot_defaults() - d['symbolsize'] = 1 - d['symbolfill'] = True - d['yerrorbars'] = False - return d - -def get_latex_for_string(txt): - """Convert to LaTeX form for the ChIPS back end. - - Parameters - ---------- - txt : str - The text component in LaTeX form (e.g. r'\alpha^2'). It - should not contain any non-LaTeX content. - - Returns - ------- - latex : str - The input text (i.e. no change). - - """ - - return txt diff --git a/sherpa/sherpa-standalone.rc b/sherpa/sherpa-standalone.rc index fdc88e349b..1fb822ee29 100644 --- a/sherpa/sherpa-standalone.rc +++ b/sherpa/sherpa-standalone.rc @@ -1,6 +1,6 @@ -# SHERPA_VERSION 4.10.0 +# SHERPA_VERSION 4.12.1 [options] -# Plotting packages available- pylab, chips +# Plotting packages available- pylab plot_pkg : pylab # IO packages available- pyfits, crates @@ -46,14 +46,3 @@ arraylength: 1000000 # Fewer than 2 will turn off parallel processing. numcores : None -[chips] -# If the plotting package is chips, set Sherpa-specific -# preferences here. If plotting package is anything else, -# this section is completely ignored. These preferences -# go into effect the first time a Sherpa plot function -# is called (*not* when Sherpa is started; chips is not -# imported until the first plot is made). - -window.height : 6 -window.width : 8 -window.units : inches diff --git a/sherpa/sherpa.rc b/sherpa/sherpa.rc index 6e23c4e224..f7e912c104 100644 --- a/sherpa/sherpa.rc +++ b/sherpa/sherpa.rc @@ -1,6 +1,6 @@ -# SHERPA_VERSION 4.10.0 +# SHERPA_VERSION 4.12.1 [options] -# Plotting packages available- pylab, chips +# Plotting packages available- pylab plot_pkg : pylab # IO packages available- pyfits, crates @@ -46,14 +46,3 @@ arraylength: 1000000 # Fewer than 2 will turn off parallel processing. numcores : None -[chips] -# If the plotting package is chips, set Sherpa-specific -# preferences here. If plotting package is anything else, -# this section is completely ignored. These preferences -# go into effect the first time a Sherpa plot function -# is called (*not* when Sherpa is started; chips is not -# imported until the first plot is made). - -window.height : 6 -window.width : 8 -window.units : inches diff --git a/sherpa/ui/tests/test_ui_plot.py b/sherpa/ui/tests/test_ui_plot.py index dc795467cf..6c3a7ae176 100644 --- a/sherpa/ui/tests/test_ui_plot.py +++ b/sherpa/ui/tests/test_ui_plot.py @@ -1,5 +1,5 @@ # -# Copyright (C) 2019 Smithsonian Astrophysical Observatory +# Copyright (C) 2019, 2020 Smithsonian Astrophysical Observatory # # # This program is free software; you can redistribute it and/or modify @@ -24,8 +24,7 @@ from sherpa import ui -# the chips plot tests mean that we can't test the plot instances -# from sherpa.plot import DataPlot, FitPlot, ModelPlot +from sherpa.plot import DataPlot, FitPlot, ModelPlot from sherpa.stats import Chi2Gehrels from sherpa.utils.testing import requires_plotting @@ -100,15 +99,9 @@ def test_get_fit_plot(idval): else: f = ui.get_fit_plot(idval) - # Should we be checking exact class? - # - # No - because the mock_chips pytest routine redefines these - # classes and so makes the test fail (or at least that's my - # assumption). - # - # assert isinstance(f, FitPlot) - # assert isinstance(f.dataplot, DataPlot) - # assert isinstance(f.modelplot, ModelPlot) + assert isinstance(f, FitPlot) + assert isinstance(f.dataplot, DataPlot) + assert isinstance(f.modelplot, ModelPlot) dp = f.dataplot mp = f.modelplot diff --git a/sherpa/utils/testing.py b/sherpa/utils/testing.py index 71d592e18b..49e1d7a913 100644 --- a/sherpa/utils/testing.py +++ b/sherpa/utils/testing.py @@ -1,5 +1,5 @@ # -# Copyright (C) 2017 Smithsonian Astrophysical Observatory +# Copyright (C) 2017, 2020 Smithsonian Astrophysical Observatory # # # This program is free software; you can redistribute it and/or modify @@ -208,7 +208,7 @@ def requires_plotting(test_function): """ Decorator for test functions requiring a plotting library. """ - packages = ('pylab', 'pychips') + packages = ('pylab', ) msg = "plotting backend required" return requires_package(msg, *packages)(test_function)