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.
		
		
		
		
		
			
		
			
				
	
	
		
			188 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			188 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Python
		
	
from tempfile import TemporaryFile
 | 
						|
 | 
						|
import numpy as np
 | 
						|
from packaging.version import parse as parse_version
 | 
						|
import pytest
 | 
						|
 | 
						|
import matplotlib as mpl
 | 
						|
from matplotlib import dviread
 | 
						|
from matplotlib.testing import _has_tex_package
 | 
						|
from matplotlib.testing.decorators import check_figures_equal, image_comparison
 | 
						|
from matplotlib.testing._markers import needs_usetex
 | 
						|
import matplotlib.pyplot as plt
 | 
						|
 | 
						|
 | 
						|
pytestmark = needs_usetex
 | 
						|
 | 
						|
 | 
						|
@image_comparison(
 | 
						|
    baseline_images=['test_usetex'],
 | 
						|
    extensions=['pdf', 'png'],
 | 
						|
    style="mpl20")
 | 
						|
def test_usetex():
 | 
						|
    mpl.rcParams['text.usetex'] = True
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
    kwargs = {"verticalalignment": "baseline", "size": 24,
 | 
						|
              "bbox": dict(pad=0, edgecolor="k", facecolor="none")}
 | 
						|
    ax.text(0.2, 0.7,
 | 
						|
            # the \LaTeX macro exercises character sizing and placement,
 | 
						|
            # \left[ ... \right\} draw some variable-height characters,
 | 
						|
            # \sqrt and \frac draw horizontal rules, \mathrm changes the font
 | 
						|
            r'\LaTeX\ $\left[\int\limits_e^{2e}'
 | 
						|
            r'\sqrt\frac{\log^3 x}{x}\,\mathrm{d}x \right\}$',
 | 
						|
            **kwargs)
 | 
						|
    ax.text(0.2, 0.3, "lg", **kwargs)
 | 
						|
    ax.text(0.4, 0.3, r"$\frac{1}{2}\pi$", **kwargs)
 | 
						|
    ax.text(0.6, 0.3, "$p^{3^A}$", **kwargs)
 | 
						|
    ax.text(0.8, 0.3, "$p_{3_2}$", **kwargs)
 | 
						|
    for x in {t.get_position()[0] for t in ax.texts}:
 | 
						|
        ax.axvline(x)
 | 
						|
    for y in {t.get_position()[1] for t in ax.texts}:
 | 
						|
        ax.axhline(y)
 | 
						|
    ax.set_axis_off()
 | 
						|
 | 
						|
 | 
						|
@check_figures_equal()
 | 
						|
def test_empty(fig_test, fig_ref):
 | 
						|
    mpl.rcParams['text.usetex'] = True
 | 
						|
    fig_test.text(.5, .5, "% a comment")
 | 
						|
 | 
						|
 | 
						|
@check_figures_equal()
 | 
						|
def test_unicode_minus(fig_test, fig_ref):
 | 
						|
    mpl.rcParams['text.usetex'] = True
 | 
						|
    fig_test.text(.5, .5, "$-$")
 | 
						|
    fig_ref.text(.5, .5, "\N{MINUS SIGN}")
 | 
						|
 | 
						|
 | 
						|
def test_mathdefault():
 | 
						|
    plt.rcParams["axes.formatter.use_mathtext"] = True
 | 
						|
    fig = plt.figure()
 | 
						|
    fig.add_subplot().set_xlim(-1, 1)
 | 
						|
    # Check that \mathdefault commands generated by tickers don't cause
 | 
						|
    # problems when later switching usetex on.
 | 
						|
    mpl.rcParams['text.usetex'] = True
 | 
						|
    fig.canvas.draw()
 | 
						|
 | 
						|
 | 
						|
@image_comparison(['eqnarray.png'])
 | 
						|
def test_multiline_eqnarray():
 | 
						|
    text = (
 | 
						|
        r'\begin{eqnarray*}'
 | 
						|
        r'foo\\'
 | 
						|
        r'bar\\'
 | 
						|
        r'baz\\'
 | 
						|
        r'\end{eqnarray*}'
 | 
						|
    )
 | 
						|
 | 
						|
    fig = plt.figure(figsize=(1, 1))
 | 
						|
    fig.text(0.5, 0.5, text, usetex=True,
 | 
						|
             horizontalalignment='center', verticalalignment='center')
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize("fontsize", [8, 10, 12])
 | 
						|
def test_minus_no_descent(fontsize):
 | 
						|
    # Test special-casing of minus descent in DviFont._height_depth_of, by
 | 
						|
    # checking that overdrawing a 1 and a -1 results in an overall height
 | 
						|
    # equivalent to drawing either of them separately.
 | 
						|
    mpl.style.use("mpl20")
 | 
						|
    mpl.rcParams['font.size'] = fontsize
 | 
						|
    heights = {}
 | 
						|
    fig = plt.figure()
 | 
						|
    for vals in [(1,), (-1,), (-1, 1)]:
 | 
						|
        fig.clear()
 | 
						|
        for x in vals:
 | 
						|
            fig.text(.5, .5, f"${x}$", usetex=True)
 | 
						|
        fig.canvas.draw()
 | 
						|
        # The following counts the number of non-fully-blank pixel rows.
 | 
						|
        heights[vals] = ((np.array(fig.canvas.buffer_rgba())[..., 0] != 255)
 | 
						|
                         .any(axis=1).sum())
 | 
						|
    assert len({*heights.values()}) == 1
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize('pkg', ['xcolor', 'chemformula'])
 | 
						|
def test_usetex_packages(pkg):
 | 
						|
    if not _has_tex_package(pkg):
 | 
						|
        pytest.skip(f'{pkg} is not available')
 | 
						|
    mpl.rcParams['text.usetex'] = True
 | 
						|
 | 
						|
    fig = plt.figure()
 | 
						|
    text = fig.text(0.5, 0.5, "Some text 0123456789")
 | 
						|
    fig.canvas.draw()
 | 
						|
 | 
						|
    mpl.rcParams['text.latex.preamble'] = (
 | 
						|
        r'\PassOptionsToPackage{dvipsnames}{xcolor}\usepackage{%s}' % pkg)
 | 
						|
    fig = plt.figure()
 | 
						|
    text2 = fig.text(0.5, 0.5, "Some text 0123456789")
 | 
						|
    fig.canvas.draw()
 | 
						|
    np.testing.assert_array_equal(text2.get_window_extent(),
 | 
						|
                                  text.get_window_extent())
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize(
 | 
						|
    "preamble",
 | 
						|
    [r"\usepackage[full]{textcomp}", r"\usepackage{underscore}"],
 | 
						|
)
 | 
						|
def test_latex_pkg_already_loaded(preamble):
 | 
						|
    plt.rcParams["text.latex.preamble"] = preamble
 | 
						|
    fig = plt.figure()
 | 
						|
    fig.text(.5, .5, "hello, world", usetex=True)
 | 
						|
    fig.canvas.draw()
 | 
						|
 | 
						|
 | 
						|
def test_usetex_with_underscore():
 | 
						|
    plt.rcParams["text.usetex"] = True
 | 
						|
    df = {"a_b": range(5)[::-1], "c": range(5)}
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
    ax.plot("c", "a_b", data=df)
 | 
						|
    ax.legend()
 | 
						|
    ax.text(0, 0, "foo_bar", usetex=True)
 | 
						|
    plt.draw()
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.flaky(reruns=3)  # Tends to hit a TeX cache lock on AppVeyor.
 | 
						|
@pytest.mark.parametrize("fmt", ["pdf", "svg"])
 | 
						|
def test_missing_psfont(fmt, monkeypatch):
 | 
						|
    """An error is raised if a TeX font lacks a Type-1 equivalent"""
 | 
						|
    monkeypatch.setattr(
 | 
						|
        dviread.PsfontsMap, '__getitem__',
 | 
						|
        lambda self, k: dviread.PsFont(
 | 
						|
            texname=b'texfont', psname=b'Some Font',
 | 
						|
            effects=None, encoding=None, filename=None))
 | 
						|
    mpl.rcParams['text.usetex'] = True
 | 
						|
    fig, ax = plt.subplots()
 | 
						|
    ax.text(0.5, 0.5, 'hello')
 | 
						|
    with TemporaryFile() as tmpfile, pytest.raises(ValueError):
 | 
						|
        fig.savefig(tmpfile, format=fmt)
 | 
						|
 | 
						|
 | 
						|
try:
 | 
						|
    _old_gs_version = mpl._get_executable_info('gs').version < parse_version('9.55')
 | 
						|
except mpl.ExecutableNotFoundError:
 | 
						|
    _old_gs_version = True
 | 
						|
 | 
						|
 | 
						|
@image_comparison(baseline_images=['rotation'], extensions=['eps', 'pdf', 'png', 'svg'],
 | 
						|
                  style='mpl20', tol=3.91 if _old_gs_version else 0)
 | 
						|
def test_rotation():
 | 
						|
    mpl.rcParams['text.usetex'] = True
 | 
						|
 | 
						|
    fig = plt.figure()
 | 
						|
    ax = fig.add_axes([0, 0, 1, 1])
 | 
						|
    ax.set(xlim=[-0.5, 5], xticks=[], ylim=[-0.5, 3], yticks=[], frame_on=False)
 | 
						|
 | 
						|
    text = {val: val[0] for val in ['top', 'center', 'bottom', 'left', 'right']}
 | 
						|
    text['baseline'] = 'B'
 | 
						|
    text['center_baseline'] = 'C'
 | 
						|
 | 
						|
    for i, va in enumerate(['top', 'center', 'bottom', 'baseline', 'center_baseline']):
 | 
						|
        for j, ha in enumerate(['left', 'center', 'right']):
 | 
						|
            for k, angle in enumerate([0, 90, 180, 270]):
 | 
						|
                k //= 2
 | 
						|
                x = i + k / 2
 | 
						|
                y = j + k / 2
 | 
						|
                ax.plot(x, y, '+', c=f'C{k}', markersize=20, markeredgewidth=0.5)
 | 
						|
                # 'My' checks full height letters plus descenders.
 | 
						|
                ax.text(x, y, f"$\\mathrm{{My {text[ha]}{text[va]} {angle}}}$",
 | 
						|
                        rotation=angle, horizontalalignment=ha, verticalalignment=va)
 |