From 7b216b35749b2ed578b044a4fa8e4036aab037f5 Mon Sep 17 00:00:00 2001 From: jbusecke Date: Thu, 10 Jan 2019 16:15:21 -0500 Subject: [PATCH 01/17] WIP: enable internal plotting with cftime datetime --- xarray/core/common.py | 1 + xarray/plot/plot.py | 48 ++++++++++++++++++++++++++++++++------- xarray/plot/utils.py | 18 ++++++++++++--- xarray/tests/test_plot.py | 38 +++++++++++++++---------------- 4 files changed, 75 insertions(+), 30 deletions(-) diff --git a/xarray/core/common.py b/xarray/core/common.py index 30ea56f3496..439d254bec0 100644 --- a/xarray/core/common.py +++ b/xarray/core/common.py @@ -1002,6 +1002,7 @@ def contains_cftime_datetimes(var): try: from cftime import datetime as cftime_datetime except ImportError: + print('Could not import cftime') return False else: if var.dtype == np.dtype('O') and var.data.size > 0: diff --git a/xarray/plot/plot.py b/xarray/plot/plot.py index 5b60f8d73a1..a4234982bdd 100644 --- a/xarray/plot/plot.py +++ b/xarray/plot/plot.py @@ -20,6 +20,12 @@ _update_axes, _valid_other_type, get_axis, import_matplotlib_pyplot, label_from_attrs) +try: + from nc_time_axis import CalendarDateTime + nc_axis_available = True +except ImportError: + nc_axis_available = False + def _infer_line_data(darray, x, y, hue): error_msg = ('must be either None or one of ({0:s})' @@ -98,6 +104,26 @@ def _infer_line_data(darray, x, y, hue): return xplt, yplt, hueplt, xlabel, ylabel, huelabel +def _convert_cftime_data(values): + converted = [CalendarDateTime(v, v.calendar) for v in values] + return converted + + +def _convert_all_cftime(da): + try: + from cftime import datetime as cftime_datetime + except ImportError: + raise ImportError('cftime package missing') + da = da.copy() + # find the dim that has a cftime datatype + dims = set(da.dims) + cftime_dims = [d for d in dims if isinstance(da[d].data.ravel()[0], + cftime_datetime)] + for cd in cftime_dims: + da[cd].data = _convert_cftime_data(da[cd].data) + return da + + def plot(darray, row=None, col=None, col_wrap=None, ax=None, hue=None, rtol=0.01, subplot_kws=None, **kwargs): """ @@ -139,14 +165,20 @@ def plot(darray, row=None, col=None, col_wrap=None, ax=None, hue=None, """ darray = darray.squeeze() - if contains_cftime_datetimes(darray): - raise NotImplementedError( - 'Built-in plotting of arrays of cftime.datetime objects or arrays ' - 'indexed by cftime.datetime objects is currently not implemented ' - 'within xarray. A possible workaround is to use the ' - 'nc-time-axis package ' - '(https://github.com/SciTools/nc-time-axis) to convert the dates ' - 'to a plottable type and plot your data directly with matplotlib.') + # If I am not mistaken, this did check only if there are cftime.datetime + # objects in the actual data, not dims. + # Correction below + + if any([contains_cftime_datetimes(darray[dim]) for dim in darray.dims]): + if nc_axis_available: + darray = _convert_all_cftime(darray) + else: + raise ImportError( + 'Built-in plotting of arrays of cftime.datetime objects or ' + 'arrays indexed by cftime.datetime objects requires the ' + 'optional `nc-time-axis` package ' + '(https://github.com/SciTools/nc-time-axis).' + ) plot_dims = set(darray.dims) plot_dims.discard(row) diff --git a/xarray/plot/utils.py b/xarray/plot/utils.py index 6d812fbc2bc..8fa21f9da6e 100644 --- a/xarray/plot/utils.py +++ b/xarray/plot/utils.py @@ -471,13 +471,25 @@ def _ensure_plottable(*args): """ numpy_types = [np.floating, np.integer, np.timedelta64, np.datetime64] other_types = [datetime] - + try: + import cftime + cftime_datetime = [cftime.datetime] + except ImportError: + cftime_datetime = [] + other_types = other_types + cftime_datetime for x in args: if not (_valid_numpy_subdtype(np.array(x), numpy_types) or _valid_other_type(np.array(x), other_types)): raise TypeError('Plotting requires coordinates to be numeric ' - 'or dates of type np.datetime64 or ' - 'datetime.datetime or pd.Interval.') + 'or dates of type np.datetime64, ' + 'datetime.datetime, or cftime.datetime or ' + 'pd.Interval.') + if (_valid_other_type(np.array(x), cftime_datetime) + and not nc_time_axis_available): + raise ImportError('Plotting of arrays of cftime.datetime ' + 'objects or arrays indexed by ' + 'cftime.datetime objects requires the ' + 'optional `nc-time-axis` package.') def _ensure_numeric(arr): diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py index 3b08ce706f5..f0fe94e254e 100644 --- a/xarray/tests/test_plot.py +++ b/xarray/tests/test_plot.py @@ -1844,25 +1844,25 @@ def test_plot_seaborn_no_import_warning(): assert len(record) == 0 -@requires_cftime -def test_plot_cftime_coordinate_error(): - cftime = _import_cftime() - time = cftime.num2date(np.arange(5), units='days since 0001-01-01', - calendar='noleap') - data = DataArray(np.arange(5), coords=[time], dims=['time']) - with raises_regex(TypeError, - 'requires coordinates to be numeric or dates'): - data.plot() - - -@requires_cftime -def test_plot_cftime_data_error(): - cftime = _import_cftime() - data = cftime.num2date(np.arange(5), units='days since 0001-01-01', - calendar='noleap') - data = DataArray(data, coords=[np.arange(5)], dims=['x']) - with raises_regex(NotImplementedError, 'cftime.datetime'): - data.plot() +# @requires_cftime +# def test_plot_cftime_coordinate_error(): +# cftime = _import_cftime() +# time = cftime.num2date(np.arange(5), units='days since 0001-01-01', +# calendar='noleap') +# data = DataArray(np.arange(5), coords=[time], dims=['time']) +# with raises_regex(TypeError, +# 'requires coordinates to be numeric or dates'): +# data.plot() + + +# @requires_cftime +# def test_plot_cftime_data_error(): +# cftime = _import_cftime() +# data = cftime.num2date(np.arange(5), units='days since 0001-01-01', +# calendar='noleap') +# data = DataArray(data, coords=[np.arange(5)], dims=['x']) +# with raises_regex(NotImplementedError, 'cftime.datetime'): +# data.plot() test_da_list = [DataArray(easy_array((10, ))), From 879cdc548e944b2601c44ab869e791827d1c2f57 Mon Sep 17 00:00:00 2001 From: jbusecke Date: Fri, 25 Jan 2019 18:02:42 -0500 Subject: [PATCH 02/17] adjusted to upstream changes in nc-time-axis --- xarray/plot/plot.py | 47 +++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/xarray/plot/plot.py b/xarray/plot/plot.py index a4234982bdd..a982efcab2b 100644 --- a/xarray/plot/plot.py +++ b/xarray/plot/plot.py @@ -21,7 +21,7 @@ label_from_attrs) try: - from nc_time_axis import CalendarDateTime + import nc_time_axis nc_axis_available = True except ImportError: nc_axis_available = False @@ -104,24 +104,24 @@ def _infer_line_data(darray, x, y, hue): return xplt, yplt, hueplt, xlabel, ylabel, huelabel -def _convert_cftime_data(values): - converted = [CalendarDateTime(v, v.calendar) for v in values] - return converted +# def _convert_cftime_data(values): +# converted = [CalendarDateTime(v, v.calendar) for v in values] +# return converted -def _convert_all_cftime(da): - try: - from cftime import datetime as cftime_datetime - except ImportError: - raise ImportError('cftime package missing') - da = da.copy() - # find the dim that has a cftime datatype - dims = set(da.dims) - cftime_dims = [d for d in dims if isinstance(da[d].data.ravel()[0], - cftime_datetime)] - for cd in cftime_dims: - da[cd].data = _convert_cftime_data(da[cd].data) - return da +# def _convert_all_cftime(da): +# try: +# from cftime import datetime as cftime_datetime +# except ImportError: +# raise ImportError('cftime package missing') +# da = da.copy() +# # find the dim that has a cftime datatype +# dims = set(da.dims) +# cftime_dims = [d for d in dims if isinstance(da[d].data.ravel()[0], +# cftime_datetime)] +# for cd in cftime_dims: +# da[cd].data = _convert_cftime_data(da[cd].data) +# return da def plot(darray, row=None, col=None, col_wrap=None, ax=None, hue=None, @@ -164,15 +164,12 @@ def plot(darray, row=None, col=None, col_wrap=None, ax=None, hue=None, """ darray = darray.squeeze() - - # If I am not mistaken, this did check only if there are cftime.datetime - # objects in the actual data, not dims. - # Correction below - + # Unsure about this. If I read correctly the commented line tests if + # cftime datetimes are in the data, not the dims. I assume we want to check + # the dims? if any([contains_cftime_datetimes(darray[dim]) for dim in darray.dims]): - if nc_axis_available: - darray = _convert_all_cftime(darray) - else: + # if contains_cftime_datetimes(darray): + if not nc_axis_available: raise ImportError( 'Built-in plotting of arrays of cftime.datetime objects or ' 'arrays indexed by cftime.datetime objects requires the ' From b67f5327124cd21ab101e64e92cd871b38d853f3 Mon Sep 17 00:00:00 2001 From: jbusecke Date: Fri, 25 Jan 2019 20:01:55 -0500 Subject: [PATCH 03/17] simplified type checking for plot variables --- xarray/plot/plot.py | 20 +++----------------- xarray/tests/test_plot.py | 21 --------------------- 2 files changed, 3 insertions(+), 38 deletions(-) diff --git a/xarray/plot/plot.py b/xarray/plot/plot.py index a982efcab2b..f05a3edd823 100644 --- a/xarray/plot/plot.py +++ b/xarray/plot/plot.py @@ -10,9 +10,7 @@ import numpy as np import pandas as pd -from xarray.core.common import contains_cftime_datetimes - -from .facetgrid import _easy_facetgrid +from .facetgrid import FacetGrid from .utils import ( _add_colorbar, _ensure_plottable, _infer_interval_breaks, _infer_xy_labels, _interval_to_double_bound_points, _interval_to_mid_points, @@ -22,9 +20,9 @@ try: import nc_time_axis - nc_axis_available = True + nc_time_axis_available = True except ImportError: - nc_axis_available = False + nc_time_axis_available = False def _infer_line_data(darray, x, y, hue): @@ -164,18 +162,6 @@ def plot(darray, row=None, col=None, col_wrap=None, ax=None, hue=None, """ darray = darray.squeeze() - # Unsure about this. If I read correctly the commented line tests if - # cftime datetimes are in the data, not the dims. I assume we want to check - # the dims? - if any([contains_cftime_datetimes(darray[dim]) for dim in darray.dims]): - # if contains_cftime_datetimes(darray): - if not nc_axis_available: - raise ImportError( - 'Built-in plotting of arrays of cftime.datetime objects or ' - 'arrays indexed by cftime.datetime objects requires the ' - 'optional `nc-time-axis` package ' - '(https://github.com/SciTools/nc-time-axis).' - ) plot_dims = set(darray.dims) plot_dims.discard(row) diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py index f0fe94e254e..96f88b7bfb3 100644 --- a/xarray/tests/test_plot.py +++ b/xarray/tests/test_plot.py @@ -1844,27 +1844,6 @@ def test_plot_seaborn_no_import_warning(): assert len(record) == 0 -# @requires_cftime -# def test_plot_cftime_coordinate_error(): -# cftime = _import_cftime() -# time = cftime.num2date(np.arange(5), units='days since 0001-01-01', -# calendar='noleap') -# data = DataArray(np.arange(5), coords=[time], dims=['time']) -# with raises_regex(TypeError, -# 'requires coordinates to be numeric or dates'): -# data.plot() - - -# @requires_cftime -# def test_plot_cftime_data_error(): -# cftime = _import_cftime() -# data = cftime.num2date(np.arange(5), units='days since 0001-01-01', -# calendar='noleap') -# data = DataArray(data, coords=[np.arange(5)], dims=['x']) -# with raises_regex(NotImplementedError, 'cftime.datetime'): -# data.plot() - - test_da_list = [DataArray(easy_array((10, ))), DataArray(easy_array((10, 3))), DataArray(easy_array((10, 3, 2)))] From 0479829e740789f3122d69d511bcaed18b9ad3a7 Mon Sep 17 00:00:00 2001 From: jbusecke Date: Tue, 5 Feb 2019 12:33:06 -0500 Subject: [PATCH 04/17] added tests --- ci/requirements-py37-windows.yml | 1 + ci/requirements-py37.yml | 1 + xarray/plot/plot.py | 22 +--------------------- xarray/tests/__init__.py | 1 + xarray/tests/test_plot.py | 29 ++++++++++++++++++++++++++++- 5 files changed, 32 insertions(+), 22 deletions(-) diff --git a/ci/requirements-py37-windows.yml b/ci/requirements-py37-windows.yml index 24a7f556b2c..fb4b97cde7c 100644 --- a/ci/requirements-py37-windows.yml +++ b/ci/requirements-py37-windows.yml @@ -4,6 +4,7 @@ channels: dependencies: - python=3.7 - cftime + - nc-time-axis - dask - distributed - h5py diff --git a/ci/requirements-py37.yml b/ci/requirements-py37.yml index 1a98e6b285c..4f4d2b1728b 100644 --- a/ci/requirements-py37.yml +++ b/ci/requirements-py37.yml @@ -4,6 +4,7 @@ channels: dependencies: - python=3.7 - cftime + - nc-time-axis - dask - distributed - h5py diff --git a/xarray/plot/plot.py b/xarray/plot/plot.py index f05a3edd823..d0f4e57afff 100644 --- a/xarray/plot/plot.py +++ b/xarray/plot/plot.py @@ -10,7 +10,7 @@ import numpy as np import pandas as pd -from .facetgrid import FacetGrid +from .facetgrid import _easy_facetgrid from .utils import ( _add_colorbar, _ensure_plottable, _infer_interval_breaks, _infer_xy_labels, _interval_to_double_bound_points, _interval_to_mid_points, @@ -102,26 +102,6 @@ def _infer_line_data(darray, x, y, hue): return xplt, yplt, hueplt, xlabel, ylabel, huelabel -# def _convert_cftime_data(values): -# converted = [CalendarDateTime(v, v.calendar) for v in values] -# return converted - - -# def _convert_all_cftime(da): -# try: -# from cftime import datetime as cftime_datetime -# except ImportError: -# raise ImportError('cftime package missing') -# da = da.copy() -# # find the dim that has a cftime datatype -# dims = set(da.dims) -# cftime_dims = [d for d in dims if isinstance(da[d].data.ravel()[0], -# cftime_datetime)] -# for cd in cftime_dims: -# da[cd].data = _convert_cftime_data(da[cd].data) -# return da - - def plot(darray, row=None, col=None, col_wrap=None, ax=None, hue=None, rtol=0.01, subplot_kws=None, **kwargs): """ diff --git a/xarray/tests/__init__.py b/xarray/tests/__init__.py index a7eafa92bd7..9d571ff07f9 100644 --- a/xarray/tests/__init__.py +++ b/xarray/tests/__init__.py @@ -63,6 +63,7 @@ def LooseVersion(vstring): has_pynio, requires_pynio = _importorskip('Nio') has_pseudonetcdf, requires_pseudonetcdf = _importorskip('PseudoNetCDF') has_cftime, requires_cftime = _importorskip('cftime') +has_nc_time_axis, requires_nc_time_axis = _importorskip('nc_time_axis') has_cftime_1_0_2_1, requires_cftime_1_0_2_1 = _importorskip( 'cftime', minversion='1.0.2.1') has_dask, requires_dask = _importorskip('dask') diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py index 96f88b7bfb3..fcacf5ec1c5 100644 --- a/xarray/tests/test_plot.py +++ b/xarray/tests/test_plot.py @@ -17,7 +17,9 @@ from . import ( assert_array_equal, assert_equal, raises_regex, requires_cftime, - requires_matplotlib, requires_matplotlib2, requires_seaborn) + requires_matplotlib, requires_matplotlib2, requires_seaborn, + requires_nc_time_axis, + ) # import mpl and change the backend before other mpl imports try: @@ -1828,6 +1830,31 @@ def test_datetime_line_plot(self): self.darray.plot.line() +@requires_nc_time_axis +@requires_cftime +class TestCFDatetimePlot(PlotTestCase): + @pytest.fixture(autouse=True) + def setUp(self): + ''' + Create a DataArray with a time-axis that contains cftime.datetime64 + objects. + ''' + month = np.arange(1, 13, 1) + data = np.sin(2 * np.pi * month / 12.0) + + darray = DataArray(data, dims=['time']) + darray.coords['time'] = xr.cftime_range(start='2017', + periods=12, + freq='1M', + calendar='noleap') + + self.darray = darray + + def test_cfdatetime_line_plot(self): + # test if line plot raises no Exception + self.darray.plot.line() + + @requires_seaborn def test_import_seaborn_no_warning(): # GH1633 From 970a6a5c2354b8e441ff0098e0974071249d219d Mon Sep 17 00:00:00 2001 From: jbusecke Date: Tue, 5 Feb 2019 14:45:15 -0500 Subject: [PATCH 05/17] more tests, docs, bugfix --- doc/whats-new.rst | 6 ++++- xarray/plot/utils.py | 4 ++-- xarray/tests/test_plot.py | 47 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 142ef3a2e51..7c26e96cb18 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -24,7 +24,7 @@ Breaking changes - Remove support for Python 2. This is the first version of xarray that is Python 3 only. (:issue:`1876`). By `Joe Hamman `_. -- The `compat` argument to `Dataset` and the `encoding` argument to +- The `compat` argument to `Dataset` and the `encoding` argument to `DataArray` are deprecated and will be removed in a future release. (:issue:`1188`) By `Maximilian Roos `_. @@ -32,6 +32,10 @@ Breaking changes Enhancements ~~~~~~~~~~~~ +- Internal plotting now supports `cftime.datetime` objects as time series. + (:issue:``2164``) + By `Spencer Clark ` and + `Julius Busecke `_. - Add ``data=False`` option to ``to_dict()`` methods. (:issue:`2656`) By `Ryan Abernathey `_ - :py:meth:`~xarray.DataArray.coarsen` and diff --git a/xarray/plot/utils.py b/xarray/plot/utils.py index 8fa21f9da6e..41934bbec50 100644 --- a/xarray/plot/utils.py +++ b/xarray/plot/utils.py @@ -476,13 +476,13 @@ def _ensure_plottable(*args): cftime_datetime = [cftime.datetime] except ImportError: cftime_datetime = [] - other_types = other_types + cftime_datetime + other_types = other_types + cftime_datetime for x in args: if not (_valid_numpy_subdtype(np.array(x), numpy_types) or _valid_other_type(np.array(x), other_types)): raise TypeError('Plotting requires coordinates to be numeric ' 'or dates of type np.datetime64, ' - 'datetime.datetime, or cftime.datetime or ' + 'datetime.datetime, cftime.datetime or ' 'pd.Interval.') if (_valid_other_type(np.array(x), cftime_datetime) and not nc_time_axis_available): diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py index fcacf5ec1c5..0e4e039d24b 100644 --- a/xarray/tests/test_plot.py +++ b/xarray/tests/test_plot.py @@ -1839,7 +1839,6 @@ def setUp(self): Create a DataArray with a time-axis that contains cftime.datetime64 objects. ''' - month = np.arange(1, 13, 1) data = np.sin(2 * np.pi * month / 12.0) darray = DataArray(data, dims=['time']) @@ -1854,6 +1853,52 @@ def test_cfdatetime_line_plot(self): # test if line plot raises no Exception self.darray.plot.line() + @requires_nc_time_axis + @requires_cftime + class TestCFDatetimePcolormesh(PlotTestCase): + @pytest.fixture(autouse=True) + def setUp(self): + ''' + Create a DataArray with a time-axis that contains cftime.datetime64 + objects. + ''' + data = np.rand.random(4, 12) + + darray = DataArray(data, dims=['x', 'time']) + darray.coords['time'] = xr.cftime_range(start='2017', + periods=12, + freq='1M', + calendar='noleap') + + self.darray = darray + + def test_cfdatetime_line_plot(self): + # test if line plot raises no Exception + self.darray.plot.pcolormesh() + + @requires_nc_time_axis + @requires_cftime + class TestCFDatetimeContour(PlotTestCase): + @pytest.fixture(autouse=True) + def setUp(self): + ''' + Create a DataArray with a time-axis that contains cftime.datetime64 + objects. + ''' + data = np.rand.random(4, 12) + + darray = DataArray(data, dims=['x', 'time']) + darray.coords['time'] = xr.cftime_range(start='2017', + periods=12, + freq='1M', + calendar='noleap') + + self.darray = darray + + def test_cfdatetime_line_plot(self): + # test if line plot raises no Exception + self.darray.plot.contour() + @requires_seaborn def test_import_seaborn_no_warning(): From 849512f1d9677d72d2f8fcb84036ebaebba15e4a Mon Sep 17 00:00:00 2001 From: jbusecke Date: Tue, 5 Feb 2019 16:03:07 -0500 Subject: [PATCH 06/17] additional test for exceptions, print versions --- doc/plotting.rst | 9 ++- xarray/core/common.py | 3 +- xarray/plot/plot.py | 6 -- xarray/plot/utils.py | 15 +++- xarray/tests/__init__.py | 3 +- xarray/tests/test_plot.py | 125 +++++++++++++++++++++------------- xarray/util/print_versions.py | 1 + 7 files changed, 102 insertions(+), 60 deletions(-) diff --git a/doc/plotting.rst b/doc/plotting.rst index 1cb7aebe96d..6fdeb3edb0b 100644 --- a/doc/plotting.rst +++ b/doc/plotting.rst @@ -23,6 +23,11 @@ Matplotlib syntax and function names were copied as much as possible, which makes for an easy transition between the two. Matplotlib must be installed before xarray can plot. +To use xarray's plotting capabilities with time coordinates containing +`cftime.datetime` objects +`nc-time-axis ` v1.2.0 or later +needs to be installed. + For more extensive plotting applications consider the following projects: - `Seaborn `_: "provides @@ -226,7 +231,7 @@ Step plots ~~~~~~~~~~ As an alternative, also a step plot similar to matplotlib's ``plt.step`` can be -made using 1D data. +made using 1D data. .. ipython:: python @@ -248,7 +253,7 @@ when plotting data grouped with :py:func:`xarray.Dataset.groupby_bins`. plt.ylim(-20,30) @savefig plotting_example_step_groupby.png width=4in plt.title('Zonal mean temperature') - + In this case, the actual boundaries of the bins are used and the ``where`` argument is ignored. diff --git a/xarray/core/common.py b/xarray/core/common.py index 439d254bec0..2f32ca941be 100644 --- a/xarray/core/common.py +++ b/xarray/core/common.py @@ -713,7 +713,7 @@ def resample(self, indexer=None, skipna=None, closed=None, label=None, array([ 0. , 0.032258, 0.064516, ..., 10.935484, 10.967742, 11. ]) Coordinates: * time (time) datetime64[ns] 1999-12-15 1999-12-16 1999-12-17 ... - + Limit scope of upsampling method >>> da.resample(time='1D').nearest(tolerance='1D') @@ -1002,7 +1002,6 @@ def contains_cftime_datetimes(var): try: from cftime import datetime as cftime_datetime except ImportError: - print('Could not import cftime') return False else: if var.dtype == np.dtype('O') and var.data.size > 0: diff --git a/xarray/plot/plot.py b/xarray/plot/plot.py index d0f4e57afff..8e2457603d6 100644 --- a/xarray/plot/plot.py +++ b/xarray/plot/plot.py @@ -18,12 +18,6 @@ _update_axes, _valid_other_type, get_axis, import_matplotlib_pyplot, label_from_attrs) -try: - import nc_time_axis - nc_time_axis_available = True -except ImportError: - nc_time_axis_available = False - def _infer_line_data(darray, x, y, hue): error_msg = ('must be either None or one of ({0:s})' diff --git a/xarray/plot/utils.py b/xarray/plot/utils.py index 41934bbec50..21523ede4cd 100644 --- a/xarray/plot/utils.py +++ b/xarray/plot/utils.py @@ -10,6 +10,16 @@ from ..core.options import OPTIONS from ..core.utils import is_scalar +from distutils.version import LooseVersion + +try: + import nc_time_axis + if LooseVersion(nc_time_axis.__version__) < LooseVersion('1.2.0'): + nc_time_axis_available = False + else: + nc_time_axis_available = True +except ImportError: + nc_time_axis_available = False ROBUST_PERCENTILE = 2.0 @@ -489,10 +499,11 @@ def _ensure_plottable(*args): raise ImportError('Plotting of arrays of cftime.datetime ' 'objects or arrays indexed by ' 'cftime.datetime objects requires the ' - 'optional `nc-time-axis` package.') + 'optional `nc-time-axis` (v1.2.0 or later) ' + 'package.') -def _ensure_numeric(arr): +def _numeric(arr): numpy_types = [np.floating, np.integer] return _valid_numpy_subdtype(arr, numpy_types) diff --git a/xarray/tests/__init__.py b/xarray/tests/__init__.py index 9d571ff07f9..281fc662197 100644 --- a/xarray/tests/__init__.py +++ b/xarray/tests/__init__.py @@ -63,7 +63,8 @@ def LooseVersion(vstring): has_pynio, requires_pynio = _importorskip('Nio') has_pseudonetcdf, requires_pseudonetcdf = _importorskip('PseudoNetCDF') has_cftime, requires_cftime = _importorskip('cftime') -has_nc_time_axis, requires_nc_time_axis = _importorskip('nc_time_axis') +has_nc_time_axis, requires_nc_time_axis = _importorskip('nc_time_axis', + minversion='1.2.0') has_cftime_1_0_2_1, requires_cftime_1_0_2_1 = _importorskip( 'cftime', minversion='1.0.2.1') has_dask, requires_dask = _importorskip('dask') diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py index 0e4e039d24b..eefc9f02014 100644 --- a/xarray/tests/test_plot.py +++ b/xarray/tests/test_plot.py @@ -20,6 +20,7 @@ requires_matplotlib, requires_matplotlib2, requires_seaborn, requires_nc_time_axis, ) +from . import has_nc_time_axis # import mpl and change the backend before other mpl imports try: @@ -1836,11 +1837,11 @@ class TestCFDatetimePlot(PlotTestCase): @pytest.fixture(autouse=True) def setUp(self): ''' - Create a DataArray with a time-axis that contains cftime.datetime64 + Create a DataArray with a time-axis that contains cftime.datetime objects. ''' + month = np.arange(1, 13, 1) data = np.sin(2 * np.pi * month / 12.0) - darray = DataArray(data, dims=['time']) darray.coords['time'] = xr.cftime_range(start='2017', periods=12, @@ -1853,51 +1854,81 @@ def test_cfdatetime_line_plot(self): # test if line plot raises no Exception self.darray.plot.line() - @requires_nc_time_axis - @requires_cftime - class TestCFDatetimePcolormesh(PlotTestCase): - @pytest.fixture(autouse=True) - def setUp(self): - ''' - Create a DataArray with a time-axis that contains cftime.datetime64 - objects. - ''' - data = np.rand.random(4, 12) - - darray = DataArray(data, dims=['x', 'time']) - darray.coords['time'] = xr.cftime_range(start='2017', - periods=12, - freq='1M', - calendar='noleap') - - self.darray = darray - - def test_cfdatetime_line_plot(self): - # test if line plot raises no Exception - self.darray.plot.pcolormesh() - - @requires_nc_time_axis - @requires_cftime - class TestCFDatetimeContour(PlotTestCase): - @pytest.fixture(autouse=True) - def setUp(self): - ''' - Create a DataArray with a time-axis that contains cftime.datetime64 - objects. - ''' - data = np.rand.random(4, 12) - - darray = DataArray(data, dims=['x', 'time']) - darray.coords['time'] = xr.cftime_range(start='2017', - periods=12, - freq='1M', - calendar='noleap') - - self.darray = darray - - def test_cfdatetime_line_plot(self): - # test if line plot raises no Exception - self.darray.plot.contour() + +@requires_nc_time_axis +@requires_cftime +class TestCFDatetimePcolormesh(PlotTestCase): + @pytest.fixture(autouse=True) + def setUp(self): + ''' + Create a DataArray with a time-axis that contains cftime.datetime + objects. + ''' + month = np.arange(1, 13, 1) + data = np.rand.random(4, 12) + + darray = DataArray(data, dims=['x', 'time']) + darray.coords['time'] = xr.cftime_range(start='2017', + periods=12, + freq='1M', + calendar='noleap') + + self.darray = darray + + def test_cfdatetime_line_plot(self): + # test if line plot raises no Exception + self.darray.plot.pcolormesh() + + +@requires_nc_time_axis +@requires_cftime +class TestCFDateContour(PlotTestCase): + @pytest.fixture(autouse=True) + def setUp(self): + ''' + Create a DataArray with a time-axis that contains cftime.datetime + objects. + ''' + month = np.arange(1, 13, 1) + data = np.rand.random(4, 12) + + darray = DataArray(data, dims=['x', 'time']) + darray.coords['time'] = xr.cftime_range(start='2017', + periods=12, + freq='1M', + calendar='noleap') + + self.darray = darray + + def test_cfdatetime_line_plot(self): + # test if line plot raises no Exception + self.darray.plot.contour() + + +@requires_cftime +@pytest.mark.skipif(has_nc_time_axis, reason='nc_time_axis is installed') +class TestNcAxisNotInstalled(PlotTestCase): + @pytest.fixture(autouse=True) + def setUp(self): + ''' + Create a DataArray with a time-axis that contains cftime.datetime + objects. + ''' + month = np.arange(1, 13, 1) + data = np.sin(2 * np.pi * month / 12.0) + darray = DataArray(data, dims=['time']) + darray.coords['time'] = xr.cftime_range(start='2017', + periods=12, + freq='1M', + calendar='noleap') + + self.darray = darray + + def test_ncaxis_notinstalled_line_plot(self): + # test if line plot raises no Exception + with raises_regex(ImportError, + 'optional `nc-time-axis`'): + self.darray.plot.line() @requires_seaborn diff --git a/xarray/util/print_versions.py b/xarray/util/print_versions.py index 87eb7399e69..cfe566f42d2 100755 --- a/xarray/util/print_versions.py +++ b/xarray/util/print_versions.py @@ -97,6 +97,7 @@ def show_versions(as_json=False): ("Nio", lambda mod: mod.__version__), ("zarr", lambda mod: mod.__version__), ("cftime", lambda mod: mod.__version__), + ("nc_time_axis", lambda mod: mod.__version__), ("PseudonetCDF", lambda mod: mod.__version__), ("rasterio", lambda mod: mod.__version__), ("cfgrib", lambda mod: mod.__version__), From afe365c8514d217091c957b47e07aea0ee304599 Mon Sep 17 00:00:00 2001 From: jbusecke Date: Tue, 5 Feb 2019 16:56:41 -0500 Subject: [PATCH 07/17] bugfix for 2d plot test with cftime --- xarray/tests/test_plot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py index eefc9f02014..60049c52b34 100644 --- a/xarray/tests/test_plot.py +++ b/xarray/tests/test_plot.py @@ -1865,7 +1865,7 @@ def setUp(self): objects. ''' month = np.arange(1, 13, 1) - data = np.rand.random(4, 12) + data = np.random.rand(4, 12) darray = DataArray(data, dims=['x', 'time']) darray.coords['time'] = xr.cftime_range(start='2017', @@ -1890,7 +1890,7 @@ def setUp(self): objects. ''' month = np.arange(1, 13, 1) - data = np.rand.random(4, 12) + data = np.random.rand(4, 12) darray = DataArray(data, dims=['x', 'time']) darray.coords['time'] = xr.cftime_range(start='2017', From 69fe8229679dd84a4916da9643adea3c8cff04e3 Mon Sep 17 00:00:00 2001 From: jbusecke Date: Tue, 5 Feb 2019 17:20:59 -0500 Subject: [PATCH 08/17] linter errors --- xarray/tests/test_plot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py index 60049c52b34..1bac4740e09 100644 --- a/xarray/tests/test_plot.py +++ b/xarray/tests/test_plot.py @@ -18,8 +18,8 @@ from . import ( assert_array_equal, assert_equal, raises_regex, requires_cftime, requires_matplotlib, requires_matplotlib2, requires_seaborn, - requires_nc_time_axis, - ) + requires_nc_time_axis + ) from . import has_nc_time_axis # import mpl and change the backend before other mpl imports From 52867d7401e2753b5908e2dd22a957765d39aaf1 Mon Sep 17 00:00:00 2001 From: jbusecke Date: Tue, 5 Feb 2019 17:56:13 -0500 Subject: [PATCH 09/17] the linter again --- xarray/tests/test_plot.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py index 1bac4740e09..47f439977c4 100644 --- a/xarray/tests/test_plot.py +++ b/xarray/tests/test_plot.py @@ -18,8 +18,7 @@ from . import ( assert_array_equal, assert_equal, raises_regex, requires_cftime, requires_matplotlib, requires_matplotlib2, requires_seaborn, - requires_nc_time_axis - ) + requires_nc_time_axis) from . import has_nc_time_axis # import mpl and change the backend before other mpl imports From 4bb34462f9f94973df488d6a364b47ece63a1d23 Mon Sep 17 00:00:00 2001 From: Spencer Clark Date: Tue, 5 Feb 2019 23:16:05 -0500 Subject: [PATCH 10/17] Update doc/plotting.rst Co-Authored-By: jbusecke --- doc/plotting.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/plotting.rst b/doc/plotting.rst index 6fdeb3edb0b..66ae3752392 100644 --- a/doc/plotting.rst +++ b/doc/plotting.rst @@ -24,7 +24,7 @@ makes for an easy transition between the two. Matplotlib must be installed before xarray can plot. To use xarray's plotting capabilities with time coordinates containing -`cftime.datetime` objects +``cftime.datetime`` objects `nc-time-axis ` v1.2.0 or later needs to be installed. From 3c98d2706860450af369ab4c33eaa99ba94ea6d3 Mon Sep 17 00:00:00 2001 From: Spencer Clark Date: Tue, 5 Feb 2019 23:16:36 -0500 Subject: [PATCH 11/17] Update doc/whats-new.rst Co-Authored-By: jbusecke --- doc/whats-new.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 7c26e96cb18..5d93e8e7f10 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -33,7 +33,7 @@ Enhancements ~~~~~~~~~~~~ - Internal plotting now supports `cftime.datetime` objects as time series. - (:issue:``2164``) + (:issue:`2164`) By `Spencer Clark ` and `Julius Busecke `_. - Add ``data=False`` option to ``to_dict()`` methods. (:issue:`2656`) From 15a6c86bd0aa884624281e0d90ddb6c8f983c855 Mon Sep 17 00:00:00 2001 From: Spencer Clark Date: Tue, 5 Feb 2019 23:16:51 -0500 Subject: [PATCH 12/17] Update doc/whats-new.rst Co-Authored-By: jbusecke --- doc/whats-new.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 5d93e8e7f10..22573dd5fbe 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -32,7 +32,7 @@ Breaking changes Enhancements ~~~~~~~~~~~~ -- Internal plotting now supports `cftime.datetime` objects as time series. +- Internal plotting now supports ``cftime.datetime`` objects as time series. (:issue:`2164`) By `Spencer Clark ` and `Julius Busecke `_. From 6668f8e55de0d7a8bb03ce10e168345cb9ec45de Mon Sep 17 00:00:00 2001 From: jbusecke Date: Tue, 5 Feb 2019 23:41:06 -0500 Subject: [PATCH 13/17] final touches --- doc/time-series.rst | 31 +++++-------- doc/whats-new.rst | 4 +- xarray/tests/test_plot.py | 96 +++++++++++++++++++-------------------- 3 files changed, 60 insertions(+), 71 deletions(-) diff --git a/doc/time-series.rst b/doc/time-series.rst index b716d6cbc24..3249dad2ec6 100644 --- a/doc/time-series.rst +++ b/doc/time-series.rst @@ -74,7 +74,7 @@ will be used for indexing. :py:class:`~xarray.CFTimeIndex` enables a subset of the indexing functionality of a :py:class:`pandas.DatetimeIndex` and is only fully compatible with the standalone version of ``cftime`` (not the version packaged with earlier versions ``netCDF4``). See :ref:`CFTimeIndex` for more -information. +information. Datetime indexing ----------------- @@ -215,7 +215,7 @@ For more examples of using grouped operations on a time dimension, see .. _CFTimeIndex: - + Non-standard calendars and dates outside the Timestamp-valid range ------------------------------------------------------------------ @@ -224,14 +224,14 @@ Through the standalone ``cftime`` library and a custom subclass of functionality enabled through the standard :py:class:`pandas.DatetimeIndex` for dates from non-standard calendars commonly used in climate science or dates using a standard calendar, but outside the `Timestamp-valid range`_ -(approximately between years 1678 and 2262). +(approximately between years 1678 and 2262). .. note:: As of xarray version 0.11, by default, :py:class:`cftime.datetime` objects will be used to represent times (either in indexes, as a - :py:class:`~xarray.CFTimeIndex`, or in data arrays with dtype object) if - any of the following are true: + :py:class:`~xarray.CFTimeIndex`, or in data arrays with dtype object) if + any of the following are true: - The dates are from a non-standard calendar - Any dates are outside the Timestamp-valid range. @@ -252,7 +252,7 @@ coordinate with dates from a no-leap calendar and a dates = [DatetimeNoLeap(year, month, 1) for year, month in product(range(1, 3), range(1, 13))] da = xr.DataArray(np.arange(24), coords=[dates], dims=['time'], name='foo') - + xarray also includes a :py:func:`~xarray.cftime_range` function, which enables creating a :py:class:`~xarray.CFTimeIndex` with regularly-spaced dates. For instance, we can create the same dates and DataArray we created above using: @@ -261,12 +261,12 @@ instance, we can create the same dates and DataArray we created above using: dates = xr.cftime_range(start='0001', periods=24, freq='MS', calendar='noleap') da = xr.DataArray(np.arange(24), coords=[dates], dims=['time'], name='foo') - + For data indexed by a :py:class:`~xarray.CFTimeIndex` xarray currently supports: - `Partial datetime string indexing`_ using strictly `ISO 8601-format`_ partial datetime strings: - + .. ipython:: python da.sel(time='0001') @@ -274,7 +274,7 @@ For data indexed by a :py:class:`~xarray.CFTimeIndex` xarray currently supports: - Access of basic datetime components via the ``dt`` accessor (in this case just "year", "month", "day", "hour", "minute", "second", "microsecond", - "season", "dayofyear", and "dayofweek"): + "season", "dayofyear", and "dayofweek"): .. ipython:: python @@ -323,14 +323,7 @@ For data indexed by a :py:class:`~xarray.CFTimeIndex` xarray currently supports: da.resample(time='81T', closed='right', label='right', base=3).mean() .. note:: - - While much of the time series functionality that is possible for standard - dates has been implemented for dates from non-standard calendars, there are - still some remaining important features that have yet to be implemented, - for example: - - - Built-in plotting of data with :py:class:`cftime.datetime` coordinate axes - (:issue:`2164`). + For some use-cases it may still be useful to convert from a :py:class:`~xarray.CFTimeIndex` to a :py:class:`pandas.DatetimeIndex`, @@ -351,8 +344,8 @@ For data indexed by a :py:class:`~xarray.CFTimeIndex` xarray currently supports: do not depend on differences between dates (e.g. differentiation, interpolation, or upsampling with resample), as these could introduce subtle and silent errors due to the difference in calendar types between the dates - encoded in your data and the dates stored in memory. - + encoded in your data and the dates stored in memory. + .. _Timestamp-valid range: https://pandas.pydata.org/pandas-docs/stable/timeseries.html#timestamp-limitations .. _ISO 8601-format: https://en.wikipedia.org/wiki/ISO_8601 .. _partial datetime string indexing: https://pandas.pydata.org/pandas-docs/stable/timeseries.html#partial-string-indexing diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 22573dd5fbe..218e99de17e 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -34,8 +34,8 @@ Enhancements - Internal plotting now supports ``cftime.datetime`` objects as time series. (:issue:`2164`) - By `Spencer Clark ` and - `Julius Busecke `_. + By `Julius Busecke ` and + `Spencer Clark `_. - Add ``data=False`` option to ``to_dict()`` methods. (:issue:`2656`) By `Ryan Abernathey `_ - :py:meth:`~xarray.DataArray.coarsen` and diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py index 47f439977c4..82791c86f66 100644 --- a/xarray/tests/test_plot.py +++ b/xarray/tests/test_plot.py @@ -1839,69 +1839,65 @@ def setUp(self): Create a DataArray with a time-axis that contains cftime.datetime objects. ''' + # case for 1d array month = np.arange(1, 13, 1) data = np.sin(2 * np.pi * month / 12.0) + time = xr.cftime_range(start='2017', + periods=12, + freq='1M', + calendar='noleap') darray = DataArray(data, dims=['time']) - darray.coords['time'] = xr.cftime_range(start='2017', - periods=12, - freq='1M', - calendar='noleap') + darray.coords['time'] = time self.darray = darray - def test_cfdatetime_line_plot(self): - # test if line plot raises no Exception - self.darray.plot.line() - - -@requires_nc_time_axis -@requires_cftime -class TestCFDatetimePcolormesh(PlotTestCase): - @pytest.fixture(autouse=True) - def setUp(self): - ''' - Create a DataArray with a time-axis that contains cftime.datetime - objects. - ''' - month = np.arange(1, 13, 1) - data = np.random.rand(4, 12) - - darray = DataArray(data, dims=['x', 'time']) - darray.coords['time'] = xr.cftime_range(start='2017', - periods=12, - freq='1M', - calendar='noleap') + # case for 2d arrays + data_2d = np.random.rand(4, 12) + darray_2d = DataArray(data_2d, dims=['x', 'time']) + darray_2d.coords['time'] = time - self.darray = darray + self.darray_2d = darray_2d def test_cfdatetime_line_plot(self): # test if line plot raises no Exception - self.darray.plot.pcolormesh() - - -@requires_nc_time_axis -@requires_cftime -class TestCFDateContour(PlotTestCase): - @pytest.fixture(autouse=True) - def setUp(self): - ''' - Create a DataArray with a time-axis that contains cftime.datetime - objects. - ''' - month = np.arange(1, 13, 1) - data = np.random.rand(4, 12) - - darray = DataArray(data, dims=['x', 'time']) - darray.coords['time'] = xr.cftime_range(start='2017', - periods=12, - freq='1M', - calendar='noleap') + self.darray.plot.line() - self.darray = darray + def test_cfdatetime_pcolormesh_plot(self): + # test if line plot raises no Exception + self.darray_2d.plot.pcolormesh() - def test_cfdatetime_line_plot(self): + def test_cfdatetime_contour_plot(self): # test if line plot raises no Exception - self.darray.plot.contour() + self.darray_2d.plot.contour() + + +# @requires_nc_time_axis +# @requires_cftime +# class TestCFDatetimePcolormesh(PlotTestCase): +# @pytest.fixture(autouse=True) +# def setUp(self): +# ''' +# Create a DataArray with a time-axis that contains cftime.datetime +# objects. +# ''' +# month = np.arange(1, 13, 1) +# data = np.random.rand(4, 12) +# +# darray = DataArray(data, dims=['x', 'time']) +# darray.coords['time'] = xr.cftime_range(start='2017', +# periods=12, +# freq='1M', +# calendar='noleap') +# +# self.darray = darray +# +# def test_cfdatetime_pcolormesh_plot(self): +# # test if line plot raises no Exception +# self.darray.plot.pcolormesh() +# +# def test_cfdatetime_contour_plot(self): +# # test if line plot raises no Exception +# self.darray.plot.contour() @requires_cftime From daa5508cc48b47837918d656da6fd05f7e6f8661 Mon Sep 17 00:00:00 2001 From: Spencer Clark Date: Wed, 6 Feb 2019 10:26:38 -0500 Subject: [PATCH 14/17] Update doc/whats-new.rst Co-Authored-By: jbusecke --- doc/whats-new.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 218e99de17e..a296583f3ac 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -34,7 +34,7 @@ Enhancements - Internal plotting now supports ``cftime.datetime`` objects as time series. (:issue:`2164`) - By `Julius Busecke ` and + By `Julius Busecke `_ and `Spencer Clark `_. - Add ``data=False`` option to ``to_dict()`` methods. (:issue:`2656`) By `Ryan Abernathey `_ From 9d199461b839e03d9ebd071687c068672b12139b Mon Sep 17 00:00:00 2001 From: Spencer Clark Date: Wed, 6 Feb 2019 10:27:09 -0500 Subject: [PATCH 15/17] Update doc/plotting.rst Co-Authored-By: jbusecke --- doc/plotting.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/plotting.rst b/doc/plotting.rst index 66ae3752392..a705c683594 100644 --- a/doc/plotting.rst +++ b/doc/plotting.rst @@ -25,7 +25,7 @@ Matplotlib must be installed before xarray can plot. To use xarray's plotting capabilities with time coordinates containing ``cftime.datetime`` objects -`nc-time-axis ` v1.2.0 or later +`nc-time-axis `_ v1.2.0 or later needs to be installed. For more extensive plotting applications consider the following projects: From 985d3678a2ecddce2ab81602a5f28b15bda1c585 Mon Sep 17 00:00:00 2001 From: jbusecke Date: Wed, 6 Feb 2019 10:32:53 -0500 Subject: [PATCH 16/17] test shortened, removed unnecessary comments --- xarray/tests/test_plot.py | 51 ++++----------------------------------- 1 file changed, 5 insertions(+), 46 deletions(-) diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py index 82791c86f66..c0e03b5791c 100644 --- a/xarray/tests/test_plot.py +++ b/xarray/tests/test_plot.py @@ -1840,64 +1840,24 @@ def setUp(self): objects. ''' # case for 1d array - month = np.arange(1, 13, 1) - data = np.sin(2 * np.pi * month / 12.0) + data = np.random.rand(4, 12) time = xr.cftime_range(start='2017', periods=12, freq='1M', calendar='noleap') - darray = DataArray(data, dims=['time']) + darray = DataArray(data, dims=['x', 'time']) darray.coords['time'] = time self.darray = darray - # case for 2d arrays - data_2d = np.random.rand(4, 12) - darray_2d = DataArray(data_2d, dims=['x', 'time']) - darray_2d.coords['time'] = time - - self.darray_2d = darray_2d - def test_cfdatetime_line_plot(self): - # test if line plot raises no Exception - self.darray.plot.line() + self.darray.isel(x=0).plot.line() def test_cfdatetime_pcolormesh_plot(self): - # test if line plot raises no Exception - self.darray_2d.plot.pcolormesh() + self.darray.plot.pcolormesh() def test_cfdatetime_contour_plot(self): - # test if line plot raises no Exception - self.darray_2d.plot.contour() - - -# @requires_nc_time_axis -# @requires_cftime -# class TestCFDatetimePcolormesh(PlotTestCase): -# @pytest.fixture(autouse=True) -# def setUp(self): -# ''' -# Create a DataArray with a time-axis that contains cftime.datetime -# objects. -# ''' -# month = np.arange(1, 13, 1) -# data = np.random.rand(4, 12) -# -# darray = DataArray(data, dims=['x', 'time']) -# darray.coords['time'] = xr.cftime_range(start='2017', -# periods=12, -# freq='1M', -# calendar='noleap') -# -# self.darray = darray -# -# def test_cfdatetime_pcolormesh_plot(self): -# # test if line plot raises no Exception -# self.darray.plot.pcolormesh() -# -# def test_cfdatetime_contour_plot(self): -# # test if line plot raises no Exception -# self.darray.plot.contour() + self.darray.plot.contour() @requires_cftime @@ -1920,7 +1880,6 @@ def setUp(self): self.darray = darray def test_ncaxis_notinstalled_line_plot(self): - # test if line plot raises no Exception with raises_regex(ImportError, 'optional `nc-time-axis`'): self.darray.plot.line() From 325b00a024dc6edfd93907bee1921ba39ffebc65 Mon Sep 17 00:00:00 2001 From: jbusecke Date: Thu, 7 Feb 2019 08:16:36 -0500 Subject: [PATCH 17/17] Added nc-time-axis mention in plotting dependencies --- doc/installing.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/installing.rst b/doc/installing.rst index 083ac6c450a..84895ff748a 100644 --- a/doc/installing.rst +++ b/doc/installing.rst @@ -63,6 +63,8 @@ For plotting :ref:`plot-maps` - `seaborn `__: for better color palettes +- `nc-time-axis `__: for plotting + cftime.datetime objects (1.2.0 or later) Instructions @@ -111,4 +113,4 @@ To run these benchmark tests in a local machine, first install - `airspeed-velocity `__: a tool for benchmarking Python packages over their lifetime. and run -``asv run # this will install some conda environments in ./.asv/envs`` \ No newline at end of file +``asv run # this will install some conda environments in ./.asv/envs``