Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move Python export tests from glue-qt to here #2524

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions glue/viewers/histogram/tests/test_python_export.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from astropy.utils import NumpyRNGContext

from glue.core import Data, DataCollection
from glue.core.application_base import Application
from glue.viewers.histogram.viewer import SimpleHistogramViewer
from glue.viewers.matplotlib.tests.test_python_export import BaseTestExportPython, random_with_nan


class TestExportPython(BaseTestExportPython):

def setup_method(self, method):

with NumpyRNGContext(12345):
self.data = Data(**dict((name, random_with_nan(100, nan_index=idx + 1)) for idx, name in enumerate('abcdefgh')))
self.data_collection = DataCollection([self.data])
self.app = Application(self.data_collection)
self.viewer = self.app.new_data_viewer(SimpleHistogramViewer)
self.viewer.add_data(self.data)
self.viewer.state.x_att = self.data.id['a']

def teardown_method(self, method):
self.viewer = None
self.app = None

def test_simple(self, tmpdir):
self.assert_same(tmpdir)

def test_simple_visual(self, tmpdir):
self.viewer.state.layers[0].color = 'blue'
self.viewer.state.layers[0].alpha = 0.5
self.assert_same(tmpdir)

def test_simple_visual_legend(self, tmpdir):
self.viewer.state.legend.visible = True
self.viewer.state.layers[0].color = 'blue'
self.viewer.state.layers[0].alpha = 0.5
self.assert_same(tmpdir)

def test_cumulative(self, tmpdir):
self.viewer.state.cumulative = True
self.assert_same(tmpdir)

def test_normalize(self, tmpdir):
self.viewer.state.normalize = True
self.assert_same(tmpdir)

def test_subset(self, tmpdir):
self.data_collection.new_subset_group('mysubset', self.data.id['a'] > 0.5)
self.assert_same(tmpdir)

def test_subset_legend(self, tmpdir):
self.viewer.state.legend.visible = True
self.data_collection.new_subset_group('mysubset', self.data.id['a'] > 0.5)
self.assert_same(tmpdir)

def test_empty(self, tmpdir):
self.viewer.state.x_min = 10
self.viewer.state.x_max = 11
self.viewer.state.hist_x_min = 10
self.viewer.state.hist_x_max = 11
self.assert_same(tmpdir)
124 changes: 124 additions & 0 deletions glue/viewers/image/tests/test_python_export.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import pytest
import numpy as np
import matplotlib.pyplot as plt
from astropy.utils import NumpyRNGContext
from astropy.wcs import WCS

from glue.core import Data, DataCollection
from glue.core.coordinates import AffineCoordinates
from glue.core.application_base import Application
from glue.viewers.image.viewer import SimpleImageViewer
from glue.viewers.matplotlib.tests.test_python_export import BaseTestExportPython


class TestExportPython(BaseTestExportPython):

def setup_method(self, method):

with NumpyRNGContext(12345):
self.data = Data(cube=np.random.random((30, 50, 20)))
# Create data versions with WCS and affine coordinates
matrix = np.array([[2, 3, 0, -1], [1, 2, 0, 2], [0, 0, 1, -2], [0, 0, 0, 1]])
affine = AffineCoordinates(matrix, units=['Mm', 'Mm', 'km'], labels=['xw', 'yw', 'zw'])

self.data_wcs = Data(label='cube', cube=self.data['cube'], coords=WCS(naxis=3))
self.data_affine = Data(label='cube', cube=self.data['cube'], coords=affine)
self.data_collection = DataCollection([self.data, self.data_wcs, self.data_affine])
self.app = Application(self.data_collection)
self.viewer = self.app.new_data_viewer(SimpleImageViewer)
self.viewer.add_data(self.data)
# FIXME: On some platforms, using an integer label size
# causes some of the labels to be non-deterministically
# shifted by one pixel, so we pick a non-round font size
# to avoid this.
self.viewer.state.x_ticklabel_size = 8.21334111
self.viewer.state.y_ticklabel_size = 8.21334111

def teardown_method(self, method):
self.viewer = None
self.app = None

def assert_same(self, tmpdir, tol=0.1):
BaseTestExportPython.assert_same(self, tmpdir, tol=tol)

def viewer_load(self, coords):
if coords is not None:
self.viewer.add_data(getattr(self, f'data_{coords}'))
self.viewer.remove_data(self.data)

@pytest.mark.parametrize('coords', [None, 'wcs', 'affine'])
def test_simple(self, tmpdir, coords):
self.viewer_load(coords)
self.assert_same(tmpdir)

@pytest.mark.parametrize('coords', [None, 'wcs', 'affine'])
def test_simple_legend(self, tmpdir, coords):
self.viewer_load(coords)
self.viewer.state.show_legend = True
self.assert_same(tmpdir)

@pytest.mark.parametrize('coords', [None, 'wcs', 'affine'])
def test_simple_att(self, tmpdir, coords):
self.viewer_load(coords)
self.viewer.state.x_att = self.viewer.state.reference_data.pixel_component_ids[1]
self.viewer.state.y_att = self.viewer.state.reference_data.pixel_component_ids[0]
if coords == 'affine':
pytest.xfail('Known issue with axis label rendering')
self.assert_same(tmpdir)

@pytest.mark.parametrize('coords', [None, 'wcs', 'affine'])
def test_simple_visual(self, tmpdir, coords):
self.viewer_load(coords)
self.viewer.state.legend.visible = True
self.viewer.state.layers[0].cmap = plt.cm.RdBu
self.viewer.state.layers[0].v_min = 0.2
self.viewer.state.layers[0].v_max = 0.8
self.viewer.state.layers[0].stretch = 'sqrt'
self.viewer.state.layers[0].stretch = 'sqrt'
self.viewer.state.layers[0].contrast = 0.9
self.viewer.state.layers[0].bias = 0.6
self.assert_same(tmpdir)

@pytest.mark.parametrize('coords', [None, 'wcs', 'affine'])
def test_slice(self, tmpdir, coords):
self.viewer_load(coords)
self.viewer.state.x_att = self.viewer.state.reference_data.pixel_component_ids[1]
self.viewer.state.y_att = self.viewer.state.reference_data.pixel_component_ids[0]
self.viewer.state.slices = (2, 3, 4)
if coords == 'affine':
pytest.xfail('Known issue with axis label rendering')
self.assert_same(tmpdir)

@pytest.mark.parametrize('coords', [None, 'wcs', 'affine'])
def test_aspect(self, tmpdir, coords):
self.viewer_load(coords)
self.viewer.state.aspect = 'auto'
self.assert_same(tmpdir)

@pytest.mark.parametrize('coords', [None, 'wcs', 'affine'])
def test_subset(self, tmpdir, coords):
self.viewer_load(coords)
self.data_collection.new_subset_group('mysubset', self.data.id['cube'] > 0.5)
self.assert_same(tmpdir)

@pytest.mark.parametrize('coords', [None, 'wcs', 'affine'])
def test_subset_legend(self, tmpdir, coords):
self.viewer_load(coords)
self.data_collection.new_subset_group('mysubset',
self.viewer.state.reference_data.id['cube'] > 0.5)
self.viewer.state.legend.visible = True
self.assert_same(tmpdir, tol=0.15) # transparency and such

@pytest.mark.parametrize('coords', [None, 'wcs', 'affine'])
def test_subset_slice(self, tmpdir, coords):
self.viewer_load(coords)
self.data_collection.new_subset_group('mysubset', self.data.id['cube'] > 0.5)
self.test_slice(tmpdir, coords)

@pytest.mark.parametrize('coords', [None, 'wcs', 'affine'])
def test_subset_transposed(self, tmpdir, coords):
self.viewer_load(coords)
self.data_collection.new_subset_group('mysubset', self.data.id['cube'] > 0.5)
self.viewer.state.x_att = self.data.pixel_component_ids[0]
self.viewer.state.y_att = self.data.pixel_component_ids[1]
self.assert_same(tmpdir)
62 changes: 62 additions & 0 deletions glue/viewers/matplotlib/tests/test_python_export.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import os
import sys
import pytest
import subprocess

from glue.config import settings

import numpy as np

from matplotlib.testing.compare import compare_images

__all__ = ['random_with_nan', 'BaseTestExportPython']


def random_with_nan(nsamples, nan_index):
x = np.random.random(nsamples)
x[nan_index] = np.nan
return x


class BaseTestExportPython:

def assert_same(self, tmpdir, tol=0.1):

os.chdir(tmpdir.strpath)

expected = tmpdir.join('expected.png').strpath
script = tmpdir.join('actual.py').strpath
actual = tmpdir.join('glue_plot.png').strpath

self.viewer.axes.figure.savefig(expected)

self.viewer.export_as_script(script)
subprocess.call([sys.executable, script])

msg = compare_images(expected, actual, tol=tol)

if msg:

from base64 import b64encode

print("SCRIPT:")
with open(script, 'r') as f:
print(f.read())

print("EXPECTED:")
with open(expected, 'rb') as f:
print(b64encode(f.read()).decode())

print("ACTUAL:")
with open(actual, 'rb') as f:
print(b64encode(f.read()).decode())

pytest.fail(msg, pytrace=False)

def test_color_settings(self, tmpdir):
settings.FOREGROUND_COLOR = '#a51d2d'
settings.BACKGROUND_COLOR = '#99c1f1'
self.viewer._update_appearance_from_settings()
self.assert_same(tmpdir)
settings.reset_defaults()
self.viewer._update_appearance_from_settings()
87 changes: 87 additions & 0 deletions glue/viewers/profile/tests/test_python_export.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
from astropy.utils import NumpyRNGContext

from glue.core import Data, DataCollection
from glue.core.application_base import Application
from glue.viewers.profile.viewer import SimpleProfileViewer
from glue.viewers.matplotlib.tests.test_python_export import BaseTestExportPython, random_with_nan
from glue.viewers.profile.tests.test_state import SimpleCoordinates


class TestExportPython(BaseTestExportPython):

def setup_method(self, method):

self.data = Data(label='d1')
self.data.coords = SimpleCoordinates()
with NumpyRNGContext(12345):
self.data['x'] = random_with_nan(48, 5).reshape((6, 4, 2))
self.data['y'] = random_with_nan(48, 12).reshape((6, 4, 2))
self.data_collection = DataCollection([self.data])
self.app = Application(self.data_collection)
self.viewer = self.app.new_data_viewer(SimpleProfileViewer)
self.viewer.add_data(self.data)
# Make legend location deterministic
self.viewer.state.legend.location = 'lower left'

def teardown_method(self, method):
self.viewer = None
self.app = None

def test_simple(self, tmpdir):
self.assert_same(tmpdir)

def test_simple_legend(self, tmpdir):
self.viewer.state.legend.visible = True
self.assert_same(tmpdir)

def test_color(self, tmpdir):
self.viewer.state.layers[0].color = '#ac0567'
self.assert_same(tmpdir)

def test_linewidth(self, tmpdir):
self.viewer.state.layers[0].linewidth = 7.25
self.assert_same(tmpdir)

def test_max(self, tmpdir):
self.viewer.state.function = 'maximum'
self.assert_same(tmpdir)

def test_min(self, tmpdir):
self.viewer.state.function = 'minimum'
self.assert_same(tmpdir)

def test_mean(self, tmpdir):
self.viewer.state.function = 'mean'
self.assert_same(tmpdir)

def test_median(self, tmpdir):
self.viewer.state.function = 'median'
self.assert_same(tmpdir)

def test_sum(self, tmpdir):
self.viewer.state.function = 'sum'
self.assert_same(tmpdir)

def test_normalization(self, tmpdir):
self.viewer.state.normalize = True
self.assert_same(tmpdir)

def test_subset(self, tmpdir):
self.viewer.state.function = 'mean'
self.data_collection.new_subset_group('mysubset', self.data.id['x'] > 0.25)
self.assert_same(tmpdir)

def test_subset_legend(self, tmpdir):
self.viewer.state.legend.visible = True
self.viewer.state.function = 'mean'
self.viewer.state.layers[0].linewidth = 7.25
self.data_collection.new_subset_group('mysubset', self.data.id['x'] > 0.25)
self.assert_same(tmpdir)

def test_xatt(self, tmpdir):
self.viewer.x_att = self.data.pixel_component_ids[1]
self.assert_same(tmpdir)

def test_profile_att(self, tmpdir):
self.viewer.layers[0].state.attribute = self.data.id['y']
self.assert_same(tmpdir)
Loading
Loading