8000 Merge branch 'master' of https://github.com/matplotlib/matplotlib int… · matplotlib/matplotlib@2bf76d7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2bf76d7

Browse files
committed
Merge branch 'master' of https://github.com/matplotlib/matplotlib into axes_iob
2 parents ba8a882 + d0deb47 commit 2bf76d7

File tree

10 files changed

+129
-60
lines changed

10 files changed

+129
-60
lines changed

examples/lines_bars_and_markers/line_styles_reference.py

Lines changed: 0 additions & 24 deletions
This file was deleted.

examples/lines_bars_and_markers/linestyles.py

Lines changed: 50 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,50 +3,70 @@
33
Linestyles
44
==========
55
6-
This examples showcases different linestyles copying those of Tikz/PGF.
6+
Simple linestyles can be defined using the strings "solid", "dotted", "dashed"
7+
or "dashdot". More refined control can be achieved by providing a dash tuple
8+
``(offset, (on_off_seq))``. For example, ``(0, (3, 10, 1, 15))`` means
9+
(3pt line, 10pt space, 1pt line, 15pt space) with no offset. See also
10+
`.Line2D.set_linestyle`.
11+
12+
*Note*: The dash style can also be configured via `.Line2D.set_dashes`
13+
as shown in :doc:`/gallery/lines_bars_and_markers/line_demo_dash_control`
14+
and passing a list of dash sequences using the keyword *dashes* to the
15+
cycler in :doc:`property_cycle </tutorials/intermediate/color_cycle>`.
716
"""
817
import numpy as np
918
import matplotlib.pyplot as plt
8000
10-
from collections import OrderedDict
1119
from matplotlib.transforms import blended_transform_factory
1220

13-
linestyles = OrderedDict(
14-
[('solid', (0, ())),
15-
('loosely dotted', (0, (1, 10))),
16-
('dotted', (0, (1, 5))),
17-
('densely dotted', (0, (1, 1))),
21+
linestyle_str = [
22+
('solid', 'solid'), # Same as (0, ()) or '-'
23+
('dotted', 'dotted'), # Same as (0, (1, 1)) or '.'
24+
('dashed', 'dashed'), # Same as '--'
25+
('dashdot', 'dashdot')] # Same as '-.'
1826

19-
('loosely dashed', (0, (5, 10))),
20-
('dashed', (0, (5, 5))),
21-
('densely dashed', (0, (5, 1))),
27+
linestyle_tuple = [
28+
('loosely dotted', (0, (1, 10))),
29+
('dotted', (0, (1, 1))),
30+
('densely dotted', (0, (1, 1))),
2231

23-
('loosely dashdotted', (0, (3, 10, 1, 10))),
24-
('dashdotted', (0, (3, 5, 1, 5))),
25-
('densely dashdotted', (0, (3, 1, 1, 1))),
32+
('loosely dashed', (0, (5, 10))),
33+
('dashed', (0, (5, 5))),
34+
('densely dashed', (0, (5, 1))),
35+
36+
('loosely dashdotted', (0, (3, 10, 1, 10))),
37+
('dashdotted', (0, (3, 5, 1, 5))),
38+
('densely dashdotted', (0, (3, 1, 1, 1))),
2639

27-
('loosely dashdotdotted', (0, (3, 10, 1, 10, 1, 10))),
2840
('dashdotdotted', (0, (3, 5, 1, 5, 1, 5))),
29-
('densely dashdotdotted', (0, (3, 1, 1, 1, 1, 1)))])
41+
('loosely dashdotdotted', (0, (3, 10, 1, 10, 1, 10))),
42+
('densely dashdotdotted', (0, (3, 1, 1, 1, 1, 1)))]
43+
44+
45+
def plot_linestyles(ax, linestyles):
46+
X, Y = np.linspace(0, 100, 10), np.zeros(10)
47+
yticklabels = []
48+
49+
for i, (name, linestyle) in enumerate(linestyles):
50+
ax.plot(X, Y+i, linestyle=linestyle, linewidth=1.5, color='black')
51+
yticklabels.append(name)
3052

53+
ax.set(xticks=[], ylim=(-0.5, len(linestyles)-0.5),
54+
yticks=np.arange(len(linestyles)), yticklabels=yticklabels)
3155

32-
plt.figure(figsize=(10, 6))
33-
ax = plt.subplot(1, 1, 1)
56+
# For each line style, add a text annotation with a small offset from
57+
# the reference point (0 in Axes coords, y tick value in Data coords).
58+
reference_transform = blended_transform_factory(ax.transAxes, ax.transData)
59+
for i, (name, linestyle) in enumerate(linestyles):
60+
ax.annotate(repr(linestyle), xy=(0.0, i), xycoords=reference_transform,
61+
xytext=(-6, -12), textcoords='offset points', color="blue",
62+
fontsize=8, ha="right", family="monospace")
3463

35-
X, Y = np.linspace(0, 100, 10), np.zeros(10)
36-
for i, (name, linestyle) in enumerate(linestyles.items()):
37-
ax.plot(X, Y+i, linestyle=linestyle, linewidth=1.5, color='black')
3864

39-
ax.set_ylim(-0.5, len(linestyles)-0.5)
40-
plt.yticks(np.arange(len(linestyles)), linestyles.keys())
41-
plt.xticks([])
65+
fig, (ax0, ax1) = plt.subplots(2, 1, gridspec_kw={'height_ratios': [1, 3]},
66+
figsize=(10, 8))
4267

43-
# For each line style, add a text annotation with a small offset from
44-
# the reference point (0 in Axes coords, y tick value in Data coords).
45-
reference_transform = blended_transform_factory(ax.transAxes, ax.transData)
46-
for i, (name, linestyle) in enumerate(linestyles.items()):
47-
ax.annotate(str(linestyle), xy=(0.0, i), xycoords=reference_transform,
48-
xytext=(-6, -12), textcoords='offset points', color="blue",
49-
fontsize=8, ha="right", family="monospace")
68+
plot_linestyles(ax0, linestyle_str[::-1])
69+
plot_linestyles(ax1, linestyle_tuple[::-1])
5070

5171
plt.tight_layout()
5272
plt.show()

lib/matplotlib/axes/_axes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import collections
1+
import collections.abc
22
import functools
33
import itertools
44
import logging

lib/matplotlib/axis.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,10 +1578,12 @@ def set_major_locator(self, locator):
15781578
locator : ~matplotlib.ticker.Locator
15791579
"""
15801580
if not isinstance(locator, mticker.Locator):
1581-
raise TypeError("formatter argument should be instance of "
1581+
raise TypeError("locator argument should be instance of "
15821582
"matplotlib.ticker.Locator")
15831583
self.isDefault_majloc = False
15841584
self.major.locator = locator
1585+
if self.major.formatter:
1586+
self.major.formatter._set_locator(locator)
15851587
locator.set_axis(self)
15861588
self.stale = True
15871589

@@ -1594,10 +1596,12 @@ def set_minor_locator(self, locator):
15941596
locator : ~matplotlib.ticker.Locator
15951597
"""
15961598
if not isinstance(locator, mticker.Locator):
1597-
raise TypeError("formatter argument should be instance of "
1599+
raise TypeError("locator argument should be instance of "
15981600
"matplotlib.ticker.Locator")
15991601
self.isDefault_minloc = False
16001602
self.minor.locator = locator
1603+
if self.minor.formatter:
1604+
self.minor.formatter._set_locator(locator)
16011605
locator.set_axis(self)
16021606
self.stale = True
16031607

lib/matplotlib/colorbar.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ def __init__(self, ax, cmap=None,
386386
self.outline = None
387387
self.patch = None
388388
self.dividers = None
389+
self._manual_tick_data_values = None
389390

390391
if ticklocation == 'auto':
391392
ticklocation = 'bottom' if orientation == 'horizontal' else 'right'
@@ -573,7 +574,17 @@ def set_ticks(self, ticks, update_ticks=True):
573574

574575
def get_ticks(self, minor=False):
575576
"""Return the x ticks as a list of locations"""
576-
return self._tick_data_values
577+
if self._manual_tick_data_values is None:
578+
ax = self.ax
579+
if self.orientation == 'vertical':
580+
long_axis, short_axis = ax.yaxis, ax.xaxis
581+
else:
582+
long_axis, short_axis = ax.xaxis, ax.yaxis
583+
return long_axis.get_majorticklocs()
584+
else:
585+
# We made the axes manually, the old way, and the ylim is 0-1,
586+
# so the majorticklocs are in those units, not data units.
587+
return self._manual_tick_data_values
577588

578589
def set_ticklabels(self, ticklabels, update_ticks=True):
579590
"""
@@ -755,7 +766,7 @@ def _ticker(self, locator, formatter):
755766
else:
756767
eps = (intv[1] - intv[0]) * 1e-10
757768
b = b[(b <= intv[1] + eps) & (b >= intv[0] - eps)]
758-
self._tick_data_values = b
769+
self._manual_tick_data_values = b
759770
ticks = self._locate(b)
760771
formatter.set_locs(b)
761772
ticklabels = [formatter(t, i) for i, t in enumerate(b)]

lib/matplotlib/dates.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -820,8 +820,14 @@ def __init__(self, locator, tz=None, defaultfmt='%Y-%m-%d'):
820820
1. / (MUSECONDS_PER_DAY):
821821
rcParams['date.autoformatter.microsecond']}
822822

823+
def _set_locator(self, locator):
824+
self._locator = locator
825+
823826
def __call__(self, x, pos=None):
824-
locator_unit_scale = float(self._locator._get_unit())
827+
try:
828+
locator_unit_scale = float(self._locator._get_unit())
829+
except AttributeError:
830+
locator_unit_scale = 1
825831
# Pick the first scale which is greater than the locator unit.
826832
fmt = next((fmt for scale, fmt in sorted(self.scaled.items())
827833
if scale >= locator_unit_scale),

lib/matplotlib/tests/test_colorbar.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,3 +436,13 @@ def test_colorbar_renorm():
436 179B 436
cbar.update_normal(im)
437437
assert np.isclose(cbar.vmin, z.min() * 1000)
438438
assert np.isclose(cbar.vmax, z.max() * 1000)
439+
440+
441+
def test_colorbar_get_ticks():
442+
with rc_context({'_internal.classic_mode': False}):
443+
444+
fig, ax = plt. subplots()
445+
np.random.seed(19680801)
446+
pc = ax.pcolormesh(np.random.rand(30, 30))
447+
cb = fig.colorbar(pc)
448+
np.testing.assert_allclose(cb.get_ticks(), [0.2, 0.4, 0.6, 0.8])

lib/matplotlib/tests/test_constrainedlayout.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,11 @@ def test_constrained_layout23():
380380
fig.suptitle("Suptitle{}".format(i))
381381

382382

383+
# This test occasionally fails the image comparison tests, so we mark as
384+
# flaky. Apparently the constraint solver occasionally doesn't fully
385+
# optimize. Would be nice if this were more deterministic...
386+
@pytest.mark.timeout(30)
387+
@pytest.mark.flaky(reruns=3)
383388
@image_comparison(baseline_images=['test_colorbar_location'],
384389
extensions=['png'], remove_text=True, style='mpl20')
385390
def test_colorbar_location():

lib/matplotlib/tests/test_dates.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import matplotlib.pyplot as plt
1212
from matplotlib.cbook import MatplotlibDeprecationWarning
1313
import matplotlib.dates as mdates
14+
import matplotlib.ticker as mticker
1415

1516

1617
def __has_pytz():
@@ -220,6 +221,38 @@ def test_DateFormatter():
220221
fig.autofmt_xdate()
221222

222223

224+
def test_locator_set_formatter():
225+
"""
226+
Test if setting the locator only will update the AutoDateFormatter to use
227+
the new locator.
228+
"""
229+
plt.rcParams["date.autoformatter.minute"] = "%d %H:%M"
230+
t = [datetime.datetime(2018, 9, 30, 8, 0),
231+
datetime.datetime(2018, 9, 30, 8, 59),
232+
datetime.datetime(2018, 9, 30, 10, 30)]
233+
x = [2, 3, 1]
234+
235+
fig, ax = plt.subplots()
236+
ax.plot(t, x)
237+
ax.xaxis.set_major_locator(mdates.MinuteLocator((0, 30)))
238+
fig.canvas.draw()
239+
ticklabels = [tl.get_text() for tl in ax.get_xticklabels()]
240+
expected = ['30 08:00', '30 08:30', '30 09:00',
241+
'30 09:30', '30 10:00', '30 10:30']
242+
assert ticklabels == expected
243+
244+
ax.xaxis.set_major_locator(mticker.NullLocator())
245+
ax.xaxis.set_minor_locator(mdates.MinuteLocator((5, 55)))
246+
decoy_loc = mdates.MinuteLocator((12, 27))
247+
ax.xaxis.set_minor_formatter(mdates.AutoDateFormatter(decoy_loc))
248+
249+
ax.xaxis.set_minor_locator(mdates.MinuteLocator((15, 45)))
250+
fig.canvas.draw()
251+
ticklabels = [tl.get_text() for tl in ax.get_xticklabels(which="minor")]
252+
expected = ['30 08:15', '30 08:45', '30 09:15', '30 09:45', '30 10:15']
253+
assert ticklabels == expected
254+
255+
223256
def test_date_formatter_strftime():
224257
"""
225258
Tests that DateFormatter matches datetime.strftime,

lib/matplotlib/ticker.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,10 @@ def fix_minus(self, s):
299299
"""
300300
return s
301301

302+
def _set_locat 57B6 or(self, locator):
303+
""" Subclasses may want to override this to set a locator. """
304+
pass
305+
302306

303307
class IndexFormatter(Formatter):
304308
"""

0 commit comments

Comments
 (0)
0