Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 81bf74e

Browse files
committed
ENH: If an axis has a non-None converter, don't allow another non-None
1 parent 37978a8 commit 81bf74e

File tree

6 files changed

+90
-15
lines changed

6 files changed

+90
-15
lines changed

lib/matplotlib/axes/_base.py

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
from six.moves import xrange
88

99
import itertools
10-
import warnings
10+
import logging
1111
import math
1212
from operator import attrgetter
13+
import warnings
1314

1415
import numpy as np
1516

@@ -38,6 +39,8 @@
3839
from matplotlib.rcsetup import cycler
3940
from matplotlib.rcsetup import validate_axisbelow
4041

42+
_log = logging.getLogger(__name__)
43+
4144
rcParams = matplotlib.rcParams
4245

4346
is_string_like = cbook.is_string_like
@@ -1002,7 +1005,7 @@ def cla(self):
10021005
else:
10031006
self.xaxis._set_scale('linear')
10041007
try:
1005-
self.set_xlim(0, 1)
1008+
self.set_xlim(0, 1, _converter=False)
10061009
except TypeError:
10071010
pass
10081011

@@ -1016,7 +1019,7 @@ def cla(self):
10161019
else:
10171020
self.yaxis._set_scale('linear')
10181021
try:
1019-
self.set_ylim(0, 1)
1022+
self.set_ylim(0, 1, _converter=False)
10201023
except TypeError:
10211024
pass
10221025

@@ -2377,6 +2380,7 @@ def autoscale_view(self, tight=None, scalex=True, scaley=True):
23772380
case, use :meth:`matplotlib.axes.Axes.relim` prior to calling
23782381
autoscale_view.
23792382
"""
2383+
_log.debug('Autoscaling x: %s y: %s', scalex, scaley)
23802384
if tight is not None:
23812385
self._tight = bool(tight)
23822386

@@ -2446,6 +2450,7 @@ def handle_single_axis(scale, autoscaleon, shared_axes, interval,
24462450

24472451
if not self._tight:
24482452
x0, x1 = locator.view_limits(x0, x1)
2453+
_log.debug('Autolims: %e %e', x0, x1)
24492454
set_bound(x0, x1)
24502455
# End of definition of internal function 'handle_single_axis'.
24512456

@@ -2923,6 +2928,7 @@ def set_xbound(self, lower=None, upper=None):
29232928
self.set_xlim(upper, lower, auto=None)
29242929
else:
29252930
self.set_xlim(lower, upper, auto=None)
2931+
self.set_xlim(lower, upper, auto=None)
29262932
else:
29272933
if lower < upper:
29282934
self.set_xlim(lower, upper, auto=None)
@@ -3028,15 +3034,19 @@ def set_xlim(self, left=None, right=None, emit=True, auto=False, **kw):
30283034
left = kw.pop('xmin')
30293035
if 'xmax' in kw:
30303036
right = kw.pop('xmax')
3037+
# _converter is private, usually True, but can be false
3038+
_converter = kw.pop('_converter', True)
30313039
if kw:
30323040
raise ValueError("unrecognized kwargs: %s" % list(kw))
30333041

30343042
if right is None and iterable(left):
30353043
left, right = left
30363044

3037-
self._process_unit_info(xdata=(left, right))
3038-
left = self._validate_converted_limits(left, self.convert_xunits)
3039-
right = self._validate_converted_limits(right, self.convert_xunits)
3045+
if _converter:
3046+
_log.debug('Converting xlim %s %s', left, right)
3047+
self._process_unit_info(xdata=(left, right))
3048+
left = self._validate_converted_limits(left, self.convert_xunits)
3049+
right = self._validate_converted_limits(right, self.convert_xunits)
30403050

30413051
old_left, old_right = self.get_xlim()
30423052
if left is None:
@@ -3352,14 +3362,20 @@ def set_ylim(self, bottom=None, top=None, emit=True, auto=False, **kw):
33523362
bottom = kw.pop('ymin')
33533363
if 'ymax' in kw:
33543364
top = kw.pop('ymax')
3365+
_converter = kw.pop('_converter', True)
33553366
if kw:
33563367
raise ValueError("unrecognized kwargs: %s" % list(kw))
33573368

33583369
if top is None and iterable(bottom):
33593370
bottom, top = bottom
33603371

3361-
bottom = self._validate_converted_limits(bottom, self.convert_yunits)
3362-
top = self._validate_converted_limits(top, self.convert_yunits)
3372+
if _converter:
3373+
_log.debug('Converting ylim %s %s', bottom, top)
3374+
self._process_unit_info(ydata=(bottom, top))
3375+
bottom = self._validate_converted_limits(bottom,
3376+
self.convert_yunits)
3377+
top = self._validate_converted_limits(top,
3378+
self.convert_yunits)
33633379

33643380
old_bottom, old_top = self.get_ylim()
33653381

lib/matplotlib/axis.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import six
88

99
import logging
10+
import warnings
1011

1112
from matplotlib import rcParams
1213
import matplotlib.artist as artist
@@ -22,7 +23,8 @@
2223
import matplotlib.transforms as mtransforms
2324
import matplotlib.units as munits
2425
import numpy as np
25-
import warnings
26+
27+
_log = logging.getLogger(__name__)
2628

2729
_log = logging.getLogger(__name__)
2830

@@ -1434,10 +1436,25 @@ def update_units(self, data):
14341436
if *data* is registered for unit conversion.
14351437
"""
14361438

1439+
_log.debug('update_units converter due to %s %s',
1440+
data, data.__class__,)
14371441
converter = munits.registry.get_converter(data)
1442+
_log.debug('new converter: %s', converter)
14381443
if converter is None:
1444+
_log.info('No converter found for this data')
14391445
return False
14401446

1447+
if self.converter is not None:
1448+
if self.converter == converter:
1449+
_log.debug('Axis already has a converter that matches '
1450+
'data units')
1451+
return True
1452+
else:
1453+
_log.info('Axis already has a converter, but it does '
1454+
'not match new data units.')
1455+
return False
1456+
1457+
14411458
neednew = self.converter != converter
14421459
self.converter = converter
14431460
default = self.converter.default_units(data, self)
@@ -1487,6 +1504,10 @@ def have_units(self):
14871504
return self.converter is not None or self.units is not None
14881505

14891506
def convert_units(self, x):
1507+
"""
1508+
convert the units given
1509+
"""
1510+
14901511
if self.converter is None:
14911512
self.converter = munits.registry.get_converter(x)
14921513

lib/matplotlib/dates.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@
122122
from six.moves import zip
123123
import re
124124
import time
125+
import logging
125126
import math
126127
import datetime
127128
import functools

lib/matplotlib/tests/test_dates.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,3 +607,14 @@ def test_tz_utc():
607607
def test_num2timedelta(x, tdelta):
608608
dt = mdates.num2timedelta(x)
609609
assert dt == tdelta
610+
611+
612+
def test_one_non_None_converter():
613+
# test that we only allow one non-None converter at once:
614+
base = datetime.datetime(2017, 1, 1, 0, 10, 0)
615+
time = [base - datetime.timedelta(days=x) for x in range(0, 3)]
616+
data = [0., 2., 4.]
617+
fig, ax = plt.subplots()
618+
ax.plot(time, data)
619+
with pytest.raises(AttributeError):
620+
ax.plot(['a', 'b'], [1., 2.])

lib/matplotlib/units.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,25 @@ def get_converter(self, x):
171171
return converter
172172

173173

174+
class DefaultConverter(ConversionInterface):
175+
"""
176+
Do-nothing converter to catch good entries and lock out other
177+
converters.
178+
"""
179+
@staticmethod
180+
def convert(obj, unit, axis):
181+
"""
182+
convert obj using unit for the specified axis. If obj is a sequence,
183+
return the converted sequence. The output must be a sequence of
184+
scalars that can be used by the numpy array layer
185+
"""
186+
return np.asarray(obj, dtype=np.float64)
187+
188+
174189
registry = Registry()
190+
registry[np.float64] = DefaultConverter()
191+
registry[np.float32] = DefaultConverter()
192+
registry[np.int32] = DefaultConverter()
193+
registry[np.int64] = DefaultConverter()
194+
registry[float] = DefaultConverter()
195+
registry[int] = DefaultConverter()

lib/mpl_toolkits/mplot3d/axes3d.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -612,15 +612,17 @@ def set_xlim3d(self, left=None, right=None, emit=True, auto=False, **kw):
612612
left = kw.pop('xmin')
613613
if 'xmax' in kw:
614614
right = kw.pop('xmax')
615+
_converter = kw.pop('_converter', True)
615616
if kw:
616617
raise ValueError("unrecognized kwargs: %s" % list(kw))
617618

618619
if right is None and cbook.iterable(left):
619620
left, right = left
620621

621-
self._process_unit_info(xdata=(left, right))
622-
left = self._validate_converted_limits(left, self.convert_xunits)
623-
right = self._validate_converted_limits(right, self.convert_xunits)
622+
if _converter:
623+
self._process_unit_info(xdata=(left, right))
624+
left = self._validate_converted_limits(left, self.convert_xunits)
625+
right = self._validate_converted_limits(right, self.convert_xunits)
624626

625627
old_left, old_right = self.get_xlim()
626628
if left is None:
@@ -664,15 +666,18 @@ def set_ylim3d(self, bottom=None, top=None, emit=True, auto=False, **kw):
664666
bottom = kw.pop('ymin')
665667
if 'ymax' in kw:
666668
top = kw.pop('ymax')
669+
_converter = kw.pop('_converter', True)
667670
if kw:
668671
raise ValueError("unrecognized kwargs: %s" % list(kw))
669672

670673
if top is None and cbook.iterable(bottom):
671674
bottom, top = bottom
672675

673-
self._process_unit_info(ydata=(bottom, top))
674-
bottom = self._validate_converted_limits(bottom, self.convert_yunits)
675-
top = self._validate_converted_limits(top, self.convert_yunits)
676+
if _converter:
677+
self._process_unit_info(ydata=(bottom, top))
678+
bottom = self._validate_converted_limits(bottom,
679+
self.convert_yunits)
680+
top = self._validate_converted_limits(top, self.convert_yunits)
676681

677682
old_bottom, old_top = self.get_ylim()
678683
if bottom is None:

0 commit comments

Comments
 (0)