You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			388 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			388 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
import platform
 | 
						|
import sys
 | 
						|
 | 
						|
import numpy as np
 | 
						|
import pytest
 | 
						|
 | 
						|
from matplotlib import pyplot as plt
 | 
						|
from matplotlib.testing.decorators import image_comparison
 | 
						|
from matplotlib.testing.decorators import check_figures_equal
 | 
						|
 | 
						|
 | 
						|
def draw_quiver(ax, **kwargs):
 | 
						|
    X, Y = np.meshgrid(np.arange(0, 2 * np.pi, 1),
 | 
						|
                       np.arange(0, 2 * np.pi, 1))
 | 
						|
    U = np.cos(X)
 | 
						|
    V = np.sin(Y)
 | 
						|
 | 
						|
    Q = ax.quiver(U, V, **kwargs)
 | 
						|
    return Q
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.skipif(platform.python_implementation() != 'CPython',
 | 
						|
                    reason='Requires CPython')
 | 
						|
def test_quiver_memory_leak():
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
 | 
						|
    Q = draw_quiver(ax)
 | 
						|
    ttX = Q.X
 | 
						|
    orig_refcount = sys.getrefcount(ttX)
 | 
						|
    Q.remove()
 | 
						|
 | 
						|
    del Q
 | 
						|
 | 
						|
    assert sys.getrefcount(ttX) < orig_refcount
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.skipif(platform.python_implementation() != 'CPython',
 | 
						|
                    reason='Requires CPython')
 | 
						|
def test_quiver_key_memory_leak():
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
 | 
						|
    Q = draw_quiver(ax)
 | 
						|
 | 
						|
    qk = ax.quiverkey(Q, 0.5, 0.92, 2, r'$2 \frac{m}{s}$',
 | 
						|
                      labelpos='W',
 | 
						|
                      fontproperties={'weight': 'bold'})
 | 
						|
    orig_refcount = sys.getrefcount(qk)
 | 
						|
    qk.remove()
 | 
						|
    assert sys.getrefcount(qk) < orig_refcount
 | 
						|
 | 
						|
 | 
						|
def test_quiver_number_of_args():
 | 
						|
    X = [1, 2]
 | 
						|
    with pytest.raises(
 | 
						|
            TypeError,
 | 
						|
            match='takes from 2 to 5 positional arguments but 1 were given'):
 | 
						|
        plt.quiver(X)
 | 
						|
    with pytest.raises(
 | 
						|
            TypeError,
 | 
						|
            match='takes from 2 to 5 positional arguments but 6 were given'):
 | 
						|
        plt.quiver(X, X, X, X, X, X)
 | 
						|
 | 
						|
 | 
						|
def test_quiver_arg_sizes():
 | 
						|
    X2 = [1, 2]
 | 
						|
    X3 = [1, 2, 3]
 | 
						|
    with pytest.raises(
 | 
						|
            ValueError, match=('X and Y must be the same size, but '
 | 
						|
                               'X.size is 2 and Y.size is 3.')):
 | 
						|
        plt.quiver(X2, X3, X2, X2)
 | 
						|
    with pytest.raises(
 | 
						|
            ValueError, match=('Argument U has a size 3 which does not match '
 | 
						|
                               '2, the number of arrow positions')):
 | 
						|
        plt.quiver(X2, X2, X3, X2)
 | 
						|
    with pytest.raises(
 | 
						|
            ValueError, match=('Argument V has a size 3 which does not match '
 | 
						|
                               '2, the number of arrow positions')):
 | 
						|
        plt.quiver(X2, X2, X2, X3)
 | 
						|
    with pytest.raises(
 | 
						|
            ValueError, match=('Argument C has a size 3 which does not match '
 | 
						|
                               '2, the number of arrow positions')):
 | 
						|
        plt.quiver(X2, X2, X2, X2, X3)
 | 
						|
 | 
						|
 | 
						|
def test_no_warnings():
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
    X, Y = np.meshgrid(np.arange(15), np.arange(10))
 | 
						|
    U = V = np.ones_like(X)
 | 
						|
    phi = (np.random.rand(15, 10) - .5) * 150
 | 
						|
    ax.quiver(X, Y, U, V, angles=phi)
 | 
						|
    fig.canvas.draw()  # Check that no warning is emitted.
 | 
						|
 | 
						|
 | 
						|
def test_zero_headlength():
 | 
						|
    # Based on report by Doug McNeil:
 | 
						|
    # https://discourse.matplotlib.org/t/quiver-warnings/16722
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
    X, Y = np.meshgrid(np.arange(10), np.arange(10))
 | 
						|
    U, V = np.cos(X), np.sin(Y)
 | 
						|
    ax.quiver(U, V, headlength=0, headaxislength=0)
 | 
						|
    fig.canvas.draw()  # Check that no warning is emitted.
 | 
						|
 | 
						|
 | 
						|
@image_comparison(['quiver_animated_test_image.png'])
 | 
						|
def test_quiver_animate():
 | 
						|
    # Tests fix for #2616
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
    Q = draw_quiver(ax, animated=True)
 | 
						|
    ax.quiverkey(Q, 0.5, 0.92, 2, r'$2 \frac{m}{s}$',
 | 
						|
                 labelpos='W', fontproperties={'weight': 'bold'})
 | 
						|
 | 
						|
 | 
						|
@image_comparison(['quiver_with_key_test_image.png'])
 | 
						|
def test_quiver_with_key():
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
    ax.margins(0.1)
 | 
						|
    Q = draw_quiver(ax)
 | 
						|
    ax.quiverkey(Q, 0.5, 0.95, 2,
 | 
						|
                 r'$2\, \mathrm{m}\, \mathrm{s}^{-1}$',
 | 
						|
                 angle=-10,
 | 
						|
                 coordinates='figure',
 | 
						|
                 labelpos='W',
 | 
						|
                 fontproperties={'weight': 'bold', 'size': 'large'})
 | 
						|
 | 
						|
 | 
						|
@image_comparison(['quiver_single_test_image.png'], remove_text=True)
 | 
						|
def test_quiver_single():
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
    ax.margins(0.1)
 | 
						|
    ax.quiver([1], [1], [2], [2])
 | 
						|
 | 
						|
 | 
						|
def test_quiver_copy():
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
    uv = dict(u=np.array([1.1]), v=np.array([2.0]))
 | 
						|
    q0 = ax.quiver([1], [1], uv['u'], uv['v'])
 | 
						|
    uv['v'][0] = 0
 | 
						|
    assert q0.V[0] == 2.0
 | 
						|
 | 
						|
 | 
						|
@image_comparison(['quiver_key_pivot.png'], remove_text=True)
 | 
						|
def test_quiver_key_pivot():
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
 | 
						|
    u, v = np.mgrid[0:2*np.pi:10j, 0:2*np.pi:10j]
 | 
						|
 | 
						|
    q = ax.quiver(np.sin(u), np.cos(v))
 | 
						|
    ax.set_xlim(-2, 11)
 | 
						|
    ax.set_ylim(-2, 11)
 | 
						|
    ax.quiverkey(q, 0.5, 1, 1, 'N', labelpos='N')
 | 
						|
    ax.quiverkey(q, 1, 0.5, 1, 'E', labelpos='E')
 | 
						|
    ax.quiverkey(q, 0.5, 0, 1, 'S', labelpos='S')
 | 
						|
    ax.quiverkey(q, 0, 0.5, 1, 'W', labelpos='W')
 | 
						|
 | 
						|
 | 
						|
@image_comparison(['quiver_key_xy.png'], remove_text=True)
 | 
						|
def test_quiver_key_xy():
 | 
						|
    # With scale_units='xy', ensure quiverkey still matches its quiver.
 | 
						|
    # Note that the quiver and quiverkey lengths depend on the axes aspect
 | 
						|
    # ratio, and that with angles='xy' their angles also depend on the axes
 | 
						|
    # aspect ratio.
 | 
						|
    X = np.arange(8)
 | 
						|
    Y = np.zeros(8)
 | 
						|
    angles = X * (np.pi / 4)
 | 
						|
    uv = np.exp(1j * angles)
 | 
						|
    U = uv.real
 | 
						|
    V = uv.imag
 | 
						|
    fig, axs = plt.subplots(2)
 | 
						|
    for ax, angle_str in zip(axs, ('uv', 'xy')):
 | 
						|
        ax.set_xlim(-1, 8)
 | 
						|
        ax.set_ylim(-0.2, 0.2)
 | 
						|
        q = ax.quiver(X, Y, U, V, pivot='middle',
 | 
						|
                      units='xy', width=0.05,
 | 
						|
                      scale=2, scale_units='xy',
 | 
						|
                      angles=angle_str)
 | 
						|
        for x, angle in zip((0.2, 0.5, 0.8), (0, 45, 90)):
 | 
						|
            ax.quiverkey(q, X=x, Y=0.8, U=1, angle=angle, label='', color='b')
 | 
						|
 | 
						|
 | 
						|
@image_comparison(['barbs_test_image.png'], remove_text=True)
 | 
						|
def test_barbs():
 | 
						|
    x = np.linspace(-5, 5, 5)
 | 
						|
    X, Y = np.meshgrid(x, x)
 | 
						|
    U, V = 12*X, 12*Y
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
    ax.barbs(X, Y, U, V, np.hypot(U, V), fill_empty=True, rounding=False,
 | 
						|
             sizes=dict(emptybarb=0.25, spacing=0.2, height=0.3),
 | 
						|
             cmap='viridis')
 | 
						|
 | 
						|
 | 
						|
@image_comparison(['barbs_pivot_test_image.png'], remove_text=True)
 | 
						|
def test_barbs_pivot():
 | 
						|
    x = np.linspace(-5, 5, 5)
 | 
						|
    X, Y = np.meshgrid(x, x)
 | 
						|
    U, V = 12*X, 12*Y
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
    ax.barbs(X, Y, U, V, fill_empty=True, rounding=False, pivot=1.7,
 | 
						|
             sizes=dict(emptybarb=0.25, spacing=0.2, height=0.3))
 | 
						|
    ax.scatter(X, Y, s=49, c='black')
 | 
						|
 | 
						|
 | 
						|
@image_comparison(['barbs_test_flip.png'], remove_text=True)
 | 
						|
def test_barbs_flip():
 | 
						|
    """Test barbs with an array for flip_barb."""
 | 
						|
    x = np.linspace(-5, 5, 5)
 | 
						|
    X, Y = np.meshgrid(x, x)
 | 
						|
    U, V = 12*X, 12*Y
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
    ax.barbs(X, Y, U, V, fill_empty=True, rounding=False, pivot=1.7,
 | 
						|
             sizes=dict(emptybarb=0.25, spacing=0.2, height=0.3),
 | 
						|
             flip_barb=Y < 0)
 | 
						|
 | 
						|
 | 
						|
def test_barb_copy():
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
    u = np.array([1.1])
 | 
						|
    v = np.array([2.2])
 | 
						|
    b0 = ax.barbs([1], [1], u, v)
 | 
						|
    u[0] = 0
 | 
						|
    assert b0.u[0] == 1.1
 | 
						|
    v[0] = 0
 | 
						|
    assert b0.v[0] == 2.2
 | 
						|
 | 
						|
 | 
						|
def test_bad_masked_sizes():
 | 
						|
    """Test error handling when given differing sized masked arrays."""
 | 
						|
    x = np.arange(3)
 | 
						|
    y = np.arange(3)
 | 
						|
    u = np.ma.array(15. * np.ones((4,)))
 | 
						|
    v = np.ma.array(15. * np.ones_like(u))
 | 
						|
    u[1] = np.ma.masked
 | 
						|
    v[1] = np.ma.masked
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
    with pytest.raises(ValueError):
 | 
						|
        ax.barbs(x, y, u, v)
 | 
						|
 | 
						|
 | 
						|
def test_angles_and_scale():
 | 
						|
    # angles array + scale_units kwarg
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
    X, Y = np.meshgrid(np.arange(15), np.arange(10))
 | 
						|
    U = V = np.ones_like(X)
 | 
						|
    phi = (np.random.rand(15, 10) - .5) * 150
 | 
						|
    ax.quiver(X, Y, U, V, angles=phi, scale_units='xy')
 | 
						|
 | 
						|
 | 
						|
@image_comparison(['quiver_xy.png'], remove_text=True)
 | 
						|
def test_quiver_xy():
 | 
						|
    # simple arrow pointing from SW to NE
 | 
						|
    fig, ax = plt.subplots(subplot_kw=dict(aspect='equal'))
 | 
						|
    ax.quiver(0, 0, 1, 1, angles='xy', scale_units='xy', scale=1)
 | 
						|
    ax.set_xlim(0, 1.1)
 | 
						|
    ax.set_ylim(0, 1.1)
 | 
						|
    ax.grid()
 | 
						|
 | 
						|
 | 
						|
def test_quiverkey_angles():
 | 
						|
    # Check that only a single arrow is plotted for a quiverkey when an array
 | 
						|
    # of angles is given to the original quiver plot
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
 | 
						|
    X, Y = np.meshgrid(np.arange(2), np.arange(2))
 | 
						|
    U = V = angles = np.ones_like(X)
 | 
						|
 | 
						|
    q = ax.quiver(X, Y, U, V, angles=angles)
 | 
						|
    qk = ax.quiverkey(q, 1, 1, 2, 'Label')
 | 
						|
    # The arrows are only created when the key is drawn
 | 
						|
    fig.canvas.draw()
 | 
						|
    assert len(qk.verts) == 1
 | 
						|
 | 
						|
 | 
						|
def test_quiverkey_angles_xy_aitoff():
 | 
						|
    # GH 26316 and GH 26748
 | 
						|
    # Test that only one arrow will be plotted with non-cartesian
 | 
						|
    # when angles='xy' and/or scale_units='xy'
 | 
						|
 | 
						|
    # only for test purpose
 | 
						|
    # scale_units='xy' may not be a valid use case for non-cartesian
 | 
						|
    kwargs_list = [
 | 
						|
        {'angles': 'xy'},
 | 
						|
        {'angles': 'xy', 'scale_units': 'xy'},
 | 
						|
        {'scale_units': 'xy'}
 | 
						|
    ]
 | 
						|
 | 
						|
    for kwargs_dict in kwargs_list:
 | 
						|
 | 
						|
        x = np.linspace(-np.pi, np.pi, 11)
 | 
						|
        y = np.ones_like(x) * np.pi / 6
 | 
						|
        vx = np.zeros_like(x)
 | 
						|
        vy = np.ones_like(x)
 | 
						|
 | 
						|
        fig = plt.figure()
 | 
						|
        ax = fig.add_subplot(projection='aitoff')
 | 
						|
        q = ax.quiver(x, y, vx, vy, **kwargs_dict)
 | 
						|
        qk = ax.quiverkey(q, 0, 0, 1, '1 units')
 | 
						|
 | 
						|
        fig.canvas.draw()
 | 
						|
        assert len(qk.verts) == 1
 | 
						|
 | 
						|
 | 
						|
def test_quiverkey_angles_scale_units_cartesian():
 | 
						|
    # GH 26316
 | 
						|
    # Test that only one arrow will be plotted with normal cartesian
 | 
						|
    # when angles='xy' and/or scale_units='xy'
 | 
						|
 | 
						|
    kwargs_list = [
 | 
						|
        {'angles': 'xy'},
 | 
						|
        {'angles': 'xy', 'scale_units': 'xy'},
 | 
						|
        {'scale_units': 'xy'}
 | 
						|
    ]
 | 
						|
 | 
						|
    for kwargs_dict in kwargs_list:
 | 
						|
        X = [0, -1, 0]
 | 
						|
        Y = [0, -1, 0]
 | 
						|
        U = [1, -1, 1]
 | 
						|
        V = [1, -1, 0]
 | 
						|
 | 
						|
        fig, ax = plt.subplots()
 | 
						|
        q = ax.quiver(X, Y, U, V, **kwargs_dict)
 | 
						|
        ax.quiverkey(q, X=0.3, Y=1.1, U=1,
 | 
						|
                     label='Quiver key, length = 1', labelpos='E')
 | 
						|
        qk = ax.quiverkey(q, 0, 0, 1, '1 units')
 | 
						|
 | 
						|
        fig.canvas.draw()
 | 
						|
        assert len(qk.verts) == 1
 | 
						|
 | 
						|
 | 
						|
def test_quiver_setuvc_numbers():
 | 
						|
    """Check that it is possible to set all arrow UVC to the same numbers"""
 | 
						|
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
 | 
						|
    X, Y = np.meshgrid(np.arange(2), np.arange(2))
 | 
						|
    U = V = np.ones_like(X)
 | 
						|
 | 
						|
    q = ax.quiver(X, Y, U, V)
 | 
						|
    q.set_UVC(0, 1)
 | 
						|
 | 
						|
 | 
						|
def draw_quiverkey_zorder_argument(fig, zorder=None):
 | 
						|
    """Draw Quiver and QuiverKey using zorder argument"""
 | 
						|
    x = np.arange(1, 6, 1)
 | 
						|
    y = np.arange(1, 6, 1)
 | 
						|
    X, Y = np.meshgrid(x, y)
 | 
						|
    U, V = 2, 2
 | 
						|
 | 
						|
    ax = fig.subplots()
 | 
						|
    q = ax.quiver(X, Y, U, V, pivot='middle')
 | 
						|
    ax.set_xlim(0.5, 5.5)
 | 
						|
    ax.set_ylim(0.5, 5.5)
 | 
						|
    if zorder is None:
 | 
						|
        ax.quiverkey(q, 4, 4, 25, coordinates='data',
 | 
						|
                     label='U', color='blue')
 | 
						|
        ax.quiverkey(q, 5.5, 2, 20, coordinates='data',
 | 
						|
                     label='V', color='blue', angle=90)
 | 
						|
    else:
 | 
						|
        ax.quiverkey(q, 4, 4, 25, coordinates='data',
 | 
						|
                     label='U', color='blue', zorder=zorder)
 | 
						|
        ax.quiverkey(q, 5.5, 2, 20, coordinates='data',
 | 
						|
                     label='V', color='blue', angle=90, zorder=zorder)
 | 
						|
 | 
						|
 | 
						|
def draw_quiverkey_setzorder(fig, zorder=None):
 | 
						|
    """Draw Quiver and QuiverKey using set_zorder"""
 | 
						|
    x = np.arange(1, 6, 1)
 | 
						|
    y = np.arange(1, 6, 1)
 | 
						|
    X, Y = np.meshgrid(x, y)
 | 
						|
    U, V = 2, 2
 | 
						|
 | 
						|
    ax = fig.subplots()
 | 
						|
    q = ax.quiver(X, Y, U, V, pivot='middle')
 | 
						|
    ax.set_xlim(0.5, 5.5)
 | 
						|
    ax.set_ylim(0.5, 5.5)
 | 
						|
    qk1 = ax.quiverkey(q, 4, 4, 25, coordinates='data',
 | 
						|
                       label='U', color='blue')
 | 
						|
    qk2 = ax.quiverkey(q, 5.5, 2, 20, coordinates='data',
 | 
						|
                       label='V', color='blue', angle=90)
 | 
						|
    if zorder is not None:
 | 
						|
        qk1.set_zorder(zorder)
 | 
						|
        qk2.set_zorder(zorder)
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize('zorder', [0, 2, 5, None])
 | 
						|
@check_figures_equal(extensions=['png'])
 | 
						|
def test_quiverkey_zorder(fig_test, fig_ref, zorder):
 | 
						|
    draw_quiverkey_zorder_argument(fig_test, zorder=zorder)
 | 
						|
    draw_quiverkey_setzorder(fig_ref, zorder=zorder)
 |