Spaces:
Running
Running
| """ | |
| Test output reproducibility. | |
| """ | |
| import os | |
| import sys | |
| import pytest | |
| import matplotlib as mpl | |
| from matplotlib import pyplot as plt | |
| from matplotlib.cbook import get_sample_data | |
| from matplotlib.collections import PathCollection | |
| from matplotlib.image import BboxImage | |
| from matplotlib.offsetbox import AnchoredOffsetbox, AuxTransformBox | |
| from matplotlib.patches import Circle, PathPatch | |
| from matplotlib.path import Path | |
| from matplotlib.testing import subprocess_run_for_testing | |
| from matplotlib.testing._markers import needs_ghostscript, needs_usetex | |
| import matplotlib.testing.compare | |
| from matplotlib.text import TextPath | |
| from matplotlib.transforms import IdentityTransform | |
| def _save_figure(objects='mhip', fmt="pdf", usetex=False): | |
| mpl.use(fmt) | |
| mpl.rcParams.update({'svg.hashsalt': 'asdf', 'text.usetex': usetex}) | |
| fig = plt.figure() | |
| if 'm' in objects: | |
| # use different markers... | |
| ax1 = fig.add_subplot(1, 6, 1) | |
| x = range(10) | |
| ax1.plot(x, [1] * 10, marker='D') | |
| ax1.plot(x, [2] * 10, marker='x') | |
| ax1.plot(x, [3] * 10, marker='^') | |
| ax1.plot(x, [4] * 10, marker='H') | |
| ax1.plot(x, [5] * 10, marker='v') | |
| if 'h' in objects: | |
| # also use different hatch patterns | |
| ax2 = fig.add_subplot(1, 6, 2) | |
| bars = (ax2.bar(range(1, 5), range(1, 5)) + | |
| ax2.bar(range(1, 5), [6] * 4, bottom=range(1, 5))) | |
| ax2.set_xticks([1.5, 2.5, 3.5, 4.5]) | |
| patterns = ('-', '+', 'x', '\\', '*', 'o', 'O', '.') | |
| for bar, pattern in zip(bars, patterns): | |
| bar.set_hatch(pattern) | |
| if 'i' in objects: | |
| # also use different images | |
| A = [[1, 2, 3], [2, 3, 1], [3, 1, 2]] | |
| fig.add_subplot(1, 6, 3).imshow(A, interpolation='nearest') | |
| A = [[1, 3, 2], [1, 2, 3], [3, 1, 2]] | |
| fig.add_subplot(1, 6, 4).imshow(A, interpolation='bilinear') | |
| A = [[2, 3, 1], [1, 2, 3], [2, 1, 3]] | |
| fig.add_subplot(1, 6, 5).imshow(A, interpolation='bicubic') | |
| if 'p' in objects: | |
| # clipping support class, copied from demo_text_path.py gallery example | |
| class PathClippedImagePatch(PathPatch): | |
| """ | |
| The given image is used to draw the face of the patch. Internally, | |
| it uses BboxImage whose clippath set to the path of the patch. | |
| FIXME : The result is currently dpi dependent. | |
| """ | |
| def __init__(self, path, bbox_image, **kwargs): | |
| super().__init__(path, **kwargs) | |
| self.bbox_image = BboxImage( | |
| self.get_window_extent, norm=None, origin=None) | |
| self.bbox_image.set_data(bbox_image) | |
| def set_facecolor(self, color): | |
| """Simply ignore facecolor.""" | |
| super().set_facecolor("none") | |
| def draw(self, renderer=None): | |
| # the clip path must be updated every draw. any solution? -JJ | |
| self.bbox_image.set_clip_path(self._path, self.get_transform()) | |
| self.bbox_image.draw(renderer) | |
| super().draw(renderer) | |
| # add a polar projection | |
| px = fig.add_subplot(projection="polar") | |
| pimg = px.imshow([[2]]) | |
| pimg.set_clip_path(Circle((0, 1), radius=0.3333)) | |
| # add a text-based clipping path (origin: demo_text_path.py) | |
| (ax1, ax2) = fig.subplots(2) | |
| arr = plt.imread(get_sample_data("grace_hopper.jpg")) | |
| text_path = TextPath((0, 0), "!?", size=150) | |
| p = PathClippedImagePatch(text_path, arr, ec="k") | |
| offsetbox = AuxTransformBox(IdentityTransform()) | |
| offsetbox.add_artist(p) | |
| ao = AnchoredOffsetbox(loc='upper left', child=offsetbox, frameon=True, | |
| borderpad=0.2) | |
| ax1.add_artist(ao) | |
| # add a 2x2 grid of path-clipped axes (origin: test_artist.py) | |
| exterior = Path.unit_rectangle().deepcopy() | |
| exterior.vertices *= 4 | |
| exterior.vertices -= 2 | |
| interior = Path.unit_circle().deepcopy() | |
| interior.vertices = interior.vertices[::-1] | |
| clip_path = Path.make_compound_path(exterior, interior) | |
| star = Path.unit_regular_star(6).deepcopy() | |
| star.vertices *= 2.6 | |
| (row1, row2) = fig.subplots(2, 2, sharex=True, sharey=True) | |
| for row in (row1, row2): | |
| ax1, ax2 = row | |
| collection = PathCollection([star], lw=5, edgecolor='blue', | |
| facecolor='red', alpha=0.7, hatch='*') | |
| collection.set_clip_path(clip_path, ax1.transData) | |
| ax1.add_collection(collection) | |
| patch = PathPatch(star, lw=5, edgecolor='blue', facecolor='red', | |
| alpha=0.7, hatch='*') | |
| patch.set_clip_path(clip_path, ax2.transData) | |
| ax2.add_patch(patch) | |
| ax1.set_xlim([-3, 3]) | |
| ax1.set_ylim([-3, 3]) | |
| x = range(5) | |
| ax = fig.add_subplot(1, 6, 6) | |
| ax.plot(x, x) | |
| ax.set_title('A string $1+2+\\sigma$') | |
| ax.set_xlabel('A string $1+2+\\sigma$') | |
| ax.set_ylabel('A string $1+2+\\sigma$') | |
| stdout = getattr(sys.stdout, 'buffer', sys.stdout) | |
| fig.savefig(stdout, format=fmt) | |
| def test_determinism_check(objects, fmt, usetex): | |
| """ | |
| Output three times the same graphs and checks that the outputs are exactly | |
| the same. | |
| Parameters | |
| ---------- | |
| objects : str | |
| Objects to be included in the test document: 'm' for markers, 'h' for | |
| hatch patterns, 'i' for images, and 'p' for paths. | |
| fmt : {"pdf", "ps", "svg"} | |
| Output format. | |
| """ | |
| plots = [ | |
| subprocess_run_for_testing( | |
| [sys.executable, "-R", "-c", | |
| f"from matplotlib.tests.test_determinism import _save_figure;" | |
| f"_save_figure({objects!r}, {fmt!r}, {usetex})"], | |
| env={**os.environ, "SOURCE_DATE_EPOCH": "946684800", | |
| "MPLBACKEND": "Agg"}, | |
| text=False, capture_output=True, check=True).stdout | |
| for _ in range(3) | |
| ] | |
| for p in plots[1:]: | |
| if fmt == "ps" and usetex: | |
| if p != plots[0]: | |
| pytest.skip("failed, maybe due to ghostscript timestamps") | |
| else: | |
| assert p == plots[0] | |
| def test_determinism_source_date_epoch(fmt, string): | |
| """ | |
| Test SOURCE_DATE_EPOCH support. Output a document with the environment | |
| variable SOURCE_DATE_EPOCH set to 2000-01-01 00:00 UTC and check that the | |
| document contains the timestamp that corresponds to this date (given as an | |
| argument). | |
| Parameters | |
| ---------- | |
| fmt : {"pdf", "ps", "svg"} | |
| Output format. | |
| string : bytes | |
| Timestamp string for 2000-01-01 00:00 UTC. | |
| """ | |
| buf = subprocess_run_for_testing( | |
| [sys.executable, "-R", "-c", | |
| f"from matplotlib.tests.test_determinism import _save_figure; " | |
| f"_save_figure('', {fmt!r})"], | |
| env={**os.environ, "SOURCE_DATE_EPOCH": "946684800", | |
| "MPLBACKEND": "Agg"}, capture_output=True, text=False, check=True).stdout | |
| assert string in buf | |