diff --git a/CHANGES b/CHANGES index 98e42a5cd5..20060876ba 100644 --- a/CHANGES +++ b/CHANGES @@ -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) ======================== diff --git a/docs/iris/src/whatsnew/1.5.rst b/docs/iris/src/whatsnew/1.5.rst new file mode 100644 index 0000000000..0007480be3 --- /dev/null +++ b/docs/iris/src/whatsnew/1.5.rst @@ -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 + + diff --git a/lib/iris/plot.py b/lib/iris/plot.py index ed002a3e58..173fd9b0b6 100644 --- a/lib/iris/plot.py +++ b/lib/iris/plot.py @@ -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) @@ -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. diff --git a/lib/iris/quickplot.py b/lib/iris/quickplot.py index b3b75b5f2d..3948b6ccf8 100644 --- a/lib/iris/quickplot.py +++ b/lib/iris/quickplot.py @@ -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)) @@ -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) @@ -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): @@ -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 diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotTranspose.test_transpose_false.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotTranspose.test_transpose_false.0.png new file mode 100644 index 0000000000..63c0ce28a6 Binary files /dev/null and b/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotTranspose.test_transpose_false.0.png differ diff --git a/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotTranspose.test_transpose_true.0.png b/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotTranspose.test_transpose_true.0.png new file mode 100644 index 0000000000..3a3f0189c1 Binary files /dev/null and b/lib/iris/tests/results/visual_tests/test_plot.Test1dPlotTranspose.test_transpose_true.0.png differ diff --git a/lib/iris/tests/test_plot.py b/lib/iris/tests/test_plot.py index b6dbcae988..8080789a84 100644 --- a/lib/iris/tests/test_plot.py +++ b/lib/iris/tests/test_plot.py @@ -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) + self.check_graphic() + + # Caches _load_4d_testcube so subsequent calls are faster def cache(fn, cache={}): def inner(*args, **kwargs):