From 523f5c2d3e061fdcd97f923ff97e5c04e4e04078 Mon Sep 17 00:00:00 2001 From: isaacrobinson2000 Date: Sun, 22 Sep 2024 19:44:29 -0400 Subject: [PATCH 1/8] Working with latest matplotlib, scale_lines also now scales markers. --- matplotview/_transform_renderer.py | 70 +++++++++++++++++++++++ matplotview/tests/test_view_rendering.py | 73 ++++++++++++++++++++++++ 2 files changed, 143 insertions(+) diff --git a/matplotview/_transform_renderer.py b/matplotview/_transform_renderer.py index a61d1ba..6732636 100644 --- a/matplotview/_transform_renderer.py +++ b/matplotview/_transform_renderer.py @@ -251,6 +251,76 @@ def _draw_text_as_path( # checked above... (Above case causes error) super()._draw_text_as_path(gc, x, y, s, prop, angle, ismath) + def draw_markers( + self, + gc, + marker_path, + marker_trans, + path, + trans, + rgbFace = None, + ): + # If the markers need to be scaled accurately (such as in log scale), just use the fallback as each will need + # to be scaled separately. + if(self.__scale_widths): + super().draw_markers(gc, marker_path, marker_trans, path, trans, rgbFace) + return + + # Otherwise we transform just the marker offsets (not the marker patch), so they stay the same size. + path = path.deepcopy() + path.vertices = self._get_transfer_transform(trans).transform(path.vertices) + bbox = self._get_axes_display_box() + + # Change the clip to the sub-axes box + gc.set_clip_rectangle(bbox) + if (not isinstance(self.__bounding_axes.patch, Rectangle)): + gc.set_clip_path(TransformedPatchPath(self.__bounding_axes.patch)) + + rgbFace = tuple(rgbFace) if (rgbFace is not None) else None + self.__renderer.draw_markers(gc, marker_path, marker_trans, path, IdentityTransform(), rgbFace) + + def draw_path_collection( + self, + gc, + master_transform, + paths, + all_transforms, + offsets, + offset_trans, + facecolors, + edgecolors, + linewidths, + linestyles, + antialiaseds, + urls, + offset_position, + ): + # If we want accurate scaling for each marker (such as in log scale), just use superclass implementation... + if(self.__scale_widths): + super().draw_path_collection( + gc, master_transform, paths, all_transforms, offsets, offset_trans, facecolors, + edgecolors, linewidths, linestyles, antialiaseds, urls, offset_position + ) + return + + # Otherwise we transform just the offsets, and pass them to the backend. + print(offsets) + if(np.any(np.isnan(offsets))): + raise ValueError("???") + offsets = self._get_transfer_transform(offset_trans).transform(offsets) + print(offsets) + bbox = self._get_axes_display_box() + + # Change the clip to the sub-axes box + gc.set_clip_rectangle(bbox) + if (not isinstance(self.__bounding_axes.patch, Rectangle)): + gc.set_clip_path(TransformedPatchPath(self.__bounding_axes.patch)) + + self.__renderer.draw_path_collection( + gc, master_transform, paths, all_transforms, offsets, IdentityTransform(), facecolors, + edgecolors, linewidths, linestyles, antialiaseds, urls, None + ) + def draw_gouraud_triangle( self, gc: GraphicsContextBase, diff --git a/matplotview/tests/test_view_rendering.py b/matplotview/tests/test_view_rendering.py index 03b9547..bb9b744 100644 --- a/matplotview/tests/test_view_rendering.py +++ b/matplotview/tests/test_view_rendering.py @@ -240,3 +240,76 @@ def test_stop_viewing(fig_test, fig_ref): ax1_ref.plot(data) ax1_ref.text(0.5, 0.5, "Hello") + + +@check_figures_equal() +def test_log_line(fig_test, fig_ref): + data = [i for i in range(10)] + + # Test case... Create a view and stop it... + ax1_test, ax2_test = fig_test.subplots(1, 2) + + ax1_test.set(xscale="log", yscale="log") + ax1_test.plot(data, "-o") + + view(ax2_test, ax1_test, scale_lines=False) + ax2_test.set_xlim(-1, 10) + ax2_test.set_ylim(-1, 10) + + # Reference, just don't plot anything at all in the second axes... + ax1_ref, ax2_ref = fig_ref.subplots(1, 2) + + ax1_ref.set(xscale="log", yscale="log") + ax1_ref.plot(data, "-o") + ax2_ref.plot(data, "-o") + ax2_ref.set_xlim(-1, 10) + ax2_ref.set_ylim(-1, 10) + + +@check_figures_equal() +def test_log_scatter(fig_test, fig_ref): + data = [i for i in range(1, 11)] + + # Test case... Create a view and stop it... + ax1_test, ax2_test = fig_test.subplots(1, 2) + + ax1_test.set(xscale="log", yscale="log") + ax1_test.scatter(data, data) + + view(ax2_test, ax1_test, scale_lines=False) + ax2_test.set_xlim(-5, 15) + ax2_test.set_ylim(-5, 15) + + # Reference, just don't plot anything at all in the second axes... + ax1_ref, ax2_ref = fig_ref.subplots(1, 2) + + ax1_ref.set(xscale="log", yscale="log") + ax1_ref.scatter(data, data) + ax2_ref.scatter(data, data) + ax2_ref.set_xlim(-5, 15) + ax2_ref.set_ylim(-5, 15) + + +@check_figures_equal() +def test_log_scatter_with_colors(fig_test, fig_ref): + data = [i for i in range(1, 11)] + colors = list("rgbrgbrgbr") + + # Test case... Create a view and stop it... + ax1_test, ax2_test = fig_test.subplots(1, 2) + + ax1_test.set(xscale="log", yscale="log") + ax1_test.scatter(data, data, color=colors) + + view(ax2_test, ax1_test, scale_lines=False) + ax2_test.set_xlim(-5, 15) + ax2_test.set_ylim(-5, 15) + + # Reference, just don't plot anything at all in the second axes... + ax1_ref, ax2_ref = fig_ref.subplots(1, 2) + + ax1_ref.set(xscale="log", yscale="log") + ax1_ref.scatter(data, data, color=colors) + ax2_ref.scatter(data, data, color=colors) + ax2_ref.set_xlim(-5, 15) + ax2_ref.set_ylim(-5, 15) From 9c059cb2aa09c17dcc441da47a6132c912488fbe Mon Sep 17 00:00:00 2001 From: isaacrobinson2000 Date: Sun, 22 Sep 2024 19:54:47 -0400 Subject: [PATCH 2/8] Minor adjustment so we don't have a marker at 0 on the log scale. --- matplotview/tests/test_view_rendering.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matplotview/tests/test_view_rendering.py b/matplotview/tests/test_view_rendering.py index bb9b744..79c3eea 100644 --- a/matplotview/tests/test_view_rendering.py +++ b/matplotview/tests/test_view_rendering.py @@ -244,7 +244,7 @@ def test_stop_viewing(fig_test, fig_ref): @check_figures_equal() def test_log_line(fig_test, fig_ref): - data = [i for i in range(10)] + data = [i for i in range(1, 10)] # Test case... Create a view and stop it... ax1_test, ax2_test = fig_test.subplots(1, 2) From a8cf1b415b75204f58c636839aa4812c11889053 Mon Sep 17 00:00:00 2001 From: isaacr Date: Fri, 18 Jul 2025 12:52:39 -0600 Subject: [PATCH 3/8] Add artifact upload on failure. --- .github/workflows/pytest.yml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 685d7b0..e8f7712 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -57,9 +57,18 @@ jobs: flake8 matplotview --count --select=E9,F63,F7,F82 --show-source --statistics flake8 matplotview --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Test with pytest + id: pytest run: | pytest + - name: Upload images on failure + uses: actions/upload-artifact@v4 + if: ${{ failure() && steps.pytest.conclusion == 'failure' }} + with: + name: test-result-images + retention-days: 1 + path: result_images/ + test-windows: runs-on: windows-latest @@ -82,5 +91,14 @@ jobs: pip install pytest pip install -r requirements.txt - name: Test with pytest + id: pytest run: | - pytest \ No newline at end of file + pytest + + - name: Upload images on failure + uses: actions/upload-artifact@v4 + if: ${{ failure() && steps.pytest.conclusion == 'failure' }} + with: + name: test-result-images + retention-days: 1 + path: result_images/ From 351342b346f12074b26364e403531e2f3e941493 Mon Sep 17 00:00:00 2001 From: isaacr Date: Fri, 18 Jul 2025 13:12:36 -0600 Subject: [PATCH 4/8] Add small tolerance for macos --- .github/workflows/pytest.yml | 4 ++-- matplotview/tests/test_view_rendering.py | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index e8f7712..f8c31fa 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -19,7 +19,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest] - python-version: ["3.9", "3.10", "3.11"] + python-version: ["3.11", "3.12", "3.13", "3.13t"] steps: - uses: actions/checkout@v4 @@ -74,7 +74,7 @@ jobs: runs-on: windows-latest strategy: matrix: - python-version: ["3.9", "3.10", "3.11"] + python-version: ["3.11", "3.12", "3.13", "3.13t"] steps: - uses: actions/checkout@v4 diff --git a/matplotview/tests/test_view_rendering.py b/matplotview/tests/test_view_rendering.py index 79c3eea..32dbb14 100644 --- a/matplotview/tests/test_view_rendering.py +++ b/matplotview/tests/test_view_rendering.py @@ -1,3 +1,5 @@ +import sys + import numpy as np import matplotlib.pyplot as plt from matplotlib.testing.decorators import check_figures_equal @@ -241,8 +243,8 @@ def test_stop_viewing(fig_test, fig_ref): ax1_ref.plot(data) ax1_ref.text(0.5, 0.5, "Hello") - -@check_figures_equal() +# On MacOS the results are off by an extremely tiny amount, can't even see in diff. It's close enough... +@check_figures_equal(tol=0 if sys.platform.startswith("darwin") else 0.2) def test_log_line(fig_test, fig_ref): data = [i for i in range(1, 10)] From ad031e681330c3a95592aae205e5b857e0ea1515 Mon Sep 17 00:00:00 2001 From: isaacr Date: Fri, 18 Jul 2025 13:15:23 -0600 Subject: [PATCH 5/8] Add small tolerance for macos --- matplotview/tests/test_view_rendering.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matplotview/tests/test_view_rendering.py b/matplotview/tests/test_view_rendering.py index 32dbb14..b348ce8 100644 --- a/matplotview/tests/test_view_rendering.py +++ b/matplotview/tests/test_view_rendering.py @@ -244,7 +244,7 @@ def test_stop_viewing(fig_test, fig_ref): ax1_ref.text(0.5, 0.5, "Hello") # On MacOS the results are off by an extremely tiny amount, can't even see in diff. It's close enough... -@check_figures_equal(tol=0 if sys.platform.startswith("darwin") else 0.2) +@check_figures_equal(tol=0.02) def test_log_line(fig_test, fig_ref): data = [i for i in range(1, 10)] From 3e94fa2b6d970642b022cc16c552ea87c37d0df5 Mon Sep 17 00:00:00 2001 From: isaacr Date: Fri, 18 Jul 2025 13:15:33 -0600 Subject: [PATCH 6/8] Add small tolerance for macos --- matplotview/tests/test_view_rendering.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/matplotview/tests/test_view_rendering.py b/matplotview/tests/test_view_rendering.py index b348ce8..6e3ab02 100644 --- a/matplotview/tests/test_view_rendering.py +++ b/matplotview/tests/test_view_rendering.py @@ -1,5 +1,3 @@ -import sys - import numpy as np import matplotlib.pyplot as plt from matplotlib.testing.decorators import check_figures_equal From 0e560d958d84f07c9172e499c893efce8a68ab56 Mon Sep 17 00:00:00 2001 From: isaacr Date: Fri, 18 Jul 2025 13:16:42 -0600 Subject: [PATCH 7/8] Add small tolerance for macos --- matplotview/tests/test_view_rendering.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/matplotview/tests/test_view_rendering.py b/matplotview/tests/test_view_rendering.py index 6e3ab02..5cafa7c 100644 --- a/matplotview/tests/test_view_rendering.py +++ b/matplotview/tests/test_view_rendering.py @@ -1,3 +1,5 @@ +import sys + import numpy as np import matplotlib.pyplot as plt from matplotlib.testing.decorators import check_figures_equal @@ -242,7 +244,7 @@ def test_stop_viewing(fig_test, fig_ref): ax1_ref.text(0.5, 0.5, "Hello") # On MacOS the results are off by an extremely tiny amount, can't even see in diff. It's close enough... -@check_figures_equal(tol=0.02) +@check_figures_equal(tol=0.02 if sys.platform.startswith("darwin") else 0) def test_log_line(fig_test, fig_ref): data = [i for i in range(1, 10)] From 4ca387b637474f5677f0ab7162cbee9c39000e4f Mon Sep 17 00:00:00 2001 From: isaacr Date: Fri, 18 Jul 2025 13:21:36 -0600 Subject: [PATCH 8/8] Fix some linting issues. --- matplotview/_transform_renderer.py | 8 ++++---- matplotview/tests/test_view_rendering.py | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/matplotview/_transform_renderer.py b/matplotview/_transform_renderer.py index 6732636..4bfd180 100644 --- a/matplotview/_transform_renderer.py +++ b/matplotview/_transform_renderer.py @@ -258,11 +258,11 @@ def draw_markers( marker_trans, path, trans, - rgbFace = None, + rgbFace=None, ): # If the markers need to be scaled accurately (such as in log scale), just use the fallback as each will need # to be scaled separately. - if(self.__scale_widths): + if (self.__scale_widths): super().draw_markers(gc, marker_path, marker_trans, path, trans, rgbFace) return @@ -296,7 +296,7 @@ def draw_path_collection( offset_position, ): # If we want accurate scaling for each marker (such as in log scale), just use superclass implementation... - if(self.__scale_widths): + if (self.__scale_widths): super().draw_path_collection( gc, master_transform, paths, all_transforms, offsets, offset_trans, facecolors, edgecolors, linewidths, linestyles, antialiaseds, urls, offset_position @@ -305,7 +305,7 @@ def draw_path_collection( # Otherwise we transform just the offsets, and pass them to the backend. print(offsets) - if(np.any(np.isnan(offsets))): + if (np.any(np.isnan(offsets))): raise ValueError("???") offsets = self._get_transfer_transform(offset_trans).transform(offsets) print(offsets) diff --git a/matplotview/tests/test_view_rendering.py b/matplotview/tests/test_view_rendering.py index 5cafa7c..05d44e1 100644 --- a/matplotview/tests/test_view_rendering.py +++ b/matplotview/tests/test_view_rendering.py @@ -243,6 +243,7 @@ def test_stop_viewing(fig_test, fig_ref): ax1_ref.plot(data) ax1_ref.text(0.5, 0.5, "Hello") + # On MacOS the results are off by an extremely tiny amount, can't even see in diff. It's close enough... @check_figures_equal(tol=0.02 if sys.platform.startswith("darwin") else 0) def test_log_line(fig_test, fig_ref):