Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
Release 1.5 (unreleased)
========================


Features added
--------------
* A new transpose keyword argument for `iris.plot.plot` and `iris.quickplot.plot`
allows the coordinate of a 1d plot to be presented on the y-axis with the data
values on the x-axis.


----------------------------


Release 1.4 (unreleased)
========================

Expand Down
30 changes: 30 additions & 0 deletions docs/iris/src/whatsnew/1.5.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
What's new in Iris 1.5
**********************

:Release: 1.5.0
:Date: unreleased

This document explains the new/changed features of Iris in version 1.5.

Iris 1.5 features
=================

A summary of the main features added with version 1.5:

* A new transpose keyword argument for :func:`iris.plot.plot` and
:func:`iris.quickplot.plot` allows the coordinate of a 1d plot to be
presented on the y-axis with the data values on the x-axis.

Bugs fixed
----------
* N/A

Incompatible changes
--------------------
* N/A

Deprecations
------------
* N/A


11 changes: 11 additions & 0 deletions lib/iris/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,11 @@ def _draw_1d_from_points(draw_method_name, arg_func, cube, *args, **kwargs):
else:
u = np.arange(data.shape[0])

# get & remove the transpose entry from kwargs
transpose = kwargs.pop('transpose', False)
if transpose:
u, data = data, u

draw_method = getattr(plt, draw_method_name)
if arg_func is not None:
args, kwargs = arg_func(u, data, *args, **kwargs)
Expand Down Expand Up @@ -718,6 +723,12 @@ def plot(cube, *args, **kwargs):
element is the horizontal axis of the plot and the second element is
the vertical axis of the plot.

* transpose: True or False
If False the plot will have the coordinate on the x-axis and the data
values on the y-axis. If True the plot axes will be transposed with the
coordinate on the y-axis and the data values on the x-axis. This is
suitable for vertical profile type plots. Defaults to False.

See :func:`matplotlib.pyplot.plot` for details of other valid keyword
arguments.

Expand Down
20 changes: 14 additions & 6 deletions lib/iris/quickplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def _title(cube_or_coord, with_units):
return title


def _label(cube, mode, result=None, ndims=2, coords=None):
def _label(cube, mode, result=None, ndims=2, coords=None, transpose1d=False):
"""Puts labels on the current plot using the given cube."""

plt.title(_title(cube, with_units=False))
Expand Down Expand Up @@ -82,8 +82,14 @@ def _label(cube, mode, result=None, ndims=2, coords=None):
plt.ylabel(_title(plot_defn.coords[0], with_units=True))
plt.xlabel(_title(plot_defn.coords[1], with_units=True))
elif ndims == 1:
plt.xlabel(_title(plot_defn.coords[0], with_units=True))
plt.ylabel(_title(cube, with_units=True))
cube_title = _title(cube, with_units=True)
coord_title = _title(plot_defn.coords[0], with_units=True)
if transpose1d:
plt.xlabel(cube_title)
plt.ylabel(coord_title)
else:
plt.xlabel(coord_title)
plt.ylabel(cube_title)
else:
raise ValueError('Unexpected number of dimensions (%s) given to _label.' % ndims)

Expand All @@ -92,8 +98,9 @@ def _label_with_bounds(cube, result=None, ndims=2, coords=None):
_label(cube, iris.coords.BOUND_MODE, result, ndims, coords)


def _label_with_points(cube, result=None, ndims=2, coords=None):
_label(cube, iris.coords.POINT_MODE, result, ndims, coords)
def _label_with_points(cube, result=None, ndims=2, coords=None,
transpose1d=False):
_label(cube, iris.coords.POINT_MODE, result, ndims, coords, transpose1d)


def contour(cube, *args, **kwargs):
Expand Down Expand Up @@ -200,6 +207,7 @@ def plot(cube, *args, **kwargs):

"""
coords = kwargs.get('coords')
transpose = kwargs.get('transpose', False)
result = iplt.plot(cube, *args, **kwargs)
_label_with_points(cube, ndims=1, coords=coords)
_label_with_points(cube, ndims=1, coords=coords, transpose1d=transpose)
return result
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions lib/iris/tests/test_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,24 @@ def test_orography(self):
self.check_graphic()


@iris.tests.skip_data
class Test1dPlotTranspose(tests.GraphicsTest):

def setUp(self):
path = tests.get_data_path(('NetCDF', 'ORCA2', 'votemper.nc'))
self.cube = iris.load_cube(path)[0, :, 60, 80]

def test_transpose_true(self):
# put the coordinate on the y-axis
qplt.plot(self.cube, transpose=True)
self.check_graphic()

def test_transpose_false(self):
# put the coordinate on the x-axis (normal behaviour)
qplt.plot(self.cube, transpose=False)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick brain-dump:

There was a conversation a while ago to allow users to pick the dimension of the data to plot (I think the syntax was something like coords=('dim1', 'time')) I don't necessarily like the proposal, but I do think the functionality would be useful. An extension to this capability that I have thought of a couple of times would be to allow users to specify "data" in some way as one of the plot axis. Using this same clunky syntax that might look like coords=('data', 'time').
Having such a capability would allow one to define the coordinate order of the plot without the need for the boolean keyword argument.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having such a capability would allow one to define the coordinate order of the plot without the need for the boolean keyword argument.

@esc24 and I touched on the data-token idea when we were discussing his proposal. But as things stand I'd rather we take the route he proposed on this PR.

self.check_graphic()


# Caches _load_4d_testcube so subsequent calls are faster
def cache(fn, cache={}):
def inner(*args, **kwargs):
Expand Down