8000 Mrg animation merge by tacaswell · Pull Request #7622 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

Mrg animation merge #7622

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
Dec 13, 2016
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
80d8dd8
DOC: partially numpydoc-ify animation module
tacaswell Dec 7, 2016
24c7aad
DOC: use auto summary in animation_api.rst
tacaswell Dec 8, 2016
e465fb7
DOC: start to add animation prose
tacaswell Dec 8, 2016
ff1e71e
DOC: address comments
tacaswell Dec 11, 2016
55017cd
DOC: re-work MovieWriter section a bit
tacaswell Dec 11, 2016
437386b
MNT: tweak MovieWriter.saving to be more cautious
tacaswell Dec 11, 2016
1a6c61c
DOC: address the rest of the comments
tacaswell Dec 11, 2016
8e8291c
DOC: Fix more typos and minor errors
tacaswell Dec 11, 2016
e3de3be
BUG: fix minpos handling and other log ticker problems
efiring Dec 9, 2016
8bdabcd
refactor LogFormatter classes for consistency, readability
efiring Dec 10, 2016
a8e7575
api_changes: add note about LogFormatter linthresh kwarg.
efiring Dec 10, 2016
aa36ec3
test for shared log axes
efiring Dec 10, 2016
93d09be
Merge pull request #7596 from anntzer/delay-fc-list-warning
QuLogic Dec 12, 2016
1a21bea
Merge pull request #7618 from samuelstjean/patch-1
tacaswell Dec 12, 2016
4c4779b
DOC: minor tweaks
tacaswell Dec 12, 2016
4177725
Merge pull request #7589 from tacaswell/doc_animation
dopplershift Dec 12, 2016
4d59447
Merge pull request #7598 from efiring/minpos_initial
tacaswell Dec 12, 2016
06dce26
API: convert string fontsize to points immediately
tacaswell Aug 30, 2016
2ddcc68
API: cache usetex value at text creation time
tacaswell Dec 3, 2016
23392f8
Merge pull request #7606 from tacaswell/mnt_more_paranoid_moviewriter…
efiring Dec 12, 2016
98e9fb2
STY: some whitespace cleanups
tacaswell Dec 3, 2016
bb37ab6
MNT: ensure that defaults are cached init
tacaswell Dec 3, 2016
a578628
STY: wrap long line
tacaswell Dec 4, 2016
b079583
MNT: remove None from value checks
tacaswell Dec 4, 2016
55c266c
MNT: set the family to rcParam value in init
tacaswell Dec 5, 2016
b6278e3
MNT: use else block to localize exceptions
tacaswell Dec 5, 2016
5f4eead
MNT: minor simplification
tacaswell Dec 12, 2016
f367003
Merge pull request #7007 from tacaswell/api_set_font_size_at_creation…
QuLogic Dec 12, 2016
bbe4fd8
Merge remote-tracking branch 'matplotlib/v2.x'
tacaswell Dec 13, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions doc/api/api_changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ the kwarg is None which internally sets it to the 'auto' string,
triggering a new algorithm for adjusting the maximum according
to the axis length relative to the ticklabel font size.

`matplotlib.ticker.LogFormatter` gains minor_thresholds kwarg
-------------------------------------------------------------
`matplotlib.ticker.LogFormatter`: two new kwargs
------------------------------------------------

Previously, minor ticks on log-scaled axes were not labeled by
default. An algorithm has been added to the
Expand All @@ -151,6 +151,9 @@ ticks between integer powers of the base. The algorithm uses
two parameters supplied in a kwarg tuple named 'minor_thresholds'.
See the docstring for further explanation.

To improve support for axes using `~matplotlib.ticker.SymmetricLogLocator`,
a 'linthresh' kwarg was added.


New defaults for 3D quiver function in mpl_toolkits.mplot3d.axes3d.py
---------------------------------------------------------------------
Expand Down
9 changes: 8 additions & 1 deletion lib/matplotlib/scale.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,10 @@ def limit_range_for_scale(self, vmin, vmax, minpos):
"""
Limit the domain to positive values.
"""
if not np.isfinite(minpos):
minpos = 1e-300 # This value should rarely if ever
# end up with a visible effect.

return (minpos if vmin <= 0 else vmin,
minpos if vmax <= 0 else vmax)

Expand Down Expand Up @@ -499,7 +503,10 @@ def limit_range_for_scale(self, vmin, vmax, minpos):
"""
Limit the domain to values between 0 and 1 (excluded).
"""
return (minpos if vmin <= 0 else minpos,
if not np.isfinite(minpos):
minpos = 1e-7 # This value should rarely if ever
# end up with a visible effect.
return (minpos if vmin <= 0 else vmin,
1 - minpos if vmax >= 1 else vmax)


Expand Down
19 changes: 19 additions & 0 deletions lib/matplotlib/tests/test_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,25 @@ def test_autoscale_tight():
assert_allclose(ax.get_xlim(), (-0.15, 3.15))
assert_allclose(ax.get_ylim(), (1.0, 4.0))


@cleanup(style='default')
def test_autoscale_log_shared():
# related to github #7587
# array starts at zero to trigger _minpos handling
x = np.arange(100, dtype=float)
fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True)
ax1.loglog(x, x)
ax2.semilogx(x, x)
ax1.autoscale(tight=True)
ax2.autoscale(tight=True)
plt.draw()
lims = (x[1], x[-1])
assert_allclose(ax1.get_xlim(), lims)
assert_allclose(ax1.get_ylim(), lims)
assert_allclose(ax2.get_xlim(), lims)
assert_allclose(ax2.get_ylim(), (x[0], x[-1]))


@cleanup(style='default')
def test_use_sticky_edges():
fig, ax = plt.subplots()
Expand Down
193 changes: 93 additions & 100 deletions lib/matplotlib/ticker.py
Original file line number Diff line number Diff line change
Expand Up @@ -902,10 +902,6 @@ def set_locs(self, locs=None):
self._sublabels = None
return

b = self._base

vmin, vmax = self.axis.get_view_interval()

# Handle symlog case:
linthresh = self._linthresh
if linthresh is None:
Expand All @@ -914,6 +910,18 @@ def set_locs(self, locs=None):
except AttributeError:
pass

vmin, vmax = self.axis.get_view_interval()
if vmin > vmax:
vmin, vmax = vmax, vmin

if linthresh is None and vmin <= 0:
# It's probably a colorbar with
# a format kwarg setting a LogFormatter in the manner
# that worked with 1.5.x, but that doesn't work now.
self._sublabels = set((1,)) # label powers of base
return

b = self._base
if linthresh is not None: # symlog
# Only compute the number of decades in the logarithmic part of the
# axis
Expand Down Expand Up @@ -943,37 +951,38 @@ def set_locs(self, locs=None):
# Label all integer multiples of base**n.
self._sublabels = set(np.arange(1, b + 1))

def _num_to_string(self, x, vmin, vmax):
if x > 10000:
s = '%1.0e' % x
elif x < 1:
s = '%1.0e' % x
else:
s = self.pprint_val(x, vmax - vmin)

def __call__(self, x, pos=None):
"""
Return the format for tick val `x`.
"""
vmin, vmax = self.axis.get_view_interval()
vmin, vmax = mtransforms.nonsingular(vmin, vmax, expander=0.05)
d = abs(vmax - vmin)
b = self._base
if x == 0.0:
if x == 0.0: # Symlog
return '0'

sign = np.sign(x)
x = abs(x)
b = self._base
# only label the decades
fx = math.log(x) / math.log(b)
is_x_decade = is_close_to_int(fx)
exponent = np.round(fx) if is_x_decade else np.floor(fx)
coeff = np.round(x / b ** exponent)

if self.labelOnlyBase and not is_x_decade:
return ''
if self._sublabels is not None and coeff not in self._sublabels:
return ''

if x > 10000:
s = '%1.0e' % x
elif x < 1:
s = '%1.0e' % x
else:
s = self.pprint_val(x, d)
if sign == -1:
s = '-%s' % s

vmin, vmax = self.axis.get_view_interval()
vmin, vmax = mtransforms.nonsingular(vmin, vmax, expander=0.05)
s = self._num_to_string(x, vmin, vmax)
return self.fix_minus(s)

def format_data(self, value):
Expand Down Expand Up @@ -1026,41 +1035,16 @@ class LogFormatterExponent(LogFormatter):
"""
Format values for log axis using ``exponent = log_base(value)``.
"""
def __call__(self, x, pos=None):
"""
Return the format for tick value `x`.
"""
vmin, vmax = self.axis.get_view_interval()
vmin, vmax = mtransforms.nonsingular(vmin, vmax, expander=0.05)
d = abs(vmax - vmin)
b = self._base
if x == 0:
return '0'
sign = np.sign(x)
x = abs(x)
# only label the decades
fx = math.log(x) / math.log(b)

is_x_decade = is_close_to_int(fx)
exponent = np.round(fx) if is_x_decade else np.floor(fx)
coeff = np.round(x / b ** exponent)

if self.labelOnlyBase and not is_x_decade:
return ''
if self._sublabels is not None and coeff not in self._sublabels:
return ''

def _num_to_string(self, x, vmin, vmax):
fx = math.log(x) / math.log(self._base)
if abs(fx) > 10000:
s = '%1.0g' % fx
elif abs(fx) < 1:
s = '%1.0g' % fx
else:
fd = math.log(abs(d)) / math.log(b)
fd = math.log(vmax - vmin) / math.log(self._base)
s = self.pprint_val(fx, fd)
if sign == -1:
s = '-%s' % s

return self.fix_minus(s)
return s


class LogFormatterMathtext(LogFormatter):
Expand All @@ -1082,35 +1066,34 @@ def __call__(self, x, pos=None):

The position `pos` is ignored.
"""
b = self._base
usetex = rcParams['text.usetex']

# only label the decades
if x == 0:
if x == 0: # Symlog
if usetex:
return '$0$'
else:
return '$%s$' % _mathdefault('0')

sign_string = '-' if x < 0 else ''
x = abs(x)
b = self._base

# only label the decades
fx = math.log(x) / math.log(b)
is_x_decade = is_close_to_int(fx)
exponent = np.round(fx) if is_x_decade else np.floor(fx)
coeff = np.round(x / b ** exponent)

if self.labelOnlyBase and not is_x_decade:
return ''
if self._sublabels is not None and coeff not in self._sublabels:
return ''

# use string formatting of the base if it is not an integer
if b % 1 == 0.0:
base = '%d' % b
else:
base = '%s' % b

if self.labelOnlyBase and not is_x_decade:
return ''
if self._sublabels is not None and coeff not in self._sublabels:
return ''

if not is_x_decade:
return self._non_decade_format(sign_string, base, fx, usetex)
else:
Expand Down Expand Up @@ -2032,36 +2015,41 @@ def view_limits(self, vmin, vmax):
'Try to choose the view limits intelligently'
b = self._base

if vmax < vmin:
vmin, vmax = vmax, vmin
vmin, vmax = self.nonsingular(vmin, vmax)

if self.axis.axes.name == 'polar':
vmax = math.ceil(math.log(vmax) / math.log(b))
vmin = b ** (vmax - self.numdecs)
return vmin, vmax

minpos = self.axis.get_minpos()

if minpos <= 0 or not np.isfinite(minpos):
raise ValueError(
"Data has no positive values, and therefore can not be "
"log-scaled.")

if vmin <= 0:
vmin = minpos

if rcParams['axes.autolimit_mode'] == 'round_numbers':
if not is_decade(vmin, self._base):
vmin = decade_down(vmin, self._base)
if not is_decade(vmax, self._base):
vmax = decade_up(vmax, self._base)

if vmin == vmax:
vmin = decade_down(vmin, self._base)
vmax = decade_up(vmax, self._base)
return vmin, vmax

result = mtransforms.nonsingular(vmin, vmax)
return result
def nonsingular(self, vmin, vmax):
if not np.isfinite(vmin) or not np.isfinite(vmax):
return 1, 10 # initial range, no data plotted yet

if vmin > vmax:
vmin, vmax = vmax, vmin
if vmax <= 0:
warnings.warn(
"Data has no positive values, and therefore cannot be "
"log-scaled.")
return 1, 10

minpos = self.axis.get_minpos()
if not np.isfinite(minpos):
minpos = 1e-300 # This should never take effect.
if vmin <= 0:
vmin = minpos
if vmin == vmax:
vmin = decade_down(vmin, self._base)
vmax = decade_up(vmax, self._base)
return vmin, vmax


class SymmetricalLogLocator(Locator):
Expand Down Expand Up @@ -2260,32 +2248,7 @@ def tick_values(self, vmin, vmax):
if hasattr(self.axis, 'axes') and self.axis.axes.name == 'polar':
raise NotImplementedError('Polar axis cannot be logit scaled yet')

# what to do if a window beyond ]0, 1[ is chosen
if vmin <= 0.0:
if self.axis is not None:
vmin = self.axis.get_minpos()

if (vmin <= 0.0) or (not np.isfinite(vmin)):
raise ValueError(
"Data has no values in ]0, 1[ and therefore can not be "
"logit-scaled.")

# NOTE: for vmax, we should query a property similar to get_minpos, but
# related to the maximal, less-than-one data point. Unfortunately,
# get_minpos is defined very deep in the BBox and updated with data,
# so for now we use the trick below.
if vmax >= 1.0:
if self.axis is not None:
vmax = 1 - self.axis.get_minpos()

if (vmax >= 1.0) or (not np.isfinite(vmax)):
raise ValueError(
"Data has no values in ]0, 1[ and therefore can not be "
"logit-scaled.")

if vmax < vmin:
vmin, vmax = vmax, vmin

vmin, vmax = self.nonsingular(vmin, vmax)
vmin = np.log10(vmin / (1 - vmin))
vmax = np.log10(vmax / (1 - vmax))

Expand Down Expand Up @@ -2320,6 +2283,36 @@ def tick_values(self, vmin, vmax):

return self.raise_if_exceeds(np.array(ticklocs))

def nonsingular(self, vmin, vmax):
initial_range = (1e-7, 1 - 1e-7)
if not np.isfinite(vmin) or not np.isfinite(vmax):
return initial_range # no data plotted yet

if vmin > vmax:
vmin, vmax = vmax, vmin

# what to do if a window beyond ]0, 1[ is chosen
if self.axis is not None:
minpos = self.axis.get_minpos()
if not np.isfinite(minpos):
return initial_range # again, no data plotted
else:
minpos = 1e-7 # should not occur in normal use

# NOTE: for vmax, we should query a property similar to get_minpos, but
# related to the maximal, less-than-one data point. Unfortunately,
# Bbox._minpos is defined very deep in the BBox and updated with data,
# so for now we use 1 - minpos as a substitute.

if vmin <= 0:
vmin = minpos
if vmax >= 1:
vmax = 1 - minpos
if vmin == vmax:
return 0.1 * vmin, 1 - 0.1 * vmin

return vmin, vmax


class AutoLocator(MaxNLocator):
def __init__(self):
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,7 @@ def __init__(self, points, **kwargs):
raise ValueError('Bbox points must be of the form '
'"[[x0, y0], [x1, y1]]".')
self._points = points
self._minpos = np.array([0.0000001, 0.0000001])
self._minpos = np.array([np.inf, np.inf])
self._ignore = True
# it is helpful in some contexts to know if the bbox is a
# default or has been mutated; we store the orig points to
Expand Down
0