@@ -1908,6 +1908,64 @@ def test_nn_pixel_alignment(nonaffine_identity):
19081908 axs [i , j ].hlines (seps , - 1 , N , lw = 0.5 , color = 'red' , ls = 'dashed' )
19091909
19101910
1911+ @image_comparison (['alignment_half_display_pixels.png' ], style = 'mpl20' )
1912+ def test_alignment_half_display_pixels (nonaffine_identity ):
1913+ # All values in this test are chosen carefully so that many display pixels are
1914+ # aligned with an edge or a corner of an input pixel
1915+
1916+ # Layout:
1917+ # Top row is origin='upper', bottom row is origin='lower'
1918+ # Column 1: affine transform, anchored at whole pixel
1919+ # Column 2: affine transform, anchored at half pixel
1920+ # Column 3: nonaffine transform, anchored at whole pixel
1921+ # Column 4: nonaffine transform, anchored at half pixel
1922+ # Column 5: affine transform, anchored at half pixel, interpolation='hanning'
1923+
1924+ # Each axes patch is magenta, so seeing a magenta line at an edge of the image
1925+ # means that the image is not filling the axes
1926+
1927+ fig = plt .figure (figsize = (5 , 2 ), dpi = 100 )
1928+ fig .set_facecolor ('g' )
1929+
1930+ corner_x = [0.01 , 0.199 , 0.41 , 0.599 , 0.809 ]
1931+ corner_y = [0.05 , 0.53 ]
1932+
1933+ axs = []
1934+ for cy in corner_y :
1935+ for ix , cx in enumerate (corner_x ):
1936+ my = cy + 0.0125 if ix in [1 , 3 , 4 ] else cy
1937+ axs .append (fig .add_axes ([cx , my , 0.17 , 0.425 ], xticks = [], yticks = []))
1938+
1939+ # Verify that each axes has been created with the correct width/height and that all
1940+ # four corners are on whole pixels (columns 1 and 3) or half pixels (columns 2, 4,
1941+ # and 5)
1942+ for i , ax in enumerate (axs ):
1943+ extents = ax .get_window_extent ().extents
1944+ assert_allclose (extents [2 :4 ] - extents [0 :2 ], 85 , rtol = 0 , atol = 1e-13 )
1945+ assert_allclose (extents % 1 , 0.5 if i % 5 in [1 , 3 , 4 ] else 0 ,
1946+ rtol = 0 , atol = 1e-13 )
1947+
1948+ N = 10
1949+
1950+ data = np .arange (N ** 2 ).reshape ((N , N )) % 9
1951+ seps = np .arange (- 0.5 , N )
1952+
1953+ for i , ax in enumerate (axs ):
1954+ ax .set_facecolor ('m' )
1955+
1956+ transform = nonaffine_identity + ax .transData if i % 4 >= 2 else ax .transData
1957+ ax .imshow (data , cmap = 'Blues' ,
1958+ interpolation = 'hanning' if i % 5 == 4 else 'nearest' ,
1959+ origin = 'upper' if i >= 5 else 'lower' ,
1960+ transform = transform )
1961+
1962+ ax .vlines (seps , - 0.5 , N - 0.5 , lw = 0.5 , color = 'red' , ls = (0 , (2 , 4 )))
1963+ ax .hlines (seps , - 0.5 , N - 0.5 , lw = 0.5 , color = 'red' , ls = (0 , (2 , 4 )))
1964+
1965+ for spine in ax .spines :
1966+ ax .spines [spine ].set_linestyle ((0 , (5 , 10 )))
1967+
1968+
19111969@image_comparison (['image_bounds_handling.png' ], tol = 0.006 )
19121970def test_image_bounds_handling (nonaffine_identity ):
19131971 # TODO: The second and third panels in the bottom row show that the handling of
0 commit comments