8000 FIX: add support for imshow extent to have units · matplotlib/matplotlib@d1b5289 · GitHub
[go: up one dir, main page]

Skip to content

Commit d1b5289

Browse filesBrowse files
committed
FIX: add support for imshow extent to have units
1 parent b9ae51c commit d1b5289

File tree

5 files changed

+59
-4
lines changed

5 files changed

+59
-4
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
The *extent* parameter of imshow and set_extent functions can now be expressed with units
2+
-----------------------------------------------------------------------------------------
3+
The *extent* parameter of `~axes.Axes.imshow` and `~AxesImage.set_extent`
4+
can now be expressed with units.
5+
6+
.. plot::
7+
:include-source: true
8+
9+
import matplotlib.pyplot as plt
10+
import numpy as np
11+
from matplotlib.dates import HourLocator, DateFormatter
12+
from matplotlib.ticker import AutoMinorLocator
13+
14+
15+
fig, ax = plt.subplots()
16+
dates = np.arange("2020-01-01","2020-01-13", dtype='datetime64[h]')
17+
18+
arr = [[i+j for i in range(10)] for j in range(10)]
19+
20+
ax.imshow(arr, origin='lower', extent=[dates[0], dates[10], dates[10], dates[0]])
21+
22+
ax.xaxis.set_major_formatter(DateFormatter('%d/%m:%H'))
23+
ax.xaxis.set_major_locator(HourLocator(byhour=[0, 2, 4, 6, 8, 10]))
24+
ax.xaxis.set_minor_locator(AutoMinorLocator())
25+
26+
plt.show()

lib/matplotlib/axes/_axes.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5375,7 +5375,7 @@ def imshow(self, X, cmap=None, norm=None, aspect=None,
53755375
See the :doc:`/tutorials/intermediate/imshow_extent` tutorial for
53765376
examples and a more detailed description.
53775377
5378-
extent : floats (left, right, bottom, top), optional
5378+
extent : floats or units (left, right, bottom, top), optional
53795379
The bounding box in data coordinates that the image will fill.
53805380
The image is stretched individually along x and y to fill the box.
53815381
@@ -5452,6 +5452,7 @@ def imshow(self, X, cmap=None, norm=None, aspect=None,
54525452
if aspect is None:
54535453
aspect = rcParams['image.aspect']
54545454
self.set_aspect(aspect)
5455+
54555456
im = mimage.AxesImage(self, cmap, norm, interpolation,
54565457
origin, extent, filternorm=filternorm,
54575458
filterrad=filterrad, resample=resample,
@@ -5468,7 +5469,7 @@ def imshow(self, X, cmap=None, norm=None, aspect=None,
54685469

54695470
# update ax.dataLim, and, if autoscaling, set viewLim
54705471
# to tightly fit the image, regardless of dataLim.
5471-
im.set_extent(im.get_extent())
5472+
im.set_extent(im.get_extent(), **kwargs)
54725473

54735474
self.add_image(im)
54745475
return im

lib/matplotlib/image.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -952,7 +952,7 @@ def _check_unsampled_image(self):
952952
"""Return whether the image would be better drawn unsampled."""
953953
return self.get_interpolation() == "none"
954954

955-
def set_extent(self, extent):
955+
def set_extent(self, extent, **kwargs):
956956
"""
957957
Set the image extent.
958958
@@ -961,6 +961,10 @@ def set_extent(self, extent):
961961
extent : 4-tuple of float
962962
The position and size of the image as tuple
963963
``(left, right, bottom, top)`` in data coordinates.
964+
**kwargs
965+
Other parameters from which unit info (i.e., the *xunits*,
966+
*yunits*, *zunits* (for 3D axes), *runits* and *thetaunits* (for
967+
polar axes) entries are applied, if present.
964968
965969
Notes
966970
-----
@@ -969,7 +973,21 @@ def set_extent(self, extent):
969973
state is not changed, so following this with ``ax.autoscale_view()``
970974
will redo the autoscaling in accord with ``dataLim``.
971975
"""
972-
self._extent = xmin, xmax, ymin, ymax = extent
976+
(xmin, xmax), (ymin, ymax) = self.axes._process_unit_info(
977+
[("x", [extent[0], extent[1]]),
978+
("y", [extent[2], extent[3]])],
979+
kwargs)
980+
xmin = self.axes._validate_converted_limits(
981+
xmin, self.convert_xunits)
982+
xmax = self.axes._validate_converted_limits(
983+
xmax, self.convert_xunits)
984+
ymin = self.axes._validate_converted_limits(
985+
ymin, self.convert_yunits)
986+
ymax = self.axes._validate_converted_limits(
987+
ymax, self.convert_yunits)
988+
extent = [xmin, xmax, ymin, ymax]
989+
990+
self._extent = extent
973991
corners = (xmin, ymin), (xmax, ymax)
974992
self.axes.update_datalim(corners)
975993
self.sticky_edges.x[:] = [xmin, xmax]
Binary file not shown.

lib/matplotlib/tests/test_axes.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7605,3 +7605,13 @@ def test_bezier_autoscale():
76057605
# Bottom ylim should be at the edge of the curve (-0.5), and not include
76067606
# the control point (at -1)
76077607
assert ax.get_ylim()[0] == -0.5
7608+
7609+
7610+
@image_comparison(["extent_units.pdf"])
7611+
def test_extent_units():
7612+
mpl.style.use("mpl20")
7613+
fig, ax = plt.subplots()
7614+
dates = np.arange("2020-01-01", "2020-01-13", dtype='datetime64')
7615+
arr = [[i+j for i in range(10)] for j in range(10)]
7616+
ax.imshow(arr, origin='lower',
7617+
extent=[0, 10, dates[10], dates[0]])

0 commit comments

Comments
 (0)
0