diff --git a/tests/data/test_threadcontainer.py b/tests/data/test_threadcontainer.py index 519f8350a03..1aa653bf1e9 100644 --- a/tests/data/test_threadcontainer.py +++ b/tests/data/test_threadcontainer.py @@ -11,18 +11,16 @@ from __future__ import annotations -import os import tempfile import time import unittest -from pathlib import Path import torch from monai.data import DataLoader from monai.utils import optional_import, set_determinism from monai.utils.enums import CommonKeys -from tests.test_utils import SkipIfNoModule +from tests.test_utils import SkipIfNoModule, get_matplotlib_baseline try: _, has_ignite = optional_import("ignite") @@ -70,9 +68,6 @@ def test_container(self): @SkipIfNoModule("matplotlib") def test_plot(self): set_determinism(0) - test_dir = Path(__file__).parents[1] - testing_dir = os.path.join(test_dir, "testing_data") - net = torch.nn.Conv2d(1, 1, 3, padding=1) opt = torch.optim.Adam(net.parameters()) @@ -105,7 +100,7 @@ def test_plot(self): with tempfile.TemporaryDirectory() as tempdir: tempimg = f"{tempdir}/threadcontainer_plot_test.png" fig.savefig(tempimg) - comp = compare_images(f"{testing_dir}/threadcontainer_plot_test.png", tempimg, 5e-2) + comp = compare_images(get_matplotlib_baseline("threadcontainer_plot_test.png"), tempimg, 5e-2) self.assertIsNone(comp, comp) # None indicates test passed diff --git a/tests/test_matplotlib_baseline.py b/tests/test_matplotlib_baseline.py new file mode 100644 index 00000000000..f6d7b810cec --- /dev/null +++ b/tests/test_matplotlib_baseline.py @@ -0,0 +1,50 @@ +# Copyright (c) MONAI Consortium +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations + +import unittest +from unittest.mock import patch + +from tests.test_utils import MODULE_PATH, SkipIfNoModule, get_matplotlib_baseline + + +@SkipIfNoModule("matplotlib") +class TestMatplotlibBaseline(unittest.TestCase): + def test_renderer_boundary(self): + cases = ( + ("3.9.4", False), + ("3.10.9", False), + ("3.10.99", False), + ("3.11.0.dev0", True), + ("3.11.0a1", True), + ("3.11.0rc1", True), + ("3.11.0", True), + ("3.11.2", True), + ("3.12.0.dev0", True), + ("4.0.0", True), + ) + for version, modern in cases: + with self.subTest(version=version), patch("matplotlib.__version__", version): + expected = MODULE_PATH / "tests" / "testing_data" + if modern: + expected /= "matplotlib_3_11" + self.assertEqual(get_matplotlib_baseline("matshow3d_test.png"), expected / "matshow3d_test.png") + + def test_missing_reference_does_not_fall_back(self): + with patch("matplotlib.__version__", "3.11.2"): + path = get_matplotlib_baseline("missing-reference.png") + self.assertEqual(path.parent.name, "matplotlib_3_11") + self.assertFalse(path.exists()) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_utils.py b/tests/test_utils.py index 9d245f9778a..6cb7ae02bab 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -50,7 +50,7 @@ from monai.data import create_test_image_2d, create_test_image_3d from monai.data.meta_tensor import MetaTensor, get_track_meta from monai.networks import convert_to_onnx, convert_to_torchscript -from monai.utils import optional_import +from monai.utils import optional_import, version_geq from monai.utils.misc import MONAIEnvVars from monai.utils.module import compute_capabilities_after, pytorch_after from monai.utils.tf32 import detect_default_tf32 @@ -101,6 +101,15 @@ def testing_data_config(*keys): return reduce(operator.getitem, keys, _test_data_config) +def get_matplotlib_baseline(filename: str) -> Path: + """Select the reference for the pre-3.11 or 3.11+ text renderer.""" + matplotlib_version, _ = optional_import("matplotlib", name="__version__") + directory = MODULE_PATH / "tests" / "testing_data" + if version_geq(matplotlib_version, "3.11.0.dev0"): + directory /= "matplotlib_3_11" + return directory / filename + + def get_testing_algo_template_path(): """ a local folder to the testing algorithm template or a url to the compressed template file. diff --git a/tests/testing_data/matplotlib_3_11/matshow3d_patch_test.png b/tests/testing_data/matplotlib_3_11/matshow3d_patch_test.png new file mode 100644 index 00000000000..6db22096b4e Binary files /dev/null and b/tests/testing_data/matplotlib_3_11/matshow3d_patch_test.png differ diff --git a/tests/testing_data/matplotlib_3_11/matshow3d_rgb_test.png b/tests/testing_data/matplotlib_3_11/matshow3d_rgb_test.png new file mode 100644 index 00000000000..fb291c7c4d5 Binary files /dev/null and b/tests/testing_data/matplotlib_3_11/matshow3d_rgb_test.png differ diff --git a/tests/testing_data/matplotlib_3_11/matshow3d_test.png b/tests/testing_data/matplotlib_3_11/matshow3d_test.png new file mode 100644 index 00000000000..9900c1bdcf6 Binary files /dev/null and b/tests/testing_data/matplotlib_3_11/matshow3d_test.png differ diff --git a/tests/testing_data/matplotlib_3_11/threadcontainer_plot_test.png b/tests/testing_data/matplotlib_3_11/threadcontainer_plot_test.png new file mode 100644 index 00000000000..d439cc24512 Binary files /dev/null and b/tests/testing_data/matplotlib_3_11/threadcontainer_plot_test.png differ diff --git a/tests/visualize/utils/test_matshow3d.py b/tests/visualize/utils/test_matshow3d.py index f10f1ea79de..1e2741e3e80 100644 --- a/tests/visualize/utils/test_matshow3d.py +++ b/tests/visualize/utils/test_matshow3d.py @@ -28,7 +28,7 @@ ) from monai.utils import optional_import from monai.visualize.utils import matshow3d -from tests.test_utils import SkipIfNoModule +from tests.test_utils import SkipIfNoModule, get_matplotlib_baseline compare_images, _ = optional_import("matplotlib.testing.compare", name="compare_images") pyplot, has_pyplot = optional_import("matplotlib", name="pyplot") @@ -57,7 +57,7 @@ def test_3d(self): with tempfile.TemporaryDirectory() as tempdir: tempimg = f"{tempdir}/matshow3d_test.png" fig.savefig(tempimg) - comp = compare_images(f"{testing_dir}/matshow3d_test.png", tempimg, 5e-2) + comp = compare_images(get_matplotlib_baseline("matshow3d_test.png"), tempimg, 5e-2) self.assertIsNone(comp, f"value of comp={comp}") # None indicates test passed _, axes = pyplot.subplots() @@ -86,8 +86,9 @@ def test_samples(self): with tempfile.TemporaryDirectory() as tempdir: tempimg = f"{tempdir}/matshow3d_patch_test.png" fig.savefig(tempimg) - comp = compare_images(f"{testing_dir}/matshow3d_patch_test.png", tempimg, 5e-2, in_decorator=True) - if comp: + baseline = get_matplotlib_baseline("matshow3d_patch_test.png") + comp = compare_images(baseline, tempimg, 5e-2, in_decorator=True) + if comp and baseline == Path(testing_dir) / "matshow3d_patch_test.png": print("not none comp: ", comp) # matplotlib 3.2.2 np.testing.assert_allclose(comp["rms"], 30.786983, atol=1e-3, rtol=1e-3) else: @@ -125,7 +126,7 @@ def test_3d_rgb(self): with tempfile.TemporaryDirectory() as tempdir: tempimg = f"{tempdir}/matshow3d_rgb_test.png" fig.savefig(tempimg) - comp = compare_images(f"{testing_dir}/matshow3d_rgb_test.png", tempimg, 5e-2) + comp = compare_images(get_matplotlib_baseline("matshow3d_rgb_test.png"), tempimg, 5e-2) self.assertIsNone(comp, f"value of comp={comp}") # None indicates test passed