Skip to content

Commit

Permalink
TST: migrate answer-tests image tests to pytest-mpl
Browse files Browse the repository at this point in the history
  • Loading branch information
neutrinoceros committed Feb 22, 2023
1 parent e3a95cd commit dde193d
Show file tree
Hide file tree
Showing 27 changed files with 1,180 additions and 1,089 deletions.
1 change: 1 addition & 0 deletions nose_answer.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ with-answer-testing=1
with-timer=1
with-xunit=1
xunit-file=answer_nosetests.xml
ignore-files=(test_raw_field_slices\.py)
8 changes: 8 additions & 0 deletions nose_ignores.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,26 @@
--ignore-file=test_firefly\.py
--ignore-file=test_geometries\.py
--ignore-file=test_glue\.py
--ignore-file=test_image_comp_2D_plots\.py
--ignore-file=test_image_comp_geo\.py
--ignore-file=test_invalid_origin\.py
--ignore-file=test_line_annotation_unit\.py
--ignore-file=test_line_plots\.py
--ignore-file=test_load_archive\.py
--ignore-file=test_load_errors\.py
--ignore-file=test_load_sample\.py
--ignore-file=test_mesh_render\.py
--ignore-file=test_mesh_slices\.py
--ignore-file=test_normal_plot_api\.py
--ignore-file=test_on_demand_imports\.py
--ignore-file=test_outputs_pytest\.py
--ignore-file=test_profile_plots\.py
--ignore-file=test_raw_field_slices\.py
--ignore-file=test_registration\.py
--ignore-file=test_sanitize_center\.py
--ignore-file=test_save\.py
--ignore-file=test_set_zlim\.py
--ignore-file=test_stream_particles\.py
--ignore-file=test_stream_stretched\.py
--ignore-file=test_version\.py
--ignore-file=test_vr_orientation\.py
46 changes: 8 additions & 38 deletions tests/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ answer_tests:
- yt/visualization/tests/test_particle_plot.py:test_particle_projection_answers
- yt/visualization/tests/test_particle_plot.py:test_particle_projection_filter
- yt/visualization/tests/test_particle_plot.py:test_particle_phase_answers
- yt/visualization/tests/test_raw_field_slices.py:test_raw_field_slices
- yt/visualization/tests/test_callbacks.py:test_axis_manipulations

local_tipsy_008: # PR 2909
Expand All @@ -121,24 +120,6 @@ answer_tests:
- yt/fields/tests/test_xray_fields.py:test_d9p_cloudy
- yt/fields/tests/test_xray_fields.py:test_d9p_cloudy_local

local_unstructured_012:
- yt/visualization/volume_rendering/tests/test_mesh_render.py:test_composite_mesh_render
- yt/visualization/volume_rendering/tests/test_mesh_render.py:test_composite_mesh_render_pyembree
- yt/visualization/volume_rendering/tests/test_mesh_render.py:test_hex20_render
- yt/visualization/volume_rendering/tests/test_mesh_render.py:test_hex20_render_pyembree
- yt/visualization/volume_rendering/tests/test_mesh_render.py:test_hex8_render
- yt/visualization/volume_rendering/tests/test_mesh_render.py:test_hex8_render_pyembree
- yt/visualization/volume_rendering/tests/test_mesh_render.py:test_perspective_mesh_render
- yt/visualization/volume_rendering/tests/test_mesh_render.py:test_perspective_mesh_render_pyembree
- yt/visualization/volume_rendering/tests/test_mesh_render.py:test_surface_mesh_render
- yt/visualization/volume_rendering/tests/test_mesh_render.py:test_surface_mesh_render_pyembree
- yt/visualization/volume_rendering/tests/test_mesh_render.py:test_tet10_render
- yt/visualization/volume_rendering/tests/test_mesh_render.py:test_tet10_render_pyembree
- yt/visualization/volume_rendering/tests/test_mesh_render.py:test_tet4_render
- yt/visualization/volume_rendering/tests/test_mesh_render.py:test_tet4_render_pyembree
- yt/visualization/volume_rendering/tests/test_mesh_render.py:test_wedge6_render
- yt/visualization/volume_rendering/tests/test_mesh_render.py:test_wedge6_render_pyembree

local_boxlib_011:
- yt/frontends/boxlib/tests/test_outputs.py:test_radadvect
- yt/frontends/boxlib/tests/test_outputs.py:test_radtube
Expand Down Expand Up @@ -178,31 +159,12 @@ answer_tests:
local_axialpix_009: # PR 3818
- yt/geometry/coordinates/tests/test_axial_pixelization.py:test_axial_pixelization

local_cylindrical_background_016: # PR 4132
- yt/geometry/coordinates/tests/test_cylindrical_coordinates.py:test_noise_plots

local_spherical_background_010: # PR 4132
- yt/geometry/coordinates/tests/test_spherical_coordinates.py:test_noise_plots

#local_particle_trajectory_001:
# - yt/data_objects/tests/test_particle_trajectories.py

local_nc4_cm1_002: # PR 2176, 2998
- yt/frontends/nc4_cm1/tests/test_outputs.py:test_cm1_mesh_fields

local_norm_api_009: # PR 4132
- yt/visualization/tests/test_norm_api_lineplot.py:test_lineplot_set_axis_properties
- yt/visualization/tests/test_norm_api_profileplot.py:test_profileplot_set_axis_properties
- yt/visualization/tests/test_norm_api_custom_norm.py:test_sliceplot_custom_norm
- yt/visualization/tests/test_norm_api_set_background_color.py:test_sliceplot_set_background_color
- yt/visualization/tests/test_norm_api_phaseplot_set_colorbar_implicit.py:test_phaseplot_set_colorbar_properties_implicit
- yt/visualization/tests/test_norm_api_phaseplot_set_colorbar_explicit.py:test_phaseplot_set_colorbar_properties_explicit
- yt/visualization/tests/test_norm_api_particleplot.py:test_particleprojectionplot_set_colorbar_properties
- yt/visualization/tests/test_norm_api_inf_zlim.py:test_inf_and_finite_values_zlim

local_cf_radial_002: # PR 1990
- yt/frontends/cf_radial/tests/test_outputs.py:test_cfradial_grid_field_values

other_tests:
unittests:
# keep in sync with nose_ignores.txt
Expand All @@ -220,21 +182,29 @@ other_tests:
- "--ignore-file=test_firefly\\.py"
- "--ignore-file=test_geometries\\.py"
- "--ignore-file=test_glue\\.py"
- "--ignore-file=test_image_comp_2D_plots\\.py"
- "--ignore-file=test_image_comp_geo\\.py"
- "--ignore-file=test_invalid_origin\\.py"
- "--ignore-file=test_line_annotation_unit\\.py"
- "--ignore-file=test_line_plots\\.py"
- "--ignore-file=test_load_archive\\.py"
- "--ignore-file=test_load_errors\\.py"
- "--ignore-file=test_load_sample\\.py"
- "--ignore-file=test_mesh_render\\.py"
- "--ignore-file=test_mesh_slices\\.py"
- "--ignore-file=test_normal_plot_api\\.py"
- "--ignore-file=test_on_demand_imports\\.py"
- "--ignore-file=test_outputs_pytest\\.py"
- "--ignore-file=test_profile_plots\\.py"
- "--ignore-file=test_raw_field_slices\\.py"
- "--ignore-file=test_registration\\.py"
- "--ignore-file=test_sanitize_center\\.py"
- "--ignore-file=test_save\\.py"
- "--ignore-file=test_set_zlim\\.py"
- "--ignore-file=test_stream_particles\\.py"
- "--ignore-file=test_stream_stretched\\.py"
- "--ignore-file=test_version\\.py"
- "--ignore-file=test_vr_orientation\\.py"
- "--exclude-test=yt.frontends.gdf.tests.test_outputs.TestGDF"
- "--exclude-test=yt.frontends.adaptahop.tests.test_outputs"
- "--exclude-test=yt.frontends.stream.tests.test_stream_particles.test_stream_non_cartesian_particles"
Expand Down
2 changes: 1 addition & 1 deletion yt/fields/tests/test_field_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ def test_field_access():
oap = ProjectionPlot(ds, [1, 1, 1], field)

for plot_object in [s, oas, p, oap, prof, phase]:
plot_object._setup_plots()
plot_object.render()
if hasattr(plot_object, "_frb"):
plot_object._frb[field]
2 changes: 1 addition & 1 deletion yt/frontends/stream/tests/test_stream_hexahedral.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,5 @@ def test_stream_hexahedral():
assert_almost_equal(dd[("index", "dz")].to_ndarray(), 1.0 / Nz)

s = SlicePlot(ds, "x", "random_field")
s._setup_plots()
s.render()
s.frb[("stream", "random_field")]
23 changes: 1 addition & 22 deletions yt/geometry/coordinates/tests/test_cylindrical_coordinates.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

import numpy as np

from yt import SlicePlot
from yt.testing import add_noise_fields, assert_almost_equal, assert_equal, fake_amr_ds
from yt.utilities.answer_testing.framework import GenericImageTest
from yt.testing import assert_almost_equal, assert_equal, fake_amr_ds

# Our canonical tests are that we can access all of our fields and we can
# compute our volume correctly.
Expand Down Expand Up @@ -33,22 +31,3 @@ def test_cylindrical_coordinates():
assert_equal(
dd["index", "path_element_theta"], dd["index", "r"] * dd["index", "dtheta"]
)


def test_noise_plots():
ds = fake_amr_ds(geometry="cylindrical")
add_noise_fields(ds)

def create_image(filename_prefix):
fields = ["noise%d" % i for i in range(4)]

p = SlicePlot(ds, "z", fields)
p.save(f"{filename_prefix}_log")

p.set_log("all", False)
p.save(f"{filename_prefix}_lin")

test = GenericImageTest(ds, create_image, 12)
test.prefix = "test_noise_plot_lin"
test_noise_plots.__name__ = test.description
yield test
21 changes: 1 addition & 20 deletions yt/geometry/coordinates/tests/test_spherical_coordinates.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

import numpy as np

from yt import SlicePlot
from yt.testing import add_noise_fields, assert_almost_equal, assert_equal, fake_amr_ds
from yt.utilities.answer_testing.framework import GenericImageTest
from yt.testing import assert_almost_equal, assert_equal, fake_amr_ds

# Our canonical tests are that we can access all of our fields and we can
# compute our volume correctly.
Expand Down Expand Up @@ -40,20 +38,3 @@ def test_spherical_coordinates():
dd["index", "path_element_phi"],
(dd["index", "r"] * dd["index", "dphi"] * np.sin(dd["index", "theta"])),
)


def test_noise_plots():
ds = fake_amr_ds(geometry="spherical")
add_noise_fields(ds)

def create_image(filename_prefix):
fields = ["noise%d" % i for i in range(4)]

for normal in ("phi", "theta"):
p = SlicePlot(ds, normal, fields)
p.save(f"{filename_prefix}_{normal}")

test = GenericImageTest(ds, create_image, 12)
test.prefix = "test_noise_plot_lin"
test_noise_plots.__name__ = test.description
yield test
71 changes: 8 additions & 63 deletions yt/utilities/answer_testing/framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
Purpose: Contains answer tests that are used by yt's various frontends
"""
import contextlib
import glob
import hashlib
import logging
import os
Expand Down Expand Up @@ -341,6 +340,13 @@ def data_dir_load(ds_fn, cls=None, args=None, kwargs=None):
return ds


def data_dir_load_v2(fn, *args, **kwargs):
# a version of data_dir_load without type flexibility
# that is simpler to reason about
path = os.path.join(ytcfg.get("yt", "test_data_dir"), fn)
return load(path, *args, **kwargs)


def sim_dir_load(sim_fn, path=None, sim_type="Enzo", find_outputs=False):
if path is None and not os.path.exists(sim_fn):
raise OSError
Expand Down Expand Up @@ -850,30 +856,6 @@ def compare_image_lists(new_result, old_result, decimals):
os.remove(fn)


class VRImageComparisonTest(AnswerTestingTest):
_type_name = "VRImageComparison"
_attrs = ("desc",)

def __init__(self, scene, ds, desc, decimals):
super().__init__(None)
self.obj_type = ("vr",)
self.ds = ds
self.scene = scene
self.desc = desc
self.decimals = decimals

def run(self):
tmpfd, tmpname = tempfile.mkstemp(suffix=".png")
os.close(tmpfd)
self.scene.save(tmpname, sigma_clip=1.0)
image = mpimg.imread(tmpname)
os.remove(tmpname)
return [zlib.compress(image.dumps())]

def compare(self, new_result, old_result):
compare_image_lists(new_result, old_result, self.decimals)


class PlotWindowAttributeTest(AnswerTestingTest):
_type_name = "PlotWindowAttribute"
_attrs = (
Expand Down Expand Up @@ -1040,43 +1022,6 @@ def compare(self, new_result, old_result):
)


class GenericImageTest(AnswerTestingTest):
_type_name = "GenericImage"
_attrs = ("image_func_name", "args", "kwargs")

def __init__(self, ds_fn, image_func, decimals, args=None, kwargs=None):
super().__init__(ds_fn)
self.image_func = image_func
self.image_func_name = image_func.__name__
self.args = args
self.kwargs = kwargs
self.decimals = decimals

def run(self):
if self.args is None:
args = []
else:
args = self.args
if self.kwargs is None:
kwargs = {}
else:
kwargs = self.kwargs
comp_imgs = []
tmpdir = tempfile.mkdtemp()
image_prefix = os.path.join(tmpdir, "test_img")
self.image_func(image_prefix, *args, **kwargs)
imgs = sorted(glob.glob(image_prefix + "*"))
assert len(imgs) > 0
for img in imgs:
img_data = mpimg.imread(img)
os.remove(img)
comp_imgs.append(zlib.compress(img_data.dumps()))
return comp_imgs

def compare(self, new_result, old_result):
compare_image_lists(new_result, old_result, self.decimals)


class AxialPixelizationTest(AnswerTestingTest):
# This test is typically used once per geometry or coordinates type.
# Feed it a dataset, and it checks that the results of basic pixelization
Expand Down Expand Up @@ -1137,7 +1082,7 @@ def requires_answer_testing():

def requires_ds(ds_fn, big_data=False, file_check=False):
condition = (big_data and not run_big_data) or not can_run_ds(ds_fn, file_check)
return skipif(condition, reason="cannot load dataset")
return skipif(condition, reason=f"cannot load dataset {ds_fn}")


def small_patch_amr(ds_fn, fields, input_center="max", input_weight=("gas", "density")):
Expand Down
47 changes: 1 addition & 46 deletions yt/visualization/tests/test_geo_projections.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import unittest

import numpy as np
from nose.plugins.attrib import attr

import yt
from yt.testing import ANSWER_TEST_TAG, fake_amr_ds, requires_module
from yt.utilities.answer_testing.framework import GenericImageTest
from yt.testing import fake_amr_ds, requires_module
from yt.visualization.geo_plot_utils import get_mpl_transform, transform_list


Expand All @@ -16,49 +14,6 @@ def setup():
ytcfg["yt", "internals", "within_testing"] = True


def compare(
ds, field, idir, test_prefix, test_name, projection, decimals=12, annotate=False
):
def slice_image(filename_prefix):
sl = yt.SlicePlot(ds, idir, field, origin="native")
sl.set_mpl_projection(projection)
if annotate:
sl._setup_plots()
sl.annotate_mesh_lines()
sl.set_log("all", False)
image_file = sl.save(filename_prefix)
return image_file

slice_image.__name__ = f"slice_{test_prefix}"
test = GenericImageTest(ds, slice_image, decimals)
test.prefix = test_prefix
test.answer_name = test_name
return test


@requires_module("cartopy")
@attr(ANSWER_TEST_TAG)
def test_geo_slices_amr():
ds = fake_amr_ds(geometry="geographic")
for transform in transform_list:
if transform == "UTM":
# requires additional argument so we skip
continue
if transform == "OSNI":
# avoid crashes, see https://github.com/SciTools/cartopy/issues/1177
continue
for field in ds.field_list:
prefix = f"{field[0]}_{field[1]}_{transform}"
yield compare(
ds,
field,
"altitude",
test_prefix=prefix,
test_name="geo_slices_amr",
projection=transform,
)


class TestGeoProjections(unittest.TestCase):
@requires_module("cartopy")
def setUp(self):
Expand Down
Loading

0 comments on commit dde193d

Please sign in to comment.