12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505 |
- from contextlib import ExitStack
- from copy import copy
- import functools
- import io
- import os
- from pathlib import Path
- import platform
- import sys
- import urllib.request
- import numpy as np
- from numpy.testing import assert_array_equal
- from PIL import Image
- import matplotlib as mpl
- from matplotlib import (
- colors, image as mimage, patches, pyplot as plt, style, rcParams)
- from matplotlib.image import (AxesImage, BboxImage, FigureImage,
- NonUniformImage, PcolorImage)
- from matplotlib.testing.decorators import check_figures_equal, image_comparison
- from matplotlib.transforms import Bbox, Affine2D, TransformedBbox
- import matplotlib.ticker as mticker
- import pytest
- @image_comparison(['image_interps'], style='mpl20')
- def test_image_interps():
- """Make the basic nearest, bilinear and bicubic interps."""
- # Remove texts when this image is regenerated.
- # Remove this line when this test image is regenerated.
- plt.rcParams['text.kerning_factor'] = 6
- X = np.arange(100).reshape(5, 20)
- fig, (ax1, ax2, ax3) = plt.subplots(3)
- ax1.imshow(X, interpolation='nearest')
- ax1.set_title('three interpolations')
- ax1.set_ylabel('nearest')
- ax2.imshow(X, interpolation='bilinear')
- ax2.set_ylabel('bilinear')
- ax3.imshow(X, interpolation='bicubic')
- ax3.set_ylabel('bicubic')
- @image_comparison(['interp_alpha.png'], remove_text=True)
- def test_alpha_interp():
- """Test the interpolation of the alpha channel on RGBA images"""
- fig, (axl, axr) = plt.subplots(1, 2)
- # full green image
- img = np.zeros((5, 5, 4))
- img[..., 1] = np.ones((5, 5))
- # transparent under main diagonal
- img[..., 3] = np.tril(np.ones((5, 5), dtype=np.uint8))
- axl.imshow(img, interpolation="none")
- axr.imshow(img, interpolation="bilinear")
- @image_comparison(['interp_nearest_vs_none'],
- extensions=['pdf', 'svg'], remove_text=True)
- def test_interp_nearest_vs_none():
- """Test the effect of "nearest" and "none" interpolation"""
- # Setting dpi to something really small makes the difference very
- # visible. This works fine with pdf, since the dpi setting doesn't
- # affect anything but images, but the agg output becomes unusably
- # small.
- rcParams['savefig.dpi'] = 3
- X = np.array([[[218, 165, 32], [122, 103, 238]],
- [[127, 255, 0], [255, 99, 71]]], dtype=np.uint8)
- fig, (ax1, ax2) = plt.subplots(1, 2)
- ax1.imshow(X, interpolation='none')
- ax1.set_title('interpolation none')
- ax2.imshow(X, interpolation='nearest')
- ax2.set_title('interpolation nearest')
- @pytest.mark.parametrize('suppressComposite', [False, True])
- @image_comparison(['figimage'], extensions=['png', 'pdf'])
- def test_figimage(suppressComposite):
- fig = plt.figure(figsize=(2, 2), dpi=100)
- fig.suppressComposite = suppressComposite
- x, y = np.ix_(np.arange(100) / 100.0, np.arange(100) / 100)
- z = np.sin(x**2 + y**2 - x*y)
- c = np.sin(20*x**2 + 50*y**2)
- img = z + c/5
- fig.figimage(img, xo=0, yo=0, origin='lower')
- fig.figimage(img[::-1, :], xo=0, yo=100, origin='lower')
- fig.figimage(img[:, ::-1], xo=100, yo=0, origin='lower')
- fig.figimage(img[::-1, ::-1], xo=100, yo=100, origin='lower')
- def test_image_python_io():
- fig, ax = plt.subplots()
- ax.plot([1, 2, 3])
- buffer = io.BytesIO()
- fig.savefig(buffer)
- buffer.seek(0)
- plt.imread(buffer)
- @pytest.mark.parametrize(
- "img_size, fig_size, interpolation",
- [(5, 2, "hanning"), # data larger than figure.
- (5, 5, "nearest"), # exact resample.
- (5, 10, "nearest"), # double sample.
- (3, 2.9, "hanning"), # <3 upsample.
- (3, 9.1, "nearest"), # >3 upsample.
- ])
- @check_figures_equal(extensions=['png'])
- def test_imshow_antialiased(fig_test, fig_ref,
- img_size, fig_size, interpolation):
- np.random.seed(19680801)
- dpi = plt.rcParams["savefig.dpi"]
- A = np.random.rand(int(dpi * img_size), int(dpi * img_size))
- for fig in [fig_test, fig_ref]:
- fig.set_size_inches(fig_size, fig_size)
- ax = fig_test.subplots()
- ax.set_position([0, 0, 1, 1])
- ax.imshow(A, interpolation='antialiased')
- ax = fig_ref.subplots()
- ax.set_position([0, 0, 1, 1])
- ax.imshow(A, interpolation=interpolation)
- @check_figures_equal(extensions=['png'])
- def test_imshow_zoom(fig_test, fig_ref):
- # should be less than 3 upsample, so should be nearest...
- np.random.seed(19680801)
- dpi = plt.rcParams["savefig.dpi"]
- A = np.random.rand(int(dpi * 3), int(dpi * 3))
- for fig in [fig_test, fig_ref]:
- fig.set_size_inches(2.9, 2.9)
- ax = fig_test.subplots()
- ax.imshow(A, interpolation='antialiased')
- ax.set_xlim([10, 20])
- ax.set_ylim([10, 20])
- ax = fig_ref.subplots()
- ax.imshow(A, interpolation='nearest')
- ax.set_xlim([10, 20])
- ax.set_ylim([10, 20])
- @check_figures_equal()
- def test_imshow_pil(fig_test, fig_ref):
- style.use("default")
- png_path = Path(__file__).parent / "baseline_images/pngsuite/basn3p04.png"
- tiff_path = Path(__file__).parent / "baseline_images/test_image/uint16.tif"
- axs = fig_test.subplots(2)
- axs[0].imshow(Image.open(png_path))
- axs[1].imshow(Image.open(tiff_path))
- axs = fig_ref.subplots(2)
- axs[0].imshow(plt.imread(png_path))
- axs[1].imshow(plt.imread(tiff_path))
- def test_imread_pil_uint16():
- img = plt.imread(os.path.join(os.path.dirname(__file__),
- 'baseline_images', 'test_image', 'uint16.tif'))
- assert img.dtype == np.uint16
- assert np.sum(img) == 134184960
- def test_imread_fspath():
- img = plt.imread(
- Path(__file__).parent / 'baseline_images/test_image/uint16.tif')
- assert img.dtype == np.uint16
- assert np.sum(img) == 134184960
- @pytest.mark.parametrize("fmt", ["png", "jpg", "jpeg", "tiff"])
- def test_imsave(fmt):
- has_alpha = fmt not in ["jpg", "jpeg"]
- # The goal here is that the user can specify an output logical DPI
- # for the image, but this will not actually add any extra pixels
- # to the image, it will merely be used for metadata purposes.
- # So we do the traditional case (dpi == 1), and the new case (dpi
- # == 100) and read the resulting PNG files back in and make sure
- # the data is 100% identical.
- np.random.seed(1)
- # The height of 1856 pixels was selected because going through creating an
- # actual dpi=100 figure to save the image to a Pillow-provided format would
- # cause a rounding error resulting in a final image of shape 1855.
- data = np.random.rand(1856, 2)
- buff_dpi1 = io.BytesIO()
- plt.imsave(buff_dpi1, data, format=fmt, dpi=1)
- buff_dpi100 = io.BytesIO()
- plt.imsave(buff_dpi100, data, format=fmt, dpi=100)
- buff_dpi1.seek(0)
- arr_dpi1 = plt.imread(buff_dpi1, format=fmt)
- buff_dpi100.seek(0)
- arr_dpi100 = plt.imread(buff_dpi100, format=fmt)
- assert arr_dpi1.shape == (1856, 2, 3 + has_alpha)
- assert arr_dpi100.shape == (1856, 2, 3 + has_alpha)
- assert_array_equal(arr_dpi1, arr_dpi100)
- @pytest.mark.parametrize("fmt", ["png", "pdf", "ps", "eps", "svg"])
- def test_imsave_fspath(fmt):
- plt.imsave(Path(os.devnull), np.array([[0, 1]]), format=fmt)
- def test_imsave_color_alpha():
- # Test that imsave accept arrays with ndim=3 where the third dimension is
- # color and alpha without raising any exceptions, and that the data is
- # acceptably preserved through a save/read roundtrip.
- np.random.seed(1)
- for origin in ['lower', 'upper']:
- data = np.random.rand(16, 16, 4)
- buff = io.BytesIO()
- plt.imsave(buff, data, origin=origin, format="png")
- buff.seek(0)
- arr_buf = plt.imread(buff)
- # Recreate the float -> uint8 conversion of the data
- # We can only expect to be the same with 8 bits of precision,
- # since that's what the PNG file used.
- data = (255*data).astype('uint8')
- if origin == 'lower':
- data = data[::-1]
- arr_buf = (255*arr_buf).astype('uint8')
- assert_array_equal(data, arr_buf)
- def test_imsave_pil_kwargs_png():
- from PIL.PngImagePlugin import PngInfo
- buf = io.BytesIO()
- pnginfo = PngInfo()
- pnginfo.add_text("Software", "test")
- plt.imsave(buf, [[0, 1], [2, 3]],
- format="png", pil_kwargs={"pnginfo": pnginfo})
- im = Image.open(buf)
- assert im.info["Software"] == "test"
- def test_imsave_pil_kwargs_tiff():
- from PIL.TiffTags import TAGS_V2 as TAGS
- buf = io.BytesIO()
- pil_kwargs = {"description": "test image"}
- plt.imsave(buf, [[0, 1], [2, 3]], format="tiff", pil_kwargs=pil_kwargs)
- assert len(pil_kwargs) == 1
- im = Image.open(buf)
- tags = {TAGS[k].name: v for k, v in im.tag_v2.items()}
- assert tags["ImageDescription"] == "test image"
- @image_comparison(['image_alpha'], remove_text=True)
- def test_image_alpha():
- np.random.seed(0)
- Z = np.random.rand(6, 6)
- fig, (ax1, ax2, ax3) = plt.subplots(1, 3)
- ax1.imshow(Z, alpha=1.0, interpolation='none')
- ax2.imshow(Z, alpha=0.5, interpolation='none')
- ax3.imshow(Z, alpha=0.5, interpolation='nearest')
- def test_cursor_data():
- from matplotlib.backend_bases import MouseEvent
- fig, ax = plt.subplots()
- im = ax.imshow(np.arange(100).reshape(10, 10), origin='upper')
- x, y = 4, 4
- xdisp, ydisp = ax.transData.transform([x, y])
- event = MouseEvent('motion_notify_event', fig.canvas, xdisp, ydisp)
- assert im.get_cursor_data(event) == 44
- # Now try for a point outside the image
- # Tests issue #4957
- x, y = 10.1, 4
- xdisp, ydisp = ax.transData.transform([x, y])
- event = MouseEvent('motion_notify_event', fig.canvas, xdisp, ydisp)
- assert im.get_cursor_data(event) is None
- # Hmm, something is wrong here... I get 0, not None...
- # But, this works further down in the tests with extents flipped
- # x, y = 0.1, -0.1
- # xdisp, ydisp = ax.transData.transform([x, y])
- # event = MouseEvent('motion_notify_event', fig.canvas, xdisp, ydisp)
- # z = im.get_cursor_data(event)
- # assert z is None, "Did not get None, got %d" % z
- ax.clear()
- # Now try with the extents flipped.
- im = ax.imshow(np.arange(100).reshape(10, 10), origin='lower')
- x, y = 4, 4
- xdisp, ydisp = ax.transData.transform([x, y])
- event = MouseEvent('motion_notify_event', fig.canvas, xdisp, ydisp)
- assert im.get_cursor_data(event) == 44
- fig, ax = plt.subplots()
- im = ax.imshow(np.arange(100).reshape(10, 10), extent=[0, 0.5, 0, 0.5])
- x, y = 0.25, 0.25
- xdisp, ydisp = ax.transData.transform([x, y])
- event = MouseEvent('motion_notify_event', fig.canvas, xdisp, ydisp)
- assert im.get_cursor_data(event) == 55
- # Now try for a point outside the image
- # Tests issue #4957
- x, y = 0.75, 0.25
- xdisp, ydisp = ax.transData.transform([x, y])
- event = MouseEvent('motion_notify_event', fig.canvas, xdisp, ydisp)
- assert im.get_cursor_data(event) is None
- x, y = 0.01, -0.01
- xdisp, ydisp = ax.transData.transform([x, y])
- event = MouseEvent('motion_notify_event', fig.canvas, xdisp, ydisp)
- assert im.get_cursor_data(event) is None
- # Now try with additional transform applied to the image artist
- trans = Affine2D().scale(2).rotate(0.5)
- im = ax.imshow(np.arange(100).reshape(10, 10),
- transform=trans + ax.transData)
- x, y = 3, 10
- xdisp, ydisp = ax.transData.transform([x, y])
- event = MouseEvent('motion_notify_event', fig.canvas, xdisp, ydisp)
- assert im.get_cursor_data(event) == 44
- @pytest.mark.parametrize(
- "data, text", [
- ([[10001, 10000]], "[10001.000]"),
- ([[.123, .987]], "[0.123]"),
- ([[np.nan, 1, 2]], "[]"),
- ([[1, 1+1e-15]], "[1.0000000000000000]"),
- ([[-1, -1]], "[-1.0000000000000000]"),
- ])
- def test_format_cursor_data(data, text):
- from matplotlib.backend_bases import MouseEvent
- fig, ax = plt.subplots()
- im = ax.imshow(data)
- xdisp, ydisp = ax.transData.transform([0, 0])
- event = MouseEvent('motion_notify_event', fig.canvas, xdisp, ydisp)
- assert im.format_cursor_data(im.get_cursor_data(event)) == text
- @image_comparison(['image_clip'], style='mpl20')
- def test_image_clip():
- d = [[1, 2], [3, 4]]
- fig, ax = plt.subplots()
- im = ax.imshow(d)
- patch = patches.Circle((0, 0), radius=1, transform=ax.transData)
- im.set_clip_path(patch)
- @image_comparison(['image_cliprect'], style='mpl20')
- def test_image_cliprect():
- fig, ax = plt.subplots()
- d = [[1, 2], [3, 4]]
- im = ax.imshow(d, extent=(0, 5, 0, 5))
- rect = patches.Rectangle(
- xy=(1, 1), width=2, height=2, transform=im.axes.transData)
- im.set_clip_path(rect)
- @image_comparison(['imshow'], remove_text=True, style='mpl20')
- def test_imshow():
- fig, ax = plt.subplots()
- arr = np.arange(100).reshape((10, 10))
- ax.imshow(arr, interpolation="bilinear", extent=(1, 2, 1, 2))
- ax.set_xlim(0, 3)
- ax.set_ylim(0, 3)
- @check_figures_equal(extensions=['png'])
- def test_imshow_10_10_1(fig_test, fig_ref):
- # 10x10x1 should be the same as 10x10
- arr = np.arange(100).reshape((10, 10, 1))
- ax = fig_ref.subplots()
- ax.imshow(arr[:, :, 0], interpolation="bilinear", extent=(1, 2, 1, 2))
- ax.set_xlim(0, 3)
- ax.set_ylim(0, 3)
- ax = fig_test.subplots()
- ax.imshow(arr, interpolation="bilinear", extent=(1, 2, 1, 2))
- ax.set_xlim(0, 3)
- ax.set_ylim(0, 3)
- def test_imshow_10_10_2():
- fig, ax = plt.subplots()
- arr = np.arange(200).reshape((10, 10, 2))
- with pytest.raises(TypeError):
- ax.imshow(arr)
- def test_imshow_10_10_5():
- fig, ax = plt.subplots()
- arr = np.arange(500).reshape((10, 10, 5))
- with pytest.raises(TypeError):
- ax.imshow(arr)
- @image_comparison(['no_interpolation_origin'], remove_text=True)
- def test_no_interpolation_origin():
- fig, axs = plt.subplots(2)
- axs[0].imshow(np.arange(100).reshape((2, 50)), origin="lower",
- interpolation='none')
- axs[1].imshow(np.arange(100).reshape((2, 50)), interpolation='none')
- @image_comparison(['image_shift'], remove_text=True, extensions=['pdf', 'svg'])
- def test_image_shift():
- imgData = [[1 / x + 1 / y for x in range(1, 100)] for y in range(1, 100)]
- tMin = 734717.945208
- tMax = 734717.946366
- fig, ax = plt.subplots()
- ax.imshow(imgData, norm=colors.LogNorm(), interpolation='none',
- extent=(tMin, tMax, 1, 100))
- ax.set_aspect('auto')
- def test_image_edges():
- fig = plt.figure(figsize=[1, 1])
- ax = fig.add_axes([0, 0, 1, 1], frameon=False)
- data = np.tile(np.arange(12), 15).reshape(20, 9)
- im = ax.imshow(data, origin='upper', extent=[-10, 10, -10, 10],
- interpolation='none', cmap='gray')
- x = y = 2
- ax.set_xlim([-x, x])
- ax.set_ylim([-y, y])
- ax.set_xticks([])
- ax.set_yticks([])
- buf = io.BytesIO()
- fig.savefig(buf, facecolor=(0, 1, 0))
- buf.seek(0)
- im = plt.imread(buf)
- r, g, b, a = sum(im[:, 0])
- r, g, b, a = sum(im[:, -1])
- assert g != 100, 'Expected a non-green edge - but sadly, it was.'
- @image_comparison(['image_composite_background'],
- remove_text=True, style='mpl20')
- def test_image_composite_background():
- fig, ax = plt.subplots()
- arr = np.arange(12).reshape(4, 3)
- ax.imshow(arr, extent=[0, 2, 15, 0])
- ax.imshow(arr, extent=[4, 6, 15, 0])
- ax.set_facecolor((1, 0, 0, 0.5))
- ax.set_xlim([0, 12])
- @image_comparison(['image_composite_alpha'], remove_text=True)
- def test_image_composite_alpha():
- """
- Tests that the alpha value is recognized and correctly applied in the
- process of compositing images together.
- """
- fig, ax = plt.subplots()
- arr = np.zeros((11, 21, 4))
- arr[:, :, 0] = 1
- arr[:, :, 3] = np.concatenate(
- (np.arange(0, 1.1, 0.1), np.arange(0, 1, 0.1)[::-1]))
- arr2 = np.zeros((21, 11, 4))
- arr2[:, :, 0] = 1
- arr2[:, :, 1] = 1
- arr2[:, :, 3] = np.concatenate(
- (np.arange(0, 1.1, 0.1), np.arange(0, 1, 0.1)[::-1]))[:, np.newaxis]
- ax.imshow(arr, extent=[1, 2, 5, 0], alpha=0.3)
- ax.imshow(arr, extent=[2, 3, 5, 0], alpha=0.6)
- ax.imshow(arr, extent=[3, 4, 5, 0])
- ax.imshow(arr2, extent=[0, 5, 1, 2])
- ax.imshow(arr2, extent=[0, 5, 2, 3], alpha=0.6)
- ax.imshow(arr2, extent=[0, 5, 3, 4], alpha=0.3)
- ax.set_facecolor((0, 0.5, 0, 1))
- ax.set_xlim([0, 5])
- ax.set_ylim([5, 0])
- @check_figures_equal(extensions=["pdf"])
- def test_clip_path_disables_compositing(fig_test, fig_ref):
- t = np.arange(9).reshape((3, 3))
- for fig in [fig_test, fig_ref]:
- ax = fig.add_subplot()
- ax.imshow(t, clip_path=(mpl.path.Path([(0, 0), (0, 1), (1, 0)]),
- ax.transData))
- ax.imshow(t, clip_path=(mpl.path.Path([(1, 1), (1, 2), (2, 1)]),
- ax.transData))
- fig_ref.suppressComposite = True
- @image_comparison(['rasterize_10dpi'],
- extensions=['pdf', 'svg'], remove_text=True, style='mpl20')
- def test_rasterize_dpi():
- # This test should check rasterized rendering with high output resolution.
- # It plots a rasterized line and a normal image with imshow. So it will
- # catch when images end up in the wrong place in case of non-standard dpi
- # setting. Instead of high-res rasterization I use low-res. Therefore
- # the fact that the resolution is non-standard is easily checked by
- # image_comparison.
- img = np.asarray([[1, 2], [3, 4]])
- fig, axs = plt.subplots(1, 3, figsize=(3, 1))
- axs[0].imshow(img)
- axs[1].plot([0, 1], [0, 1], linewidth=20., rasterized=True)
- axs[1].set(xlim=(0, 1), ylim=(-1, 2))
- axs[2].plot([0, 1], [0, 1], linewidth=20.)
- axs[2].set(xlim=(0, 1), ylim=(-1, 2))
- # Low-dpi PDF rasterization errors prevent proper image comparison tests.
- # Hide detailed structures like the axes spines.
- for ax in axs:
- ax.set_xticks([])
- ax.set_yticks([])
- ax.spines[:].set_visible(False)
- rcParams['savefig.dpi'] = 10
- @image_comparison(['bbox_image_inverted'], remove_text=True, style='mpl20')
- def test_bbox_image_inverted():
- # This is just used to produce an image to feed to BboxImage
- image = np.arange(100).reshape((10, 10))
- fig, ax = plt.subplots()
- bbox_im = BboxImage(
- TransformedBbox(Bbox([[100, 100], [0, 0]]), ax.transData),
- interpolation='nearest')
- bbox_im.set_data(image)
- bbox_im.set_clip_on(False)
- ax.set_xlim(0, 100)
- ax.set_ylim(0, 100)
- ax.add_artist(bbox_im)
- image = np.identity(10)
- bbox_im = BboxImage(TransformedBbox(Bbox([[0.1, 0.2], [0.3, 0.25]]),
- ax.figure.transFigure),
- interpolation='nearest')
- bbox_im.set_data(image)
- bbox_im.set_clip_on(False)
- ax.add_artist(bbox_im)
- def test_get_window_extent_for_AxisImage():
- # Create a figure of known size (1000x1000 pixels), place an image
- # object at a given location and check that get_window_extent()
- # returns the correct bounding box values (in pixels).
- im = np.array([[0.25, 0.75, 1.0, 0.75], [0.1, 0.65, 0.5, 0.4],
- [0.6, 0.3, 0.0, 0.2], [0.7, 0.9, 0.4, 0.6]])
- fig, ax = plt.subplots(figsize=(10, 10), dpi=100)
- ax.set_position([0, 0, 1, 1])
- ax.set_xlim(0, 1)
- ax.set_ylim(0, 1)
- im_obj = ax.imshow(
- im, extent=[0.4, 0.7, 0.2, 0.9], interpolation='nearest')
- fig.canvas.draw()
- renderer = fig.canvas.renderer
- im_bbox = im_obj.get_window_extent(renderer)
- assert_array_equal(im_bbox.get_points(), [[400, 200], [700, 900]])
- fig, ax = plt.subplots(figsize=(10, 10), dpi=100)
- ax.set_position([0, 0, 1, 1])
- ax.set_xlim(1, 2)
- ax.set_ylim(0, 1)
- im_obj = ax.imshow(
- im, extent=[0.4, 0.7, 0.2, 0.9], interpolation='nearest',
- transform=ax.transAxes)
- fig.canvas.draw()
- renderer = fig.canvas.renderer
- im_bbox = im_obj.get_window_extent(renderer)
- assert_array_equal(im_bbox.get_points(), [[400, 200], [700, 900]])
- @image_comparison(['zoom_and_clip_upper_origin.png'],
- remove_text=True, style='mpl20')
- def test_zoom_and_clip_upper_origin():
- image = np.arange(100)
- image = image.reshape((10, 10))
- fig, ax = plt.subplots()
- ax.imshow(image)
- ax.set_ylim(2.0, -0.5)
- ax.set_xlim(-0.5, 2.0)
- def test_nonuniformimage_setcmap():
- ax = plt.gca()
- im = NonUniformImage(ax)
- im.set_cmap('Blues')
- def test_nonuniformimage_setnorm():
- ax = plt.gca()
- im = NonUniformImage(ax)
- im.set_norm(plt.Normalize())
- def test_jpeg_2d():
- # smoke test that mode-L pillow images work.
- imd = np.ones((10, 10), dtype='uint8')
- for i in range(10):
- imd[i, :] = np.linspace(0.0, 1.0, 10) * 255
- im = Image.new('L', (10, 10))
- im.putdata(imd.flatten())
- fig, ax = plt.subplots()
- ax.imshow(im)
- def test_jpeg_alpha():
- plt.figure(figsize=(1, 1), dpi=300)
- # Create an image that is all black, with a gradient from 0-1 in
- # the alpha channel from left to right.
- im = np.zeros((300, 300, 4), dtype=float)
- im[..., 3] = np.linspace(0.0, 1.0, 300)
- plt.figimage(im)
- buff = io.BytesIO()
- plt.savefig(buff, facecolor="red", format='jpg', dpi=300)
- buff.seek(0)
- image = Image.open(buff)
- # If this fails, there will be only one color (all black). If this
- # is working, we should have all 256 shades of grey represented.
- num_colors = len(image.getcolors(256))
- assert 175 <= num_colors <= 210
- # The fully transparent part should be red.
- corner_pixel = image.getpixel((0, 0))
- assert corner_pixel == (254, 0, 0)
- def test_axesimage_setdata():
- ax = plt.gca()
- im = AxesImage(ax)
- z = np.arange(12, dtype=float).reshape((4, 3))
- im.set_data(z)
- z[0, 0] = 9.9
- assert im._A[0, 0] == 0, 'value changed'
- def test_figureimage_setdata():
- fig = plt.gcf()
- im = FigureImage(fig)
- z = np.arange(12, dtype=float).reshape((4, 3))
- im.set_data(z)
- z[0, 0] = 9.9
- assert im._A[0, 0] == 0, 'value changed'
- @pytest.mark.parametrize(
- "image_cls,x,y,a", [
- (NonUniformImage,
- np.arange(3.), np.arange(4.), np.arange(12.).reshape((4, 3))),
- (PcolorImage,
- np.arange(3.), np.arange(4.), np.arange(6.).reshape((3, 2))),
- ])
- def test_setdata_xya(image_cls, x, y, a):
- ax = plt.gca()
- im = image_cls(ax)
- im.set_data(x, y, a)
- x[0] = y[0] = a[0, 0] = 9.9
- assert im._A[0, 0] == im._Ax[0] == im._Ay[0] == 0, 'value changed'
- im.set_data(x, y, a.reshape((*a.shape, -1))) # Just a smoketest.
- def test_minimized_rasterized():
- # This ensures that the rasterized content in the colorbars is
- # only as thick as the colorbar, and doesn't extend to other parts
- # of the image. See #5814. While the original bug exists only
- # in Postscript, the best way to detect it is to generate SVG
- # and then parse the output to make sure the two colorbar images
- # are the same size.
- from xml.etree import ElementTree
- np.random.seed(0)
- data = np.random.rand(10, 10)
- fig, ax = plt.subplots(1, 2)
- p1 = ax[0].pcolormesh(data)
- p2 = ax[1].pcolormesh(data)
- plt.colorbar(p1, ax=ax[0])
- plt.colorbar(p2, ax=ax[1])
- buff = io.BytesIO()
- plt.savefig(buff, format='svg')
- buff = io.BytesIO(buff.getvalue())
- tree = ElementTree.parse(buff)
- width = None
- for image in tree.iter('image'):
- if width is None:
- width = image['width']
- else:
- if image['width'] != width:
- assert False
- def test_load_from_url():
- path = Path(__file__).parent / "baseline_images/pngsuite/basn3p04.png"
- url = ('file:'
- + ('///' if sys.platform == 'win32' else '')
- + path.resolve().as_posix())
- with pytest.raises(ValueError, match="Please open the URL"):
- plt.imread(url)
- with urllib.request.urlopen(url) as file:
- plt.imread(file)
- @image_comparison(['log_scale_image'], remove_text=True)
- def test_log_scale_image():
- Z = np.zeros((10, 10))
- Z[::2] = 1
- fig, ax = plt.subplots()
- ax.imshow(Z, extent=[1, 100, 1, 100], cmap='viridis', vmax=1, vmin=-1,
- aspect='auto')
- ax.set(yscale='log')
- @image_comparison(['rotate_image'], remove_text=True)
- def test_rotate_image():
- delta = 0.25
- x = y = np.arange(-3.0, 3.0, delta)
- X, Y = np.meshgrid(x, y)
- Z1 = np.exp(-(X**2 + Y**2) / 2) / (2 * np.pi)
- Z2 = (np.exp(-(((X - 1) / 1.5)**2 + ((Y - 1) / 0.5)**2) / 2) /
- (2 * np.pi * 0.5 * 1.5))
- Z = Z2 - Z1 # difference of Gaussians
- fig, ax1 = plt.subplots(1, 1)
- im1 = ax1.imshow(Z, interpolation='none', cmap='viridis',
- origin='lower',
- extent=[-2, 4, -3, 2], clip_on=True)
- trans_data2 = Affine2D().rotate_deg(30) + ax1.transData
- im1.set_transform(trans_data2)
- # display intended extent of the image
- x1, x2, y1, y2 = im1.get_extent()
- ax1.plot([x1, x2, x2, x1, x1], [y1, y1, y2, y2, y1], "r--", lw=3,
- transform=trans_data2)
- ax1.set_xlim(2, 5)
- ax1.set_ylim(0, 4)
- def test_image_preserve_size():
- buff = io.BytesIO()
- im = np.zeros((481, 321))
- plt.imsave(buff, im, format="png")
- buff.seek(0)
- img = plt.imread(buff)
- assert img.shape[:2] == im.shape
- def test_image_preserve_size2():
- n = 7
- data = np.identity(n, float)
- fig = plt.figure(figsize=(n, n), frameon=False)
- ax = plt.Axes(fig, [0.0, 0.0, 1.0, 1.0])
- ax.set_axis_off()
- fig.add_axes(ax)
- ax.imshow(data, interpolation='nearest', origin='lower', aspect='auto')
- buff = io.BytesIO()
- fig.savefig(buff, dpi=1)
- buff.seek(0)
- img = plt.imread(buff)
- assert img.shape == (7, 7, 4)
- assert_array_equal(np.asarray(img[:, :, 0], bool),
- np.identity(n, bool)[::-1])
- @image_comparison(['mask_image_over_under.png'], remove_text=True, tol=1.0)
- def test_mask_image_over_under():
- # Remove this line when this test image is regenerated.
- plt.rcParams['pcolormesh.snap'] = False
- delta = 0.025
- x = y = np.arange(-3.0, 3.0, delta)
- X, Y = np.meshgrid(x, y)
- Z1 = np.exp(-(X**2 + Y**2) / 2) / (2 * np.pi)
- Z2 = (np.exp(-(((X - 1) / 1.5)**2 + ((Y - 1) / 0.5)**2) / 2) /
- (2 * np.pi * 0.5 * 1.5))
- Z = 10*(Z2 - Z1) # difference of Gaussians
- palette = plt.cm.gray.with_extremes(over='r', under='g', bad='b')
- Zm = np.ma.masked_where(Z > 1.2, Z)
- fig, (ax1, ax2) = plt.subplots(1, 2)
- im = ax1.imshow(Zm, interpolation='bilinear',
- cmap=palette,
- norm=colors.Normalize(vmin=-1.0, vmax=1.0, clip=False),
- origin='lower', extent=[-3, 3, -3, 3])
- ax1.set_title('Green=low, Red=high, Blue=bad')
- fig.colorbar(im, extend='both', orientation='horizontal',
- ax=ax1, aspect=10)
- im = ax2.imshow(Zm, interpolation='nearest',
- cmap=palette,
- norm=colors.BoundaryNorm([-1, -0.5, -0.2, 0, 0.2, 0.5, 1],
- ncolors=256, clip=False),
- origin='lower', extent=[-3, 3, -3, 3])
- ax2.set_title('With BoundaryNorm')
- fig.colorbar(im, extend='both', spacing='proportional',
- orientation='horizontal', ax=ax2, aspect=10)
- @image_comparison(['mask_image'], remove_text=True)
- def test_mask_image():
- # Test mask image two ways: Using nans and using a masked array.
- fig, (ax1, ax2) = plt.subplots(1, 2)
- A = np.ones((5, 5))
- A[1:2, 1:2] = np.nan
- ax1.imshow(A, interpolation='nearest')
- A = np.zeros((5, 5), dtype=bool)
- A[1:2, 1:2] = True
- A = np.ma.masked_array(np.ones((5, 5), dtype=np.uint16), A)
- ax2.imshow(A, interpolation='nearest')
- def test_mask_image_all():
- # Test behavior with an image that is entirely masked does not warn
- data = np.full((2, 2), np.nan)
- fig, ax = plt.subplots()
- ax.imshow(data)
- fig.canvas.draw_idle() # would emit a warning
- @image_comparison(['imshow_endianess.png'], remove_text=True)
- def test_imshow_endianess():
- x = np.arange(10)
- X, Y = np.meshgrid(x, x)
- Z = np.hypot(X - 5, Y - 5)
- fig, (ax1, ax2) = plt.subplots(1, 2)
- kwargs = dict(origin="lower", interpolation='nearest', cmap='viridis')
- ax1.imshow(Z.astype('<f8'), **kwargs)
- ax2.imshow(Z.astype('>f8'), **kwargs)
- @image_comparison(['imshow_masked_interpolation'],
- tol=0 if platform.machine() == 'x86_64' else 0.01,
- remove_text=True, style='mpl20')
- def test_imshow_masked_interpolation():
- cmap = mpl.colormaps['viridis'].with_extremes(over='r', under='b', bad='k')
- N = 20
- n = colors.Normalize(vmin=0, vmax=N*N-1)
- data = np.arange(N*N, dtype=float).reshape(N, N)
- data[5, 5] = -1
- # This will cause crazy ringing for the higher-order
- # interpolations
- data[15, 5] = 1e5
- # data[3, 3] = np.nan
- data[15, 15] = np.inf
- mask = np.zeros_like(data).astype('bool')
- mask[5, 15] = True
- data = np.ma.masked_array(data, mask)
- fig, ax_grid = plt.subplots(3, 6)
- interps = sorted(mimage._interpd_)
- interps.remove('antialiased')
- for interp, ax in zip(interps, ax_grid.ravel()):
- ax.set_title(interp)
- ax.imshow(data, norm=n, cmap=cmap, interpolation=interp)
- ax.axis('off')
- def test_imshow_no_warn_invalid():
- plt.imshow([[1, 2], [3, np.nan]]) # Check that no warning is emitted.
- @pytest.mark.parametrize(
- 'dtype', [np.dtype(s) for s in 'u2 u4 i2 i4 i8 f4 f8'.split()])
- def test_imshow_clips_rgb_to_valid_range(dtype):
- arr = np.arange(300, dtype=dtype).reshape((10, 10, 3))
- if dtype.kind != 'u':
- arr -= 10
- too_low = arr < 0
- too_high = arr > 255
- if dtype.kind == 'f':
- arr = arr / 255
- _, ax = plt.subplots()
- out = ax.imshow(arr).get_array()
- assert (out[too_low] == 0).all()
- if dtype.kind == 'f':
- assert (out[too_high] == 1).all()
- assert out.dtype.kind == 'f'
- else:
- assert (out[too_high] == 255).all()
- assert out.dtype == np.uint8
- @image_comparison(['imshow_flatfield.png'], remove_text=True, style='mpl20')
- def test_imshow_flatfield():
- fig, ax = plt.subplots()
- im = ax.imshow(np.ones((5, 5)), interpolation='nearest')
- im.set_clim(.5, 1.5)
- @image_comparison(['imshow_bignumbers.png'], remove_text=True, style='mpl20')
- def test_imshow_bignumbers():
- rcParams['image.interpolation'] = 'nearest'
- # putting a big number in an array of integers shouldn't
- # ruin the dynamic range of the resolved bits.
- fig, ax = plt.subplots()
- img = np.array([[1, 2, 1e12], [3, 1, 4]], dtype=np.uint64)
- pc = ax.imshow(img)
- pc.set_clim(0, 5)
- @image_comparison(['imshow_bignumbers_real.png'],
- remove_text=True, style='mpl20')
- def test_imshow_bignumbers_real():
- rcParams['image.interpolation'] = 'nearest'
- # putting a big number in an array of integers shouldn't
- # ruin the dynamic range of the resolved bits.
- fig, ax = plt.subplots()
- img = np.array([[2., 1., 1.e22], [4., 1., 3.]])
- pc = ax.imshow(img)
- pc.set_clim(0, 5)
- @pytest.mark.parametrize(
- "make_norm",
- [colors.Normalize,
- colors.LogNorm,
- lambda: colors.SymLogNorm(1),
- lambda: colors.PowerNorm(1)])
- def test_empty_imshow(make_norm):
- fig, ax = plt.subplots()
- with pytest.warns(UserWarning,
- match="Attempting to set identical low and high xlims"):
- im = ax.imshow([[]], norm=make_norm())
- im.set_extent([-5, 5, -5, 5])
- fig.canvas.draw()
- with pytest.raises(RuntimeError):
- im.make_image(fig.canvas.get_renderer())
- def test_imshow_float16():
- fig, ax = plt.subplots()
- ax.imshow(np.zeros((3, 3), dtype=np.float16))
- # Ensure that drawing doesn't cause crash.
- fig.canvas.draw()
- def test_imshow_float128():
- fig, ax = plt.subplots()
- ax.imshow(np.zeros((3, 3), dtype=np.longdouble))
- with (ExitStack() if np.can_cast(np.longdouble, np.float64, "equiv")
- else pytest.warns(UserWarning)):
- # Ensure that drawing doesn't cause crash.
- fig.canvas.draw()
- def test_imshow_bool():
- fig, ax = plt.subplots()
- ax.imshow(np.array([[True, False], [False, True]], dtype=bool))
- def test_full_invalid():
- fig, ax = plt.subplots()
- ax.imshow(np.full((10, 10), np.nan))
- fig.canvas.draw()
- @pytest.mark.parametrize("fmt,counted",
- [("ps", b" colorimage"), ("svg", b"<image")])
- @pytest.mark.parametrize("composite_image,count", [(True, 1), (False, 2)])
- def test_composite(fmt, counted, composite_image, count):
- # Test that figures can be saved with and without combining multiple images
- # (on a single set of axes) into a single composite image.
- X, Y = np.meshgrid(np.arange(-5, 5, 1), np.arange(-5, 5, 1))
- Z = np.sin(Y ** 2)
- fig, ax = plt.subplots()
- ax.set_xlim(0, 3)
- ax.imshow(Z, extent=[0, 1, 0, 1])
- ax.imshow(Z[::-1], extent=[2, 3, 0, 1])
- plt.rcParams['image.composite_image'] = composite_image
- buf = io.BytesIO()
- fig.savefig(buf, format=fmt)
- assert buf.getvalue().count(counted) == count
- def test_relim():
- fig, ax = plt.subplots()
- ax.imshow([[0]], extent=(0, 1, 0, 1))
- ax.relim()
- ax.autoscale()
- assert ax.get_xlim() == ax.get_ylim() == (0, 1)
- def test_unclipped():
- fig, ax = plt.subplots()
- ax.set_axis_off()
- im = ax.imshow([[0, 0], [0, 0]], aspect="auto", extent=(-10, 10, -10, 10),
- cmap='gray', clip_on=False)
- ax.set(xlim=(0, 1), ylim=(0, 1))
- fig.canvas.draw()
- # The unclipped image should fill the *entire* figure and be black.
- # Ignore alpha for this comparison.
- assert (np.array(fig.canvas.buffer_rgba())[..., :3] == 0).all()
- def test_respects_bbox():
- fig, axs = plt.subplots(2)
- for ax in axs:
- ax.set_axis_off()
- im = axs[1].imshow([[0, 1], [2, 3]], aspect="auto", extent=(0, 1, 0, 1))
- im.set_clip_path(None)
- # Make the image invisible in axs[1], but visible in axs[0] if we pan
- # axs[1] up.
- im.set_clip_box(axs[0].bbox)
- buf_before = io.BytesIO()
- fig.savefig(buf_before, format="rgba")
- assert {*buf_before.getvalue()} == {0xff} # All white.
- axs[1].set(ylim=(-1, 0))
- buf_after = io.BytesIO()
- fig.savefig(buf_after, format="rgba")
- assert buf_before.getvalue() != buf_after.getvalue() # Not all white.
- def test_image_cursor_formatting():
- fig, ax = plt.subplots()
- # Create a dummy image to be able to call format_cursor_data
- im = ax.imshow(np.zeros((4, 4)))
- data = np.ma.masked_array([0], mask=[True])
- assert im.format_cursor_data(data) == '[]'
- data = np.ma.masked_array([0], mask=[False])
- assert im.format_cursor_data(data) == '[0]'
- data = np.nan
- assert im.format_cursor_data(data) == '[nan]'
- @check_figures_equal()
- def test_image_array_alpha(fig_test, fig_ref):
- """Per-pixel alpha channel test."""
- x = np.linspace(0, 1)
- xx, yy = np.meshgrid(x, x)
- zz = np.exp(- 3 * ((xx - 0.5) ** 2) + (yy - 0.7 ** 2))
- alpha = zz / zz.max()
- cmap = mpl.colormaps['viridis']
- ax = fig_test.add_subplot()
- ax.imshow(zz, alpha=alpha, cmap=cmap, interpolation='nearest')
- ax = fig_ref.add_subplot()
- rgba = cmap(colors.Normalize()(zz))
- rgba[..., -1] = alpha
- ax.imshow(rgba, interpolation='nearest')
- def test_image_array_alpha_validation():
- with pytest.raises(TypeError, match="alpha must be a float, two-d"):
- plt.imshow(np.zeros((2, 2)), alpha=[1, 1])
- @mpl.style.context('mpl20')
- def test_exact_vmin():
- cmap = copy(mpl.colormaps["autumn_r"])
- cmap.set_under(color="lightgrey")
- # make the image exactly 190 pixels wide
- fig = plt.figure(figsize=(1.9, 0.1), dpi=100)
- ax = fig.add_axes([0, 0, 1, 1])
- data = np.array(
- [[-1, -1, -1, 0, 0, 0, 0, 43, 79, 95, 66, 1, -1, -1, -1, 0, 0, 0, 34]],
- dtype=float,
- )
- im = ax.imshow(data, aspect="auto", cmap=cmap, vmin=0, vmax=100)
- ax.axis("off")
- fig.canvas.draw()
- # get the RGBA slice from the image
- from_image = im.make_image(fig.canvas.renderer)[0][0]
- # expand the input to be 190 long and run through norm / cmap
- direct_computation = (
- im.cmap(im.norm((data * ([[1]] * 10)).T.ravel())) * 255
- ).astype(int)
- # check than the RBGA values are the same
- assert np.all(from_image == direct_computation)
- @image_comparison(['image_placement'], extensions=['svg', 'pdf'],
- remove_text=True, style='mpl20')
- def test_image_placement():
- """
- The red box should line up exactly with the outside of the image.
- """
- fig, ax = plt.subplots()
- ax.plot([0, 0, 1, 1, 0], [0, 1, 1, 0, 0], color='r', lw=0.1)
- np.random.seed(19680801)
- ax.imshow(np.random.randn(16, 16), cmap='Blues', extent=(0, 1, 0, 1),
- interpolation='none', vmin=-1, vmax=1)
- ax.set_xlim(-0.1, 1+0.1)
- ax.set_ylim(-0.1, 1+0.1)
- # A basic ndarray subclass that implements a quantity
- # It does not implement an entire unit system or all quantity math.
- # There is just enough implemented to test handling of ndarray
- # subclasses.
- class QuantityND(np.ndarray):
- def __new__(cls, input_array, units):
- obj = np.asarray(input_array).view(cls)
- obj.units = units
- return obj
- def __array_finalize__(self, obj):
- self.units = getattr(obj, "units", None)
- def __getitem__(self, item):
- units = getattr(self, "units", None)
- ret = super().__getitem__(item)
- if isinstance(ret, QuantityND) or units is not None:
- ret = QuantityND(ret, units)
- return ret
- def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
- func = getattr(ufunc, method)
- if "out" in kwargs:
- return NotImplemented
- if len(inputs) == 1:
- i0 = inputs[0]
- unit = getattr(i0, "units", "dimensionless")
- out_arr = func(np.asarray(i0), **kwargs)
- elif len(inputs) == 2:
- i0 = inputs[0]
- i1 = inputs[1]
- u0 = getattr(i0, "units", "dimensionless")
- u1 = getattr(i1, "units", "dimensionless")
- u0 = u1 if u0 is None else u0
- u1 = u0 if u1 is None else u1
- if ufunc in [np.add, np.subtract]:
- if u0 != u1:
- raise ValueError
- unit = u0
- elif ufunc == np.multiply:
- unit = f"{u0}*{u1}"
- elif ufunc == np.divide:
- unit = f"{u0}/({u1})"
- elif ufunc in (np.greater, np.greater_equal,
- np.equal, np.not_equal,
- np.less, np.less_equal):
- # Comparisons produce unitless booleans for output
- unit = None
- else:
- return NotImplemented
- out_arr = func(i0.view(np.ndarray), i1.view(np.ndarray), **kwargs)
- else:
- return NotImplemented
- if unit is None:
- out_arr = np.array(out_arr)
- else:
- out_arr = QuantityND(out_arr, unit)
- return out_arr
- @property
- def v(self):
- return self.view(np.ndarray)
- def test_quantitynd():
- q = QuantityND([1, 2], "m")
- q0, q1 = q[:]
- assert np.all(q.v == np.asarray([1, 2]))
- assert q.units == "m"
- assert np.all((q0 + q1).v == np.asarray([3]))
- assert (q0 * q1).units == "m*m"
- assert (q1 / q0).units == "m/(m)"
- with pytest.raises(ValueError):
- q0 + QuantityND(1, "s")
- def test_imshow_quantitynd():
- # generate a dummy ndarray subclass
- arr = QuantityND(np.ones((2, 2)), "m")
- fig, ax = plt.subplots()
- ax.imshow(arr)
- # executing the draw should not raise an exception
- fig.canvas.draw()
- @check_figures_equal(extensions=['png'])
- def test_norm_change(fig_test, fig_ref):
- # LogNorm should not mask anything invalid permanently.
- data = np.full((5, 5), 1, dtype=np.float64)
- data[0:2, :] = -1
- masked_data = np.ma.array(data, mask=False)
- masked_data.mask[0:2, 0:2] = True
- cmap = mpl.colormaps['viridis'].with_extremes(under='w')
- ax = fig_test.subplots()
- im = ax.imshow(data, norm=colors.LogNorm(vmin=0.5, vmax=1),
- extent=(0, 5, 0, 5), interpolation='nearest', cmap=cmap)
- im.set_norm(colors.Normalize(vmin=-2, vmax=2))
- im = ax.imshow(masked_data, norm=colors.LogNorm(vmin=0.5, vmax=1),
- extent=(5, 10, 5, 10), interpolation='nearest', cmap=cmap)
- im.set_norm(colors.Normalize(vmin=-2, vmax=2))
- ax.set(xlim=(0, 10), ylim=(0, 10))
- ax = fig_ref.subplots()
- ax.imshow(data, norm=colors.Normalize(vmin=-2, vmax=2),
- extent=(0, 5, 0, 5), interpolation='nearest', cmap=cmap)
- ax.imshow(masked_data, norm=colors.Normalize(vmin=-2, vmax=2),
- extent=(5, 10, 5, 10), interpolation='nearest', cmap=cmap)
- ax.set(xlim=(0, 10), ylim=(0, 10))
- @pytest.mark.parametrize('x', [-1, 1])
- @check_figures_equal(extensions=['png'])
- def test_huge_range_log(fig_test, fig_ref, x):
- # parametrize over bad lognorm -1 values and large range 1 -> 1e20
- data = np.full((5, 5), x, dtype=np.float64)
- data[0:2, :] = 1E20
- ax = fig_test.subplots()
- ax.imshow(data, norm=colors.LogNorm(vmin=1, vmax=data.max()),
- interpolation='nearest', cmap='viridis')
- data = np.full((5, 5), x, dtype=np.float64)
- data[0:2, :] = 1000
- ax = fig_ref.subplots()
- cmap = mpl.colormaps['viridis'].with_extremes(under='w')
- ax.imshow(data, norm=colors.Normalize(vmin=1, vmax=data.max()),
- interpolation='nearest', cmap=cmap)
- @check_figures_equal()
- def test_spy_box(fig_test, fig_ref):
- # setting up reference and test
- ax_test = fig_test.subplots(1, 3)
- ax_ref = fig_ref.subplots(1, 3)
- plot_data = (
- [[1, 1], [1, 1]],
- [[0, 0], [0, 0]],
- [[0, 1], [1, 0]],
- )
- plot_titles = ["ones", "zeros", "mixed"]
- for i, (z, title) in enumerate(zip(plot_data, plot_titles)):
- ax_test[i].set_title(title)
- ax_test[i].spy(z)
- ax_ref[i].set_title(title)
- ax_ref[i].imshow(z, interpolation='nearest',
- aspect='equal', origin='upper', cmap='Greys',
- vmin=0, vmax=1)
- ax_ref[i].set_xlim(-0.5, 1.5)
- ax_ref[i].set_ylim(1.5, -0.5)
- ax_ref[i].xaxis.tick_top()
- ax_ref[i].title.set_y(1.05)
- ax_ref[i].xaxis.set_ticks_position('both')
- ax_ref[i].xaxis.set_major_locator(
- mticker.MaxNLocator(nbins=9, steps=[1, 2, 5, 10], integer=True)
- )
- ax_ref[i].yaxis.set_major_locator(
- mticker.MaxNLocator(nbins=9, steps=[1, 2, 5, 10], integer=True)
- )
- @image_comparison(["nonuniform_and_pcolor.png"], style="mpl20")
- def test_nonuniform_and_pcolor():
- axs = plt.figure(figsize=(3, 3)).subplots(3, sharex=True, sharey=True)
- for ax, interpolation in zip(axs, ["nearest", "bilinear"]):
- im = NonUniformImage(ax, interpolation=interpolation)
- im.set_data(np.arange(3) ** 2, np.arange(3) ** 2,
- np.arange(9).reshape((3, 3)))
- ax.add_image(im)
- axs[2].pcolorfast( # PcolorImage
- np.arange(4) ** 2, np.arange(4) ** 2, np.arange(9).reshape((3, 3)))
- for ax in axs:
- ax.set_axis_off()
- # NonUniformImage "leaks" out of extents, not PColorImage.
- ax.set(xlim=(0, 10))
- @image_comparison(
- ['rgba_antialias.png'], style='mpl20', remove_text=True,
- tol=0.007 if platform.machine() in ('aarch64', 'ppc64le', 's390x') else 0)
- def test_rgba_antialias():
- fig, axs = plt.subplots(2, 2, figsize=(3.5, 3.5), sharex=False,
- sharey=False, constrained_layout=True)
- N = 250
- aa = np.ones((N, N))
- aa[::2, :] = -1
- x = np.arange(N) / N - 0.5
- y = np.arange(N) / N - 0.5
- X, Y = np.meshgrid(x, y)
- R = np.sqrt(X**2 + Y**2)
- f0 = 10
- k = 75
- # aliased concentric circles
- a = np.sin(np.pi * 2 * (f0 * R + k * R**2 / 2))
- # stripes on lhs
- a[:int(N/2), :][R[:int(N/2), :] < 0.4] = -1
- a[:int(N/2), :][R[:int(N/2), :] < 0.3] = 1
- aa[:, int(N/2):] = a[:, int(N/2):]
- # set some over/unders and NaNs
- aa[20:50, 20:50] = np.nan
- aa[70:90, 70:90] = 1e6
- aa[70:90, 20:30] = -1e6
- aa[70:90, 195:215] = 1e6
- aa[20:30, 195:215] = -1e6
- cmap = copy(plt.cm.RdBu_r)
- cmap.set_over('yellow')
- cmap.set_under('cyan')
- axs = axs.flatten()
- # zoom in
- axs[0].imshow(aa, interpolation='nearest', cmap=cmap, vmin=-1.2, vmax=1.2)
- axs[0].set_xlim([N/2-25, N/2+25])
- axs[0].set_ylim([N/2+50, N/2-10])
- # no anti-alias
- axs[1].imshow(aa, interpolation='nearest', cmap=cmap, vmin=-1.2, vmax=1.2)
- # data antialias: Note no purples, and white in circle. Note
- # that alternating red and blue stripes become white.
- axs[2].imshow(aa, interpolation='antialiased', interpolation_stage='data',
- cmap=cmap, vmin=-1.2, vmax=1.2)
- # rgba antialias: Note purples at boundary with circle. Note that
- # alternating red and blue stripes become purple
- axs[3].imshow(aa, interpolation='antialiased', interpolation_stage='rgba',
- cmap=cmap, vmin=-1.2, vmax=1.2)
- # We check for the warning with a draw() in the test, but we also need to
- # filter the warning as it is emitted by the figure test decorator
- @pytest.mark.filterwarnings(r'ignore:Data with more than .* '
- 'cannot be accurately displayed')
- @pytest.mark.parametrize('origin', ['upper', 'lower'])
- @pytest.mark.parametrize(
- 'dim, size, msg', [['row', 2**23, r'2\*\*23 columns'],
- ['col', 2**24, r'2\*\*24 rows']])
- @check_figures_equal(extensions=('png', ))
- def test_large_image(fig_test, fig_ref, dim, size, msg, origin):
- # Check that Matplotlib downsamples images that are too big for AGG
- # See issue #19276. Currently the fix only works for png output but not
- # pdf or svg output.
- ax_test = fig_test.subplots()
- ax_ref = fig_ref.subplots()
- array = np.zeros((1, size + 2))
- array[:, array.size // 2:] = 1
- if dim == 'col':
- array = array.T
- im = ax_test.imshow(array, vmin=0, vmax=1,
- aspect='auto', extent=(0, 1, 0, 1),
- interpolation='none',
- origin=origin)
- with pytest.warns(UserWarning,
- match=f'Data with more than {msg} cannot be '
- 'accurately displayed.'):
- fig_test.canvas.draw()
- array = np.zeros((1, 2))
- array[:, 1] = 1
- if dim == 'col':
- array = array.T
- im = ax_ref.imshow(array, vmin=0, vmax=1, aspect='auto',
- extent=(0, 1, 0, 1),
- interpolation='none',
- origin=origin)
- @check_figures_equal(extensions=["png"])
- def test_str_norms(fig_test, fig_ref):
- t = np.random.rand(10, 10) * .8 + .1 # between 0 and 1
- axts = fig_test.subplots(1, 5)
- axts[0].imshow(t, norm="log")
- axts[1].imshow(t, norm="log", vmin=.2)
- axts[2].imshow(t, norm="symlog")
- axts[3].imshow(t, norm="symlog", vmin=.3, vmax=.7)
- axts[4].imshow(t, norm="logit", vmin=.3, vmax=.7)
- axrs = fig_ref.subplots(1, 5)
- axrs[0].imshow(t, norm=colors.LogNorm())
- axrs[1].imshow(t, norm=colors.LogNorm(vmin=.2))
- # same linthresh as SymmetricalLogScale's default.
- axrs[2].imshow(t, norm=colors.SymLogNorm(linthresh=2))
- axrs[3].imshow(t, norm=colors.SymLogNorm(linthresh=2, vmin=.3, vmax=.7))
- axrs[4].imshow(t, norm="logit", clim=(.3, .7))
- assert type(axts[0].images[0].norm) is colors.LogNorm # Exactly that class
- with pytest.raises(ValueError):
- axts[0].imshow(t, norm="foobar")
- def test__resample_valid_output():
- resample = functools.partial(mpl._image.resample, transform=Affine2D())
- with pytest.raises(ValueError, match="must be a NumPy array"):
- resample(np.zeros((9, 9)), None)
- with pytest.raises(ValueError, match="different dimensionalities"):
- resample(np.zeros((9, 9)), np.zeros((9, 9, 4)))
- with pytest.raises(ValueError, match="must be RGBA"):
- resample(np.zeros((9, 9, 4)), np.zeros((9, 9, 3)))
- with pytest.raises(ValueError, match="Mismatched types"):
- resample(np.zeros((9, 9), np.uint8), np.zeros((9, 9)))
- with pytest.raises(ValueError, match="must be C-contiguous"):
- resample(np.zeros((9, 9)), np.zeros((9, 9)).T)
- def test_axesimage_get_shape():
- # generate dummy image to test get_shape method
- ax = plt.gca()
- im = AxesImage(ax)
- with pytest.raises(RuntimeError, match="You must first set the image array"):
- im.get_shape()
- z = np.arange(12, dtype=float).reshape((4, 3))
- im.set_data(z)
- assert im.get_shape() == (4, 3)
- assert im.get_size() == im.get_shape()
- def test_non_transdata_image_does_not_touch_aspect():
- ax = plt.figure().add_subplot()
- im = np.arange(4).reshape((2, 2))
- ax.imshow(im, transform=ax.transAxes)
- assert ax.get_aspect() == "auto"
- ax.imshow(im, transform=Affine2D().scale(2) + ax.transData)
- assert ax.get_aspect() == 1
- ax.imshow(im, transform=ax.transAxes, aspect=2)
- assert ax.get_aspect() == 2
|