You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If a Path has multiple connected components (separated by MOVETO codes some of them fully horizontal/vertical and some of them not, then none of the chunks are snapped (this is controlled by PathSnapper::should_snap in path_converters.h); this means that drawing that Path via a single PathPatch (or a single Path in a Collection) will render slightly differently than if creating multiple Paths, one per connected component, and drawing them via multiple PathPatches (or a single Collection with multiple Paths).
Code for reproduction
fromioimportBytesIOimportmatplotlibasmplfrommatplotlibimportpyplotaspltfrommatplotlib.patchesimportPathPatchfrommatplotlib.pathimportPathimportnumpyasnpmpl.use("qtagg")
mpl.rcParams["path.snap"] =True# Default, set to False to remove the problem.fig=plt.figure(figsize=(6, 2), dpi=200)
ax=fig.add_subplot()
# Define a path with three connected components; the last one has slanted parts.xys= [
[0.0, 4.5],
[0.740033943422379, 4.5],
[1.259966056577621, 4.5],
[1.774087425970262, 4.5],
[2.2259125740297376, 4.5],
[3.0, 4.5],
[4.0, 4.5],
[4.5, 4.0],
[4.5, 3.0],
[4.5, 2.0],
[4.5, 1.0],
[4.5, 0.0],
]
M=Path.MOVETO; L=Path.LINETOcodes= [M, L, M, L, M, L, L, L, L, L, L, L]
# Draw as single Path, save as png.ax.clear(); ax.set(xlim=(0, 9), ylim=(0, 9)); ax.set_axis_off()
ax.add_artist(PathPatch(Path(xys, codes), facecolor="none"))
buf0=BytesIO(); fig.savefig(buf0, format="png"); buf0.seek(0)
# Draw as multiple separate Paths, save as png.ax.clear(); ax.set(xlim=(0, 9), ylim=(0, 9)); ax.set_axis_off()
forslin [slice(0, 2), slice(2, 4), slice(4, 12)]:
# One can also explicitly pass the codes (Path(xys[sl], codes[sl])); this makes no# difference with leaving the codes as None.ax.add_artist(PathPatch(Path(xys[sl]), facecolor="none"))
buf1=BytesIO(); fig.savefig(buf1, format="png"); buf1.seek(0)
plt.close("all")
# Summarize the results.im0=plt.imread(buf0)[..., 0] # monochrome, so we can just take one channel.im1=plt.imread(buf1)[..., 0]
axs=plt.figure(figsize=(8, 8), layout="constrained").subplots(3, sharex=True, sharey=True)
axs[0].imshow(im0, cmap="gray")
axs[1].imshow(im1, cmap="gray")
axs[2].imshow(im0-im1, cmap="bwr", clim=(-1, 1))
axs[2].set(title=f"diff image; max={abs(im0-im1).max():.4f}")
plt.show()
Actual outcome
Note that the difference in snapping results in the bottom diff image showing the two lines being slightly offset one from the other.
Expected outcome
First two images should be exactly identical, and the bottom diff should be zero.
Additional information
Even if fixing this is tricky (we probably need to get rid of should_snap (a global value for the entire path) and instead decide for each individual LINETO whether it should be snapped), I'm mostly opening this right now to document one of the reasons why #25247 (which indeed turns multiple separate LineCollections into a single Collection) causes quite a few small image differences.
Operating system
macOS
Matplotlib Version
3.7.0
Matplotlib Backend
qtagg
Python version
3.11
Jupyter version
ENOSUCHLIB
Installation
from source (.tar.gz)
The text was updated successfully, but these errors were encountered:
Bug summary
If a Path has multiple connected components (separated by MOVETO codes some of them fully horizontal/vertical and some of them not, then none of the chunks are snapped (this is controlled by PathSnapper::should_snap in path_converters.h); this means that drawing that Path via a single PathPatch (or a single Path in a Collection) will render slightly differently than if creating multiple Paths, one per connected component, and drawing them via multiple PathPatches (or a single Collection with multiple Paths).
Code for reproduction
Actual outcome
Note that the difference in snapping results in the bottom diff image showing the two lines being slightly offset one from the other.
Expected outcome
First two images should be exactly identical, and the bottom diff should be zero.
Additional information
Even if fixing this is tricky (we probably need to get rid of should_snap (a global value for the entire path) and instead decide for each individual LINETO whether it should be snapped), I'm mostly opening this right now to document one of the reasons why #25247 (which indeed turns multiple separate LineCollections into a single Collection) causes quite a few small image differences.
Operating system
macOS
Matplotlib Version
3.7.0
Matplotlib Backend
qtagg
Python version
3.11
Jupyter version
ENOSUCHLIB
Installation
from source (.tar.gz)
The text was updated successfully, but these errors were encountered: