8000 Change colorbar approach agian, to simply locate the axes smaller if · matplotlib/matplotlib@0deed5f · GitHub
[go: up one dir, main page]

Skip to content

Commit 0deed5f

Browse files
committed
Change colorbar approach agian, to simply locate the axes smaller if
there are extends.
1 parent fb768c7 commit 0deed5f

File tree

3 files changed

+98
-126
lines changed

3 files changed

+98
-126
lines changed

lib/matplotlib/axes/_base.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2336,15 +2336,23 @@ def _update_line_limits(self, line):
23362336
updatex=updatex, updatey=updatey)
23372337
self.ignore_existing_data_limits = False
23382338

2339-
def add_patch(self, p):
2339+
def add_patch(self, p, relim=True):
23402340
"""
23412341
Add a `.Patch` to the Axes; return the patch.
2342+
2343+
Parameters
2344+
----------
2345+
p : `.Patch`
2346+
Patch to add to the axes.
2347+
relim : bool, default True
2348+
Whether the patch triggers an axes relim.
23422349
"""
23432350
self._deprecate_noninstance('add_patch', mpatches.Patch, p=p)
23442351
self._set_artist_props(p)
23452352
if p.get_clip_path() is None:
23462353
p.set_clip_path(self.patch)
2347-
self._update_patch_limits(p)
2354+
if relim:
2355+
self._update_patch_limits(p)
23482356
self._children.append(p)
23492357
p._remove_method = self._children.remove
23502358
return p

lib/matplotlib/colorbar.py

Lines changed: 72 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -206,96 +206,12 @@ def _set_ticks_on_axis_warn(*args, **kw):
206206
_api.warn_external("Use the colorbar set_ticks() method instead.")
207207

208208

209-
class ColorbarAxes(Axes):
210-
"""
211-
ColorbarAxes packages two axes, a parent axes that takes care of
212-
positioning the axes, and an inset_axes that takes care of the drawing,
213-
labels, ticks, etc. The inset axes is used as a way to properly
214-
position the extensions (triangles or rectangles) that are used to indicate
215-
over/under colors.
216-
217-
Users should not normally instantiate this class, but it is the class
218-
returned by ``cbar = fig.colorbar(im); cax = cbar.ax``.
219-
"""
220-
def __init__(self, parent, userax=True):
221-
"""
222-
Parameters
223-
----------
224-
parent : Axes
225-
Axes that specifies the position of the colorbar.
226-
userax : boolean
227-
True if the user passed `.Figure.colorbar` the axes manually.
228-
"""
229-
230-
fig = parent.figure
231-
if userax:
232-
# copy position:
233-
outer_ax = fig.add_axes(parent.get_position())
234-
# copy the locator if one exists:
235-
outer_ax._axes_locator = parent._axes_locator
236-
# if the parent is a child of another axes, swap these...
237-
if (parent._axes is not None and
238-
parent in parent._axes.child_axes):
239-
parent._axes.add_child_axes(outer_ax)
240-
outer_ax._axes.child_axes.remove(parent)
241-
else:
242-
try:
243-
parent.remove()
244-
except ValueError:
245-
pass # Already removed
246-
else:
247-
outer_ax = parent
248-
249-
# swap axes in the stack if its in there:
250-
if outer_ax in fig._localaxes:
251-
fig._localaxes.remove(outer_ax)
252-
fig._axstack.remove(outer_ax)
253-
fig._localaxes.add(self)
254-
fig._axstack.add(self)
255-
inner_ax = outer_ax.inset_axes([0, 0, 1, 1])
256-
self.__dict__.update(inner_ax.__dict__)
257-
258-
self.outer_ax = outer_ax
259-
self.inner_ax = inner_ax
260-
261-
self.outer_ax.xaxis.set_visible(False)
262-
self.outer_ax.yaxis.set_visible(False)
263-
self.outer_ax.set_facecolor('none')
264-
self.outer_ax.tick_params = self.inner_ax.tick_params
265-
self.outer_ax.set_xticks = self.inner_ax.set_xticks
266-
self.outer_ax.set_yticks = self.inner_ax.set_yticks
267-
for attr in ["get_position", "set_aspect",
268-
F438 "_remove_method", "_set_position",
269-
"set_position", "cla", "draw"]:
270-
setattr(self, attr, getattr(self.outer_ax, attr))
271-
self._colorbar_info = None # used for mpl-created axes
272-
if hasattr(self.outer_ax, "get_subplotspec"):
273-
attr = "get_subplotspec"
274-
setattr(self, attr, getattr(self.outer_ax, attr))
275-
276-
if userax:
277-
self._colorbar_info = 'user'
278-
# point the parent's methods all at this axes...
279-
origdict = parent.__dict__
280-
parent.__dict__ = self.__dict__
281-
for key in origdict.keys():
282-
if key not in parent.__dict__:
283-
parent.__dict__[key] = origdict[key]
284-
285-
def _set_inner_bounds(self, bounds):
286-
"""
287-
Change the inset_axes location...
288-
"""
289-
self.inner_ax._axes_locator = _TransformedBoundsLocator(
290-
bounds, self.outer_ax.transAxes)
291-
292-
293209
class _ColorbarSpine(mspines.Spine):
294210
def __init__(self, axes):
295211
self._ax = axes
296212
super().__init__(axes, 'colorbar',
297213
mpath.Path(np.empty((0, 2)), closed=True))
298-
mpatches.Patch.set_transform(self, axes.outer_ax.transAxes)
214+
mpatches.Patch.set_transform(self, axes.transAxes)
299215

300216
def get_window_extent(self, renderer=None):
301217
# This Spine has no Axis associated with it, and doesn't need to adjust
@@ -314,6 +230,51 @@ def draw(self, renderer):
314230
return ret
315231

316232

233+
class _ColorbarLocator:
234+
def __init__(self, cbar):
235+
"""
236+
*bounds* (a ``[l, b, w, h]`` rectangle) and *transform* together
237+
specify the position of the inset axes.
238+
"""
239+
self._cbar = cbar
240+
self._orig_locator = cbar.ax._axes_locator
241+
242+
def __call__(self, ax, renderer):
243+
# Subtracting transSubfigure will typically rely on inverted(),
244+
# freezing the transform; thus, this needs to be delayed until draw
245+
# time as transSubfigure may otherwise change after this is evaluated.
246+
pos = ax.get_position(original=True)
247+
if self._orig_locator is not None:
248+
pos = self._orig_locator(ax, renderer)
249+
if self._cbar.extend == 'neither':
250+
return pos
251+
else:
252+
y, extendlen = self._cbar._proportional_y()
253+
if not self._cbar._extend_lower():
254+
extendlen[0] = 0
255+
if not self._cbar._extend_upper():
256+
extendlen[1] = 0
257+
len = sum(extendlen) + 1
258+
shrink = 1 / len
259+
offset = extendlen[0] / len
260+
# we need to reset the aspect ratio of the axes to account fo the extends...
261+
if not self._cbar._userax:
262+
aspect = ax._colorbar_info['aspect']
263+
else:
264+
aspect = False
265+
if self._cbar.orientation == 'vertical':
266+
if aspect:
267+
ax.set_aspect(aspect*shrink)
268+
offset = offset * pos.height
269+
pos = pos.shrunk(1, shrink).translated(0, offset)
270+
else:
271+
if aspect:
272+
ax.set_aspect(aspect/shrink)
273+
offset = offset * pos.width
274+
pos = pos.shrunk(shrink, 1).translated(offset, 0)
275+
return pos
276+
277+
317278
class Colorbar:
318279
r"""
319280
Draw a colorbar in an existing axes.
@@ -413,7 +374,7 @@ def __init__(self, ax, mappable=None, *, cmap=None,
413374
extendfrac=None,
414375
extendrect=False,
415376
label='',
416-
userax=False,
377+
userax=True,
417378
):
418379

419380
if mappable is None:
@@ -452,9 +413,9 @@ def __init__(self, ax, mappable=None, *, cmap=None,
452413
_api.check_in_list(
453414
['uniform', 'proportional'], spacing=spacing)
454415

455-
# wrap the axes so that it can be positioned as an inset axes:
456-
ax = ColorbarAxes(ax, userax=userax)
457416
self.ax = ax
417+
self._userax = userax
418+
self.ax._axes_locator = _ColorbarLocator(self)
458419
ax.set(navigate=False)
459420

460421
if extend is None:
@@ -487,10 +448,8 @@ def __init__(self, ax, mappable=None, *, cmap=None,
487448

488449
for spine in self.ax.spines.values():
489450
spine.set_visible(False)
490-
for spine in self.ax.outer_ax.spines.values():
491-
spine.set_visible(False)
492451
self.outline = self.ax.spines['outline'] = _ColorbarSpine(self.ax)
493-
452+
self._short_axis().set_visible(False)
494453
self.patch = mpatches.Polygon(
495454
np.empty((0, 2)),
496455
color=mpl.rcParams['axes.facecolor'], linewidth=0.01, zorder=-1)
@@ -649,29 +608,29 @@ def _do_extends(self, extendlen):
649608
elower = extendlen[0] if self._extend_lower() else 0
650609
eupper = extendlen[1] if self._extend_upper() else 0
651610
total_len = eupper + elower + 1
652-
elower = elower / total_len
653-
eupper = eupper / total_len
611+
elower = elower
612+
eupper = eupper
654613
inner_length = 1 / total_len
655614

656615
# make the inner axes smaller to make room for the extend rectangle
657-
top = elower + inner_length
616+
top = eupper + 1
658617

659618
# xyout is the outline of the colorbar including the extend patches:
660619
if not self.extendrect:
661620
# triangle:
662-
xyout = np.array([[0, elower], [0.5, 0], [1, elower],
663-
[1, top], [0.5, 1], [0, top], [0, elower]])
621+
xyout = np.array([[0, 0], [0.5, -elower], [1, 0],
622+
[1, 1], [0.5, top], [0, 1], [0, 0]])
664623
else:
665624
# rectangle:
666-
xyout = np.array([[0, elower], [0, 0], [1, 0], [1, elower],
667-
[1, top], [1, 1], [0, 1], [0, top],
668-
[0, elower]])
625+
xyout = np.array([[0, 0], [0, -elower], [1, -elower], [1, 0],
626+
[1, 1], [1, top], [0, top], [0, 1],
627+
[0, -elower]])
669628

670629
bounds = np.array([0.0, elower, 1.0, inner_length])
671630
if self.orientation == 'horizontal':
672631
bounds = bounds[[1, 0, 3, 2]]
673632
xyout = xyout[:, ::-1]
674-
self.ax._set_inner_bounds(bounds)
633+
#self.ax._set_inner_bounds(bounds)
675634

676635
# xyout is the path for the spine:
677636
self.outline.set_xy(xyout)
@@ -690,35 +649,35 @@ def _do_extends(self, extendlen):
690649
if self._extend_lower():
691650
if not self.extendrect:
692651
# triangle
693-
xy = np.array([[0.5, 0], [1, elower], [0, elower]])
652+
xy = np.array([[0.5, -elower], [1, 0], [0, 0]])
694653
else:
695654
# rectangle
696-
xy = np.array([[0, 0], [1., 0], [1, elower], [0, elower]])
655+
xy = np.array([[0, -elower], [1., -elower], [1, 0], [0, 0]])
697656
if self.orientation == 'horizontal':
698657
xy = xy[:, ::-1]
699658
# add the patch
700659
color = self.cmap(self.norm(self._values[0]))
701660
patch = mpatches.PathPatch(
702661
mpath.Path(xy), facecolor=color, linewidth=0,
703-
antialiased=False, transform=self.ax.outer_ax.transAxes,
704-
hatch=hatches[0])
705-
self.ax.outer_ax.add_patch(patch)
662+
antialiased=False, transform=self.ax.transAxes,
663+
hatch=hatches[0], clip_on=False)
664+
self.ax.add_patch(patch, relim=False)
706665
if self._extend_upper():
707666
if not self.extendrect:
708667
# triangle
709-
xy = np.array([[0.5, 1], [1, 1-eupper], [0, 1-eupper]])
668+
xy = np.array([[0.5, top], [1, 1], [0, 1]])
710669
else:
711670
# rectangle
712-
xy = np.array([[0, 1], [1, 1], [1, 1-eupper], [0, 1-eupper]])
671+
xy = np.array([[0, top], [1, top], [1, 1], [0, 1]])
713672
if self.orientation == 'horizontal':
714673
xy = xy[:, ::-1]
715674
# add the patch
716675
color = self.cmap(self.norm(self._values[-1]))
717676
patch = mpatches.PathPatch(
718677
mpath.Path(xy), facecolor=color,
719678
linewidth=0, antialiased=False,
720-
transform=self.ax.outer_ax.transAxes, hatch=hatches[-1])
721-
self.ax.outer_ax.add_patch(patch)
679+
transform=self.ax.transAxes, hatch=hatches[-1], clip_on=False)
680+
self.ax.add_patch(patch, relim=False)
722681
return
723682

724683
def add_lines(self, *args, **kwargs):
@@ -803,6 +762,10 @@ def add_lines(self, *args, **kwargs):
803762
self.ax.add_collection(col)
804763
self.stale = True
805764

765+
def set_scale(self, scale):
766+
self.ax.set_xscale(scale)
767+
self.ax.set_yscale(scale)
768+
806769
def update_ticks(self):
807770
"""
808771
37B7 Setup the ticks and ticklabels. This should not be needed by users.

0 commit comments

Comments
 (0)
0