Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Contour segments changed after clabel #28631

Open
wei-lingfeng opened this issue Aug 1, 2024 · 1 comment
Open

[Bug]: Contour segments changed after clabel #28631

wei-lingfeng opened this issue Aug 1, 2024 · 1 comment

Comments

@wei-lingfeng
Copy link

Bug summary

ax.clabel changes the contour segments itself as it removes the label part of the contours.
image

Python 3.11.8 + Matplotlib 3.7.1 doesn't change the contour itself, where as Python 3.11.9 + Matplotlib 3.9.1 changes it. Is this an intended change?

Code for reproduction

import numpy as np
import matplotlib.pyplot as plt

size = 1000
sigma_x = 1.
sigma_y = 1.

x = np.linspace(-3, 3, size)
y = np.linspace(-3, 3, size)

xx, yy = np.meshgrid(x, y)
z = (1/(2*np.pi*sigma_x*sigma_y) * np.exp(-(xx**2/(2*sigma_x**2)
     + yy**2/(2*sigma_y**2))))

extent = [x[0], x[-1], y[0], y[-1]]
fig, ax = plt.subplots()
ax.imshow(z, extent=extent)
cs = ax.contour(z, extent=extent, colors='w')
seg1 = cs.allsegs[3][0]
ax.clabel(cs, cs.levels, fmt='%.5f%%', fontsize=15)
seg2 = cs.allsegs[3][0]
plt.show()

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(6, 3))
ax1.plot(seg1[:, 0], seg1[:, 1], marker='.', ms=1)
ax1.set_title('Before ax.clabel')
ax2.plot(seg2[:, 0], seg2[:, 1], marker='.', ms=1)
ax2.set_title('After ax.clabel')
plt.show()

Actual outcome

Contour segments changed after ax.clabel. The labeled part is removed from the contour

Expected outcome

Keep the contour segment unchanged

Additional information

Python 3.11.8 + Matplotlib 3.7.1 doesn't change the contour itself, where as Python 3.11.9 + Matplotlib 3.9.1 changes it. Is this an intended change?

Operating system

MacOS

Matplotlib Version

3.9.1

Matplotlib Backend

No response

Python version

3.11.9

Jupyter version

No response

Installation

None

@rcomer
Copy link
Member

rcomer commented Aug 1, 2024

Thanks for the clear report @wei-lingfeng!

In v3.7 allsegs was an attribute that was defined once during the ContourSet's instantiation

if getattr(self, 'allsegs', None) is None:
self.allsegs, self.allkinds = self._get_allsegs_and_allkinds()

At v3.8.0 the ContourSet had a significant re-write and allsegs became a property that is calculated from the current state of the contour paths

allsegs = property(lambda self: [
[subp.vertices for subp in p._iter_connected_components()]
for p in self.get_paths()])

Usually the paths don't change so this difference shouldn't matter, but the contour labelling does work by creating gaps in them. While writing this I saw that @anntzer has some thoughts on that (#27081 (comment)) so I will stop here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants