-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Colorbar axis zoom and pan #19515
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
Colorbar axis zoom and pan #19515
Changes from all commits
0cd51be
dc0fd65
48d0663
011551f
b4ddd97
e1f9cc9
21fc347
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
Colorbars now have pan and zoom functionality | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
Interactive plots with colorbars can now be zoomed and panned on | ||
the colorbar axis. This adjusts the *vmin* and *vmax* of the | ||
``ScalarMappable`` associated with the colorbar. This is currently | ||
only enabled for continuous norms. Norms used with contourf and | ||
categoricals, such as ``BoundaryNorm`` and ``NoNorm``, have the | ||
interactive capability disabled by default. ``cb.ax.set_navigate()`` | ||
can be used to set whether a colorbar axes is interactive or not. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -422,7 +422,6 @@ def __init__(self, ax, mappable=None, *, cmap=None, | |
|
||
self.ax = ax | ||
self.ax._axes_locator = _ColorbarAxesLocator(self) | ||
ax.set(navigate=False) | ||
|
||
if extend is None: | ||
if (not isinstance(mappable, contour.ContourSet) | ||
|
@@ -496,6 +495,29 @@ def __init__(self, ax, mappable=None, *, cmap=None, | |
if isinstance(mappable, contour.ContourSet) and not mappable.filled: | ||
self.add_lines(mappable) | ||
|
||
# Link the Axes and Colorbar for interactive use | ||
self.ax._colorbar = self | ||
# Don't navigate on any of these types of mappables | ||
if (isinstance(self.norm, (colors.BoundaryNorm, colors.NoNorm)) or | ||
isinstance(self.mappable, contour.ContourSet)): | ||
self.ax.set_navigate(False) | ||
|
||
# These are the functions that set up interactivity on this colorbar | ||
self._interactive_funcs = ["_get_view", "_set_view", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ... oh, as before, do we still need this song and dance as well? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I didn't ever figure out a way to get the norm information up to the axes any other way. (This would be easier if a Colorbar inherited from some form of Axes so we could just override the methods directly) |
||
"_set_view_from_bbox", "drag_pan"] | ||
for x in self._interactive_funcs: | ||
setattr(self.ax, x, getattr(self, x)) | ||
# Set the cla function to the cbar's method to override it | ||
self.ax.cla = self._cbar_cla | ||
|
||
def _cbar_cla(self): | ||
"""Function to clear the interactive colorbar state.""" | ||
for x in self._interactive_funcs: | ||
delattr(self.ax, x) | ||
# We now restore the old cla() back and can call it directly | ||
del self.ax.cla | ||
self.ax.cla() | ||
|
||
# Also remove ._patch after deprecation elapses. | ||
patch = _api.deprecate_privatize_attribute("3.5", alternative="ax") | ||
|
||
|
@@ -1274,6 +1296,36 @@ def _short_axis(self): | |
return self.ax.xaxis | ||
return self.ax.yaxis | ||
|
||
def _get_view(self): | ||
# docstring inherited | ||
# An interactive view for a colorbar is the norm's vmin/vmax | ||
return self.norm.vmin, self.norm.vmax | ||
|
||
def _set_view(self, view): | ||
# docstring inherited | ||
# An interactive view for a colorbar is the norm's vmin/vmax | ||
self.norm.vmin, self.norm.vmax = view | ||
|
||
def _set_view_from_bbox(self, bbox, direction='in', | ||
mode=None, twinx=False, twiny=False): | ||
# docstring inherited | ||
# For colorbars, we use the zoom bbox to scale the norm's vmin/vmax | ||
new_xbound, new_ybound = self.ax._prepare_view_from_bbox( | ||
bbox, direction=direction, mode=mode, twinx=twinx, twiny=twiny) | ||
if self.orientation == 'horizontal': | ||
self.norm.vmin, self.norm.vmax = new_xbound | ||
elif self.orientation == 'vertical': | ||
self.norm.vmin, self.norm.vmax = new_ybound | ||
|
||
def drag_pan(self, button, key, x, y): | ||
# docstring inherited | ||
points = self.ax._get_pan_points(button, key, x, y) | ||
if points is not None: | ||
if self.orientation == 'horizontal': | ||
self.norm.vmin, self.norm.vmax = points[:, 0] | ||
elif self.orientation == 'vertical': | ||
self.norm.vmin, self.norm.vmax = points[:, 1] | ||
|
||
|
||
ColorbarBase = Colorbar # Backcompat API | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.