Skip to content

Commit 5cfaad8

Browse files
author
Quentin Peter
committed
Merge remote-tracking branch 'upstream/main' into patch-2
2 parents 0938782 + 9844e9f commit 5cfaad8

File tree

24 files changed

+403
-181
lines changed

24 files changed

+403
-181
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
``AxisArtistHelper.delta1`` and ``AxisArtistHelper.delta2``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
... are deprecated with no replacement.

examples/mplot3d/wire3d_animation_sgskip.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def generate(X, Y, phi):
3939
for phi in np.linspace(0, 180. / np.pi, 100):
4040
# If a line collection is already remove it before drawing.
4141
if wframe:
42-
ax.collections.remove(wframe)
42+
wframe.remove()
4343

4444
# Plot the new wireframe and pause briefly before continuing.
4545
Z = generate(X, Y, phi)

examples/pie_and_polar_charts/bar_of_pie.py

+17-21
Original file line numberDiff line numberDiff line change
@@ -19,40 +19,36 @@
1919
fig.subplots_adjust(wspace=0)
2020

2121
# pie chart parameters
22-
ratios = [.27, .56, .17]
22+
overall_ratios = [.27, .56, .17]
2323
labels = ['Approve', 'Disapprove', 'Undecided']
2424
explode = [0.1, 0, 0]
2525
# rotate so that first wedge is split by the x-axis
26-
angle = -180 * ratios[0]
27-
ax1.pie(ratios, autopct='%1.1f%%', startangle=angle,
28-
labels=labels, explode=explode)
26+
angle = -180 * overall_ratios[0]
27+
wedges, *_ = ax1.pie(overall_ratios, autopct='%1.1f%%', startangle=angle,
28+
labels=labels, explode=explode)
2929

3030
# bar chart parameters
31-
32-
xpos = 0
33-
bottom = 0
34-
ratios = [.33, .54, .07, .06]
31+
age_ratios = [.33, .54, .07, .06]
32+
age_labels = ['Under 35', '35-49', '50-65', 'Over 65']
33+
bottom = 1
3534
width = .2
36-
colors = [[.1, .3, .5], [.1, .3, .3], [.1, .3, .7], [.1, .3, .9]]
3735

38-
for j in range(len(ratios)):
39-
height = ratios[j]
40-
ax2.bar(xpos, height, width, bottom=bottom, color=colors[j])
41-
ypos = bottom + ax2.patches[j].get_height() / 2
42-
bottom += height
43-
ax2.text(xpos, ypos, "%d%%" % (ax2.patches[j].get_height() * 100),
44-
ha='center')
36+
# Adding from the top matches the legend.
37+
for j, (height, label) in enumerate(reversed([*zip(age_ratios, age_labels)])):
38+
bottom -= height
39+
bc = ax2.bar(0, height, width, bottom=bottom, color='C0', label=label,
40+
alpha=0.1 + 0.25 * j)
41+
ax2.bar_label(bc, labels=[f"{height:.0%}"], label_type='center')
4542

4643
ax2.set_title('Age of approvers')
47-
ax2.legend(('50-65', 'Over 65', '35-49', 'Under 35'))
44+
ax2.legend()
4845
ax2.axis('off')
4946
ax2.set_xlim(- 2.5 * width, 2.5 * width)
5047

5148
# use ConnectionPatch to draw lines between the two plots
52-
# get the wedge data
53-
theta1, theta2 = ax1.patches[0].theta1, ax1.patches[0].theta2
54-
center, r = ax1.patches[0].center, ax1.patches[0].r
55-
bar_height = sum([item.get_height() for item in ax2.patches])
49+
theta1, theta2 = wedges[0].theta1, wedges[0].theta2
50+
center, r = wedges[0].center, wedges[0].r
51+
bar_height = sum(age_ratios)
5652

5753
# draw top connecting line
5854
x = r * np.cos(np.pi / 180 * theta2) + center[0]

examples/ticks/tick_xlabel_top.py

+21-16
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,32 @@
11
"""
2-
==========================================
3-
Set default x-axis tick labels on the top
4-
==========================================
2+
==================================
3+
Move x-axis tick labels to the top
4+
==================================
55
6-
We can use :rc:`xtick.labeltop` and :rc:`xtick.top` and :rc:`xtick.labelbottom`
7-
and :rc:`xtick.bottom` to control where on the axes ticks and their labels
8-
appear.
6+
`~.axes.Axes.tick_params` can be used to configure the ticks. *top* and
7+
*labeltop* control the visibility tick lines and labels at the top x-axis.
8+
To move x-axis ticks from bottom to top, we have to activate the top ticks
9+
and deactivate the bottom ticks::
910
10-
These properties can also be set in ``.matplotlib/matplotlibrc``.
11-
"""
11+
ax.tick_params(top=True, labeltop=True, bottom=False, labelbottom=False)
1212
13-
import matplotlib.pyplot as plt
14-
import numpy as np
13+
.. note::
14+
15+
If the change should be made for all future plots and not only the current
16+
Axes, you can adapt the respective config parameters
1517
18+
- :rc:`xtick.top`
19+
- :rc:`xtick.labeltop`
20+
- :rc:`xtick.bottom`
21+
- :rc:`xtick.labelbottom`
1622
17-
plt.rcParams['xtick.bottom'] = plt.rcParams['xtick.labelbottom'] = False
18-
plt.rcParams['xtick.top'] = plt.rcParams['xtick.labeltop'] = True
23+
"""
1924

20-
x = np.arange(10)
25+
import matplotlib.pyplot as plt
2126

2227
fig, ax = plt.subplots()
23-
24-
ax.plot(x)
25-
ax.set_title('xlabel top') # Note title moves to make room for ticks
28+
ax.plot(range(10))
29+
ax.tick_params(top=True, labeltop=True, bottom=False, labelbottom=False)
30+
ax.set_title('x-ticks moved to the top')
2631

2732
plt.show()

lib/matplotlib/_constrained_layout.py

-1
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,6 @@ def reposition_axes(layoutgrids, fig, renderer, *,
573573
# coordinates...
574574
ss = ax.get_subplotspec()
575575
gs = ss.get_gridspec()
576-
nrows, ncols = gs.get_geometry()
577576
if gs not in layoutgrids:
578577
return
579578

lib/matplotlib/axes/_axes.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -5624,8 +5624,11 @@ def _interp_grid(X):
56245624
return X, Y, C, shading
56255625

56265626
def _pcolor_grid_deprecation_helper(self):
5627-
if any(axis._major_tick_kw["gridOn"]
5628-
for axis in self._get_axis_list()):
5627+
grid_active = any(axis._major_tick_kw["gridOn"]
5628+
for axis in self._get_axis_list())
5629+
# explicit is-True check because get_axisbelow() can also be 'line'
5630+
grid_hidden_by_pcolor = self.get_axisbelow() is True
5631+
if grid_active and not grid_hidden_by_pcolor:
56295632
_api.warn_deprecated(
56305633
"3.5", message="Auto-removal of grids by pcolor() and "
56315634
"pcolormesh() is deprecated since %(since)s and will be "

lib/matplotlib/axes/_base.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ def _process_plot_format(fmt):
197197
i += 2
198198
else:
199199
raise ValueError(
200-
'Unrecognized character %c in format string' % c)
200+
f'Unrecognized character {c} in format string {fmt!r}')
201201

202202
if linestyle is None and marker is None:
203203
linestyle = mpl.rcParams['lines.linestyle']
@@ -708,9 +708,10 @@ def __repr__(self):
708708
fields += [f"label={self.get_label()!r}"]
709709
titles = []
710710
for k in ["left", "center", "right"]:
711-
title = self.get_title(loc=k)
712-
if title:
713-
titles.append(f"{k!r}:{title!r}")
711+
if hasattr(self, 'get_title'):
712+
title = self.get_title(loc=k)
713+
if title:
714+
titles.append(f"{k!r}:{title!r}")
714715
if titles:
715716
fields += ["title={" + ",".join(titles) + "}"]
716717
if self.get_xlabel():

lib/matplotlib/axis.py

+15-13
Original file line numberDiff line numberDiff line change
@@ -1823,9 +1823,17 @@ def set_ticks(self, ticks, labels=None, *, minor=False, **kwargs):
18231823
Parameters
18241824
----------
18251825
ticks : list of floats
1826-
List of tick locations.
1826+
List of tick locations. The axis `.Locator` is replaced by a
1827+
`~.ticker.FixedLocator`.
1828+
1829+
Some tick formatters will not label arbitrary tick positions;
1830+
e.g. log formatters only label decade ticks by default. In
1831+
such a case you can set a formatter explicitly on the axis
1832+
using `.Axis.set_major_formatter` or provide formatted
1833+
*labels* yourself.
18271834
labels : list of str, optional
1828-
List of tick labels. If not set, the labels show the data value.
1835+
List of tick labels. If not set, the labels are generated with
1836+
the axis tick `.Formatter`.
18291837
minor : bool, default: False
18301838
If ``False``, set the major ticks; if ``True``, the minor ticks.
18311839
**kwargs
@@ -2073,8 +2081,7 @@ def _update_label_position(self, renderer):
20732081
if self.label_position == 'bottom':
20742082
try:
20752083
spine = self.axes.spines['bottom']
2076-
spinebbox = spine.get_transform().transform_path(
2077-
spine.get_path()).get_extents()
2084+
spinebbox = spine.get_window_extent()
20782085
except KeyError:
20792086
# use axes if spine doesn't exist
20802087
spinebbox = self.axes.bbox
@@ -2084,12 +2091,10 @@ def _update_label_position(self, renderer):
20842091
self.label.set_position(
20852092
(x, bottom - self.labelpad * self.figure.dpi / 72)
20862093
)
2087-
20882094
else:
20892095
try:
20902096
spine = self.axes.spines['top']
2091-
spinebbox = spine.get_transform().transform_path(
2092-
spine.get_path()).get_extents()
2097+
spinebbox = spine.get_window_extent()
20932098
except KeyError:
20942099
# use axes if spine doesn't exist
20952100
spinebbox = self.axes.bbox
@@ -2336,13 +2341,11 @@ def _update_label_position(self, renderer):
23362341
# get bounding boxes for this axis and any siblings
23372342
# that have been set by `fig.align_ylabels()`
23382343
bboxes, bboxes2 = self._get_tick_boxes_siblings(renderer=renderer)
2339-
23402344
x, y = self.label.get_position()
23412345
if self.label_position == 'left':
23422346
try:
23432347
spine = self.axes.spines['left']
2344-
spinebbox = spine.get_transform().transform_path(
2345-
spine.get_path()).get_extents()
2348+
spinebbox = spine.get_window_extent()
23462349
except KeyError:
23472350
# use axes if spine doesn't exist
23482351
spinebbox = self.axes.bbox
@@ -2355,14 +2358,13 @@ def _update_label_position(self, renderer):
23552358
else:
23562359
try:
23572360
spine = self.axes.spines['right']
2358-
spinebbox = spine.get_transform().transform_path(
2359-
spine.get_path()).get_extents()
2361+
spinebbox = spine.get_window_extent()
23602362
except KeyError:
23612363
# use axes if spine doesn't exist
23622364
spinebbox = self.axes.bbox
2365+
23632366
bbox = mtransforms.Bbox.union(bboxes2 + [spinebbox])
23642367
right = bbox.x1
2365-
23662368
self.label.set_position(
23672369
(right + self.labelpad * self.figure.dpi / 72, y)
23682370
)

lib/matplotlib/backend_bases.py

-1
Original file line numberDiff line numberDiff line change
@@ -1528,7 +1528,6 @@ class Done(Exception):
15281528
def _draw(renderer): raise Done(renderer)
15291529

15301530
with cbook._setattr_cm(figure, draw=_draw), ExitStack() as stack:
1531-
orig_canvas = figure.canvas
15321531
if print_method is None:
15331532
fmt = figure.canvas.get_default_filetype()
15341533
# Even for a canvas' default output type, a canvas switch may be

lib/matplotlib/backends/_backend_tk.py

+18-8
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,9 @@ def enter_notify_event(self, event):
279279
guiEvent=event, xy=self._event_mpl_coords(event))
280280

281281
def button_press_event(self, event, dblclick=False):
282+
# set focus to the canvas so that it can receive keyboard events
283+
self._tkcanvas.focus_set()
284+
282285
num = getattr(event, 'num', None)
283286
if sys.platform == 'darwin': # 2 and 3 are reversed.
284287
num = {2: 3, 3: 2}.get(num, num)
@@ -387,6 +390,12 @@ def stop_event_loop(self):
387390
self._event_loop_id = None
388391
self._tkcanvas.quit()
389392

393+
def set_cursor(self, cursor):
394+
try:
395+
self._tkcanvas.configure(cursor=cursord[cursor])
396+
except tkinter.TclError:
397+
pass
398+
390399

391400
class FigureManagerTk(FigureManagerBase):
392401
"""
@@ -467,6 +476,7 @@ def destroy(*args):
467476
Gcf.destroy(self)
468477
self.window.protocol("WM_DELETE_WINDOW", destroy)
469478
self.window.deiconify()
479+
self.canvas._tkcanvas.focus_set()
470480
else:
471481
self.canvas.draw_idle()
472482
if mpl.rcParams['figure.raise_window']:
@@ -629,13 +639,6 @@ def remove_rubberband(self):
629639
lastrect = _api.deprecated("3.6")(
630640
property(lambda self: self.canvas._rubberband_rect))
631641

632-
def set_cursor(self, cursor):
633-
window = self.canvas.get_tk_widget().master
634-
try:
635-
window.configure(cursor=cursord[cursor])
636-
except tkinter.TclError:
637-
pass
638-
639642
def _set_image_for_button(self, button):
640643
"""
641644
Set the image for a button based on its pixel size.
@@ -840,8 +843,14 @@ def _rescale(self):
840843
def add_toolitem(
841844
self, name, group, position, image_file, description, toggle):
842845
frame = self._get_groupframe(group)
843-
button = NavigationToolbar2Tk._Button(self, name, image_file, toggle,
846+
buttons = frame.pack_slaves()
847+
if position >= len(buttons) or position < 0:
848+
before = None
849+
else:
850+
before = buttons[position]
851+
button = NavigationToolbar2Tk._Button(frame, name, image_file, toggle,
844852
lambda: self._button_click(name))
853+
button.pack_configure(before=before)
845854
if description is not None:
846855
ToolTip.createToolTip(button, description)
847856
self._toolitems.setdefault(name, [])
@@ -853,6 +862,7 @@ def _get_groupframe(self, group):
853862
self._add_separator()
854863
frame = tk.Frame(master=self, borderwidth=0)
855864
frame.pack(side=tk.LEFT, fill=tk.Y)
865+
frame._label_font = self._label_font
856866
self._groups[group] = frame
857867
return self._groups[group]
858868

lib/matplotlib/bezier.py

-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,6 @@ def find_bezier_t_intersecting_with_closedpath(
172172
if start_inside ^ middle_inside:
173173
t1 = middle_t
174174
end = middle
175-
end_inside = middle_inside
176175
else:
177176
t0 = middle_t
178177
start = middle

0 commit comments

Comments
 (0)