207 lines
5.5 KiB
Python
207 lines
5.5 KiB
Python
|
from matplotlib.cbook import MatplotlibDeprecationWarning
|
||
|
import matplotlib.pyplot as plt
|
||
|
from matplotlib.scale import (
|
||
|
LogTransform, InvertedLogTransform,
|
||
|
SymmetricalLogTransform)
|
||
|
from matplotlib.testing.decorators import check_figures_equal, image_comparison
|
||
|
|
||
|
import numpy as np
|
||
|
from numpy.testing import assert_allclose
|
||
|
import io
|
||
|
import pytest
|
||
|
|
||
|
|
||
|
@check_figures_equal()
|
||
|
def test_log_scales(fig_test, fig_ref):
|
||
|
ax_test = fig_test.add_subplot(122, yscale='log', xscale='symlog')
|
||
|
ax_test.axvline(24.1)
|
||
|
ax_test.axhline(24.1)
|
||
|
xlim = ax_test.get_xlim()
|
||
|
ylim = ax_test.get_ylim()
|
||
|
ax_ref = fig_ref.add_subplot(122, yscale='log', xscale='symlog')
|
||
|
ax_ref.set(xlim=xlim, ylim=ylim)
|
||
|
ax_ref.plot([24.1, 24.1], ylim, 'b')
|
||
|
ax_ref.plot(xlim, [24.1, 24.1], 'b')
|
||
|
|
||
|
|
||
|
def test_symlog_mask_nan():
|
||
|
# Use a transform round-trip to verify that the forward and inverse
|
||
|
# transforms work, and that they respect nans and/or masking.
|
||
|
slt = SymmetricalLogTransform(10, 2, 1)
|
||
|
slti = slt.inverted()
|
||
|
|
||
|
x = np.arange(-1.5, 5, 0.5)
|
||
|
out = slti.transform_non_affine(slt.transform_non_affine(x))
|
||
|
assert_allclose(out, x)
|
||
|
assert type(out) == type(x)
|
||
|
|
||
|
x[4] = np.nan
|
||
|
out = slti.transform_non_affine(slt.transform_non_affine(x))
|
||
|
assert_allclose(out, x)
|
||
|
assert type(out) == type(x)
|
||
|
|
||
|
x = np.ma.array(x)
|
||
|
out = slti.transform_non_affine(slt.transform_non_affine(x))
|
||
|
assert_allclose(out, x)
|
||
|
assert type(out) == type(x)
|
||
|
|
||
|
x[3] = np.ma.masked
|
||
|
out = slti.transform_non_affine(slt.transform_non_affine(x))
|
||
|
assert_allclose(out, x)
|
||
|
assert type(out) == type(x)
|
||
|
|
||
|
|
||
|
@image_comparison(['logit_scales.png'], remove_text=True)
|
||
|
def test_logit_scales():
|
||
|
fig, ax = plt.subplots()
|
||
|
|
||
|
# Typical extinction curve for logit
|
||
|
x = np.array([0.001, 0.003, 0.01, 0.03, 0.1, 0.2, 0.3, 0.4, 0.5,
|
||
|
0.6, 0.7, 0.8, 0.9, 0.97, 0.99, 0.997, 0.999])
|
||
|
y = 1.0 / x
|
||
|
|
||
|
ax.plot(x, y)
|
||
|
ax.set_xscale('logit')
|
||
|
ax.grid(True)
|
||
|
bbox = ax.get_tightbbox(fig.canvas.get_renderer())
|
||
|
assert np.isfinite(bbox.x0)
|
||
|
assert np.isfinite(bbox.y0)
|
||
|
|
||
|
|
||
|
def test_log_scatter():
|
||
|
"""Issue #1799"""
|
||
|
fig, ax = plt.subplots(1)
|
||
|
|
||
|
x = np.arange(10)
|
||
|
y = np.arange(10) - 1
|
||
|
|
||
|
ax.scatter(x, y)
|
||
|
|
||
|
buf = io.BytesIO()
|
||
|
fig.savefig(buf, format='pdf')
|
||
|
|
||
|
buf = io.BytesIO()
|
||
|
fig.savefig(buf, format='eps')
|
||
|
|
||
|
buf = io.BytesIO()
|
||
|
fig.savefig(buf, format='svg')
|
||
|
|
||
|
|
||
|
def test_logscale_subs():
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.set_yscale('log', subs=np.array([2, 3, 4]))
|
||
|
# force draw
|
||
|
fig.canvas.draw()
|
||
|
|
||
|
|
||
|
@image_comparison(['logscale_mask.png'], remove_text=True)
|
||
|
def test_logscale_mask():
|
||
|
# Check that zero values are masked correctly on log scales.
|
||
|
# See github issue 8045
|
||
|
xs = np.linspace(0, 50, 1001)
|
||
|
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.plot(np.exp(-xs**2))
|
||
|
fig.canvas.draw()
|
||
|
ax.set(yscale="log")
|
||
|
|
||
|
|
||
|
def test_extra_kwargs_raise_or_warn():
|
||
|
fig, ax = plt.subplots()
|
||
|
|
||
|
with pytest.warns(MatplotlibDeprecationWarning):
|
||
|
ax.set_yscale('linear', foo='mask')
|
||
|
|
||
|
with pytest.raises(TypeError):
|
||
|
ax.set_yscale('log', foo='mask')
|
||
|
|
||
|
with pytest.warns(MatplotlibDeprecationWarning):
|
||
|
ax.set_yscale('symlog', foo='mask')
|
||
|
|
||
|
|
||
|
def test_logscale_invert_transform():
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.set_yscale('log')
|
||
|
# get transformation from data to axes
|
||
|
tform = (ax.transAxes + ax.transData.inverted()).inverted()
|
||
|
|
||
|
# direct test of log transform inversion
|
||
|
inverted_transform = LogTransform(base=2).inverted()
|
||
|
assert isinstance(inverted_transform, InvertedLogTransform)
|
||
|
assert inverted_transform.base == 2
|
||
|
|
||
|
|
||
|
def test_logscale_transform_repr():
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.set_yscale('log')
|
||
|
repr(ax.transData)
|
||
|
repr(LogTransform(10, nonpositive='clip'))
|
||
|
|
||
|
|
||
|
@image_comparison(['logscale_nonpos_values.png'],
|
||
|
remove_text=True, tol=0.02, style='mpl20')
|
||
|
def test_logscale_nonpos_values():
|
||
|
np.random.seed(19680801)
|
||
|
xs = np.random.normal(size=int(1e3))
|
||
|
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2)
|
||
|
ax1.hist(xs, range=(-5, 5), bins=10)
|
||
|
ax1.set_yscale('log')
|
||
|
ax2.hist(xs, range=(-5, 5), bins=10)
|
||
|
ax2.set_yscale('log', nonpositive='mask')
|
||
|
|
||
|
xdata = np.arange(0, 10, 0.01)
|
||
|
ydata = np.exp(-xdata)
|
||
|
edata = 0.2*(10-xdata)*np.cos(5*xdata)*np.exp(-xdata)
|
||
|
|
||
|
ax3.fill_between(xdata, ydata - edata, ydata + edata)
|
||
|
ax3.set_yscale('log')
|
||
|
|
||
|
x = np.logspace(-1, 1)
|
||
|
y = x ** 3
|
||
|
yerr = x**2
|
||
|
ax4.errorbar(x, y, yerr=yerr)
|
||
|
|
||
|
ax4.set_yscale('log')
|
||
|
ax4.set_xscale('log')
|
||
|
|
||
|
|
||
|
def test_invalid_log_lims():
|
||
|
# Check that invalid log scale limits are ignored
|
||
|
fig, ax = plt.subplots()
|
||
|
ax.scatter(range(0, 4), range(0, 4))
|
||
|
|
||
|
ax.set_xscale('log')
|
||
|
original_xlim = ax.get_xlim()
|
||
|
with pytest.warns(UserWarning):
|
||
|
ax.set_xlim(left=0)
|
||
|
assert ax.get_xlim() == original_xlim
|
||
|
with pytest.warns(UserWarning):
|
||
|
ax.set_xlim(right=-1)
|
||
|
assert ax.get_xlim() == original_xlim
|
||
|
|
||
|
ax.set_yscale('log')
|
||
|
original_ylim = ax.get_ylim()
|
||
|
with pytest.warns(UserWarning):
|
||
|
ax.set_ylim(bottom=0)
|
||
|
assert ax.get_ylim() == original_ylim
|
||
|
with pytest.warns(UserWarning):
|
||
|
ax.set_ylim(top=-1)
|
||
|
assert ax.get_ylim() == original_ylim
|
||
|
|
||
|
|
||
|
@image_comparison(['function_scales.png'], remove_text=True, style='mpl20')
|
||
|
def test_function_scale():
|
||
|
def inverse(x):
|
||
|
return x**2
|
||
|
|
||
|
def forward(x):
|
||
|
return x**(1/2)
|
||
|
|
||
|
fig, ax = plt.subplots()
|
||
|
|
||
|
x = np.arange(1, 1000)
|
||
|
|
||
|
ax.plot(x, x)
|
||
|
ax.set_xscale('function', functions=(forward, inverse))
|
||
|
ax.set_xlim(1, 1000)
|