Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf975291

Browse files
authored
Merge pull request#23267 from oscargus/colorbarlocation
Add location keyword argument to Colorbar
2 parents9dbcbe2 +8b4ad6c commitf975291

File tree

3 files changed

+114
-15
lines changed

3 files changed

+114
-15
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
``colorbar`` now has a *location* keyword argument
2+
==================================================
3+
4+
The ``colorbar`` method now supports a *location* keyword argument to more
5+
easily position the color bar. This is useful when providing your own inset
6+
axes using the *cax* keyword argument and behaves similar to the case where
7+
axes are not provided (where the *location* keyword is passed through).
8+
*orientation* and *ticklocation* are no longer required as they are
9+
determined by *location*. *ticklocation* can still be provided if the
10+
automatic setting is not preferred. (*orientation* can also be provided but
11+
must be compatible with the *location*.)
12+
13+
An example is:
14+
15+
..plot::
16+
:include-source: true
17+
18+
import matplotlib.pyplot as plt
19+
import numpy as np
20+
rng = np.random.default_rng(19680801)
21+
imdata = rng.random((10, 10))
22+
fig, ax = plt.subplots()
23+
im = ax.imshow(imdata)
24+
fig.colorbar(im, cax=ax.inset_axes([0, 1.05, 1, 0.05]),
25+
location='top')

‎lib/matplotlib/colorbar.py

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -246,14 +246,35 @@ class Colorbar:
246246
alpha : float
247247
The colorbar transparency between 0 (transparent) and 1 (opaque).
248248
249-
orientation : {'vertical', 'horizontal'}
249+
orientation : None or {'vertical', 'horizontal'}
250+
If None, use the value determined by *location*. If both
251+
*orientation* and *location* are None then defaults to 'vertical'.
250252
251253
ticklocation : {'auto', 'left', 'right', 'top', 'bottom'}
254+
The location of the colorbar ticks. The *ticklocation* must match
255+
*orientation*. For example, a horizontal colorbar can only have ticks
256+
at the top or the bottom. If 'auto', the ticks will be the same as
257+
*location*, so a colorbar to the left will have ticks to the left. If
258+
*location* is None, the ticks will be at the bottom for a horizontal
259+
colorbar and at the right for a vertical.
252260
253261
drawedges : bool
262+
Whether to draw lines at color boundaries.
254263
255264
filled : bool
265+
256266
%(_colormap_kw_doc)s
267+
268+
location : None or {'left', 'right', 'top', 'bottom'}
269+
Set the *orientation* and *ticklocation* of the colorbar using a
270+
single argument. Colorbars on the left and right are vertical,
271+
colorbars at the top and bottom are horizontal. The *ticklocation* is
272+
the same as *location*, so if *location* is 'top', the ticks are on
273+
the top. *orientation* and/or *ticklocation* can be provided as well
274+
and overrides the value set by *location*, but there will be an error
275+
for incompatible combinations.
276+
277+
.. versionadded:: 3.7
257278
"""
258279

259280
n_rasterize=50# rasterize solids if number of colors >= n_rasterize
@@ -264,7 +285,7 @@ def __init__(self, ax, mappable=None, *, cmap=None,
264285
alpha=None,
265286
values=None,
266287
boundaries=None,
267-
orientation='vertical',
288+
orientation=None,
268289
ticklocation='auto',
269290
extend=None,
270291
spacing='uniform',# uniform or proportional
@@ -275,6 +296,7 @@ def __init__(self, ax, mappable=None, *, cmap=None,
275296
extendfrac=None,
276297
extendrect=False,
277298
label='',
299+
location=None,
278300
):
279301

280302
ifmappableisNone:
@@ -305,14 +327,23 @@ def __init__(self, ax, mappable=None, *, cmap=None,
305327
mappable.colorbar_cid=mappable.callbacks.connect(
306328
'changed',self.update_normal)
307329

330+
location_orientation=_get_orientation_from_location(location)
331+
308332
_api.check_in_list(
309-
['vertical','horizontal'],orientation=orientation)
333+
[None,'vertical','horizontal'],orientation=orientation)
310334
_api.check_in_list(
311335
['auto','left','right','top','bottom'],
312336
ticklocation=ticklocation)
313337
_api.check_in_list(
314338
['uniform','proportional'],spacing=spacing)
315339

340+
iflocation_orientationisnotNoneandorientationisnotNone:
341+
iflocation_orientation!=orientation:
342+
raiseTypeError(
343+
"location and orientation are mutually exclusive")
344+
else:
345+
orientation=orientationorlocation_orientationor"vertical"
346+
316347
self.ax=ax
317348
self.ax._axes_locator=_ColorbarAxesLocator(self)
318349

@@ -365,7 +396,8 @@ def __init__(self, ax, mappable=None, *, cmap=None,
365396
self.__scale=None# linear, log10 for now. Hopefully more?
366397

367398
ifticklocation=='auto':
368-
ticklocation='bottom'iforientation=='horizontal'else'right'
399+
ticklocation=_get_ticklocation_from_orientation(
400+
orientation)iflocationisNoneelselocation
369401
self.ticklocation=ticklocation
370402

371403
self.set_label(label)
@@ -1330,25 +1362,36 @@ def drag_pan(self, button, key, x, y):
13301362

13311363
def_normalize_location_orientation(location,orientation):
13321364
iflocationisNone:
1333-
location=_api.check_getitem(
1334-
{None:"right","vertical":"right","horizontal":"bottom"},
1335-
orientation=orientation)
1365+
location=_get_ticklocation_from_orientation(orientation)
13361366
loc_settings=_api.check_getitem({
1337-
"left": {"location":"left","orientation":"vertical",
1338-
"anchor": (1.0,0.5),"panchor": (0.0,0.5),"pad":0.10},
1339-
"right": {"location":"right","orientation":"vertical",
1340-
"anchor": (0.0,0.5),"panchor": (1.0,0.5),"pad":0.05},
1341-
"top": {"location":"top","orientation":"horizontal",
1342-
"anchor": (0.5,0.0),"panchor": (0.5,1.0),"pad":0.05},
1343-
"bottom": {"location":"bottom","orientation":"horizontal",
1344-
"anchor": (0.5,1.0),"panchor": (0.5,0.0),"pad":0.15},
1367+
"left": {"location":"left","anchor":(1.0,0.5),
1368+
"panchor": (0.0,0.5),"pad":0.10},
1369+
"right": {"location":"right","anchor":(0.0,0.5),
1370+
"panchor": (1.0,0.5),"pad":0.05},
1371+
"top": {"location":"top","anchor":(0.5,0.0),
1372+
"panchor": (0.5,1.0),"pad":0.05},
1373+
"bottom": {"location":"bottom","anchor":(0.5,1.0),
1374+
"panchor": (0.5,0.0),"pad":0.15},
13451375
},location=location)
1376+
loc_settings["orientation"]=_get_orientation_from_location(location)
13461377
iforientationisnotNoneandorientation!=loc_settings["orientation"]:
13471378
# Allow the user to pass both if they are consistent.
13481379
raiseTypeError("location and orientation are mutually exclusive")
13491380
returnloc_settings
13501381

13511382

1383+
def_get_orientation_from_location(location):
1384+
return_api.check_getitem(
1385+
{None:None,"left":"vertical","right":"vertical",
1386+
"top":"horizontal","bottom":"horizontal"},location=location)
1387+
1388+
1389+
def_get_ticklocation_from_orientation(orientation):
1390+
return_api.check_getitem(
1391+
{None:"right","vertical":"right","horizontal":"bottom"},
1392+
orientation=orientation)
1393+
1394+
13521395
@_docstring.interpd
13531396
defmake_axes(parents,location=None,orientation=None,fraction=0.15,
13541397
shrink=1.0,aspect=20,**kwargs):

‎lib/matplotlib/tests/test_colorbar.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,3 +1157,34 @@ def test_title_text_loc():
11571157
# colorbar axes, including its extend triangles....
11581158
assert (cb.ax.title.get_window_extent(fig.canvas.get_renderer()).ymax>
11591159
cb.ax.spines['outline'].get_window_extent().ymax)
1160+
1161+
1162+
@check_figures_equal(extensions=["png"])
1163+
deftest_passing_location(fig_ref,fig_test):
1164+
ax_ref=fig_ref.add_subplot()
1165+
im=ax_ref.imshow([[0,1], [2,3]])
1166+
ax_ref.figure.colorbar(im,cax=ax_ref.inset_axes([0,1.05,1,0.05]),
1167+
orientation="horizontal",ticklocation="top")
1168+
ax_test=fig_test.add_subplot()
1169+
im=ax_test.imshow([[0,1], [2,3]])
1170+
ax_test.figure.colorbar(im,cax=ax_test.inset_axes([0,1.05,1,0.05]),
1171+
location="top")
1172+
1173+
1174+
@pytest.mark.parametrize("kwargs,error,message", [
1175+
({'location':'top','orientation':'vertical'},TypeError,
1176+
"location and orientation are mutually exclusive"),
1177+
({'location':'top','orientation':'vertical','cax':True},TypeError,
1178+
"location and orientation are mutually exclusive"),# Different to above
1179+
({'ticklocation':'top','orientation':'vertical','cax':True},
1180+
ValueError,"'top' is not a valid value for position"),
1181+
({'location':'top','extendfrac': (0,None)},ValueError,
1182+
"invalid value for extendfrac"),
1183+
])
1184+
deftest_colorbar_errors(kwargs,error,message):
1185+
fig,ax=plt.subplots()
1186+
im=ax.imshow([[0,1], [2,3]])
1187+
ifkwargs.get('cax',None)isTrue:
1188+
kwargs['cax']=ax.inset_axes([0,1.05,1,0.05])
1189+
withpytest.raises(error,match=message):
1190+
fig.colorbar(im,**kwargs)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp