Skip to content

Support rendering of cftime time axes #103

Closed

Description

@bradyrx

proplot doesn't seem to know how to handle cftime too well, which is increasingly more common in xarray now and can handle various climate model calendars, making it pretty useful.

It looks like the auto-generated datetime axis fails and tries to fill in every single time step:

import numpy as np
import proplot as plot
import xarray as xr

datetime = np.arange('1990-01', '2000-01', dtype='datetime64[M]')
cftime = xr.cftime_range('1990-01', '2000-01', freq='M')
da_datetime = xr.DataArray(np.random.rand(len(datetime)), dims='time', coords=[datetime])
da_cftime = xr.DataArray(np.random.rand(len(cftime)), dims='time', coords=[cftime])

f, ax = plot.subplots()
%time ax.plot(da_datetime.time, da_datetime)

f, ax = plot.subplots()
%time ax.plot(da_cftime.time, da_cftime)

Timing comes out essentially equivalent but the latter hangs for 10-15 seconds, probably trying to render the image in the notebook.

Screen Shot 2020-01-08 at 1 36 15 PM

Screen Shot 2020-01-08 at 1 36 19 PM

Activity

  1. lukelbd commented on Jan 9, 2020

    @lukelbd
    Collaborator

    Yikes. Thanks for the report, will try to get to this soon

  2. lukelbd commented on Feb 10, 2020

    @lukelbd
    Collaborator

    It looks like this is not supported natively by matplotlib. Do you get the same result?

    import matplotlib.pyplot as plt
    import numpy as np
    f, ax = plt.subplots()
    ax.plot(cftime, np.random.rand(len(cftime)))

    ...results in:

    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-30-37897cbb2798> in <module>
    ----> 1 f, ax = plt.subplots(); ax.plot(cftime, np.random.rand(len(cftime)))
    
    ~/miniconda3/lib/python3.7/site-packages/matplotlib/axes/_axes.py in plot(self, scalex, scaley, data, *args, **kwargs)
       1666         lines = [*self._get_lines(*args, data=data, **kwargs)]
       1667         for line in lines:
    -> 1668             self.add_line(line)
       1669         self.autoscale_view(scalex=scalex, scaley=scaley)
       1670         return lines
    
    ~/miniconda3/lib/python3.7/site-packages/matplotlib/axes/_base.py in add_line(self, line)
       1900             line.set_clip_path(self.patch)
       1901
    -> 1902         self._update_line_limits(line)
       1903         if not line.get_label():
       1904             line.set_label('_line%d' % len(self.lines))
    
    ~/miniconda3/lib/python3.7/site-packages/matplotlib/axes/_base.py in _update_line_limits(self, line)
       1922         Figures out the data limit of the given line, updating self.dataLim.
       1923         """
    -> 1924         path = line.get_path()
       1925         if path.vertices.size == 0:
       1926             return
    
    ~/miniconda3/lib/python3.7/site-packages/matplotlib/lines.py in get_path(self)
       1025         """
       1026         if self._invalidy or self._invalidx:
    -> 1027             self.recache()
       1028         return self._path
       1029
    
    ~/miniconda3/lib/python3.7/site-packages/matplotlib/lines.py in recache(self, always)
        668         if always or self._invalidx:
        669             xconv = self.convert_xunits(self._xorig)
    --> 670             x = _to_unmasked_float_array(xconv).ravel()
        671         else:
        672             x = self._x
    
    ~/miniconda3/lib/python3.7/site-packages/matplotlib/cbook/__init__.py in _to_unmasked_float_array(x)
       1388         return np.ma.asarray(x, float).filled(np.nan)
       1389     else:
    -> 1390         return np.asarray(x, float)
       1391
       1392
    
    ~/miniconda3/lib/python3.7/site-packages/numpy/core/_asarray.py in asarray(a, dtype, order)
         83
         84     """
    ---> 85     return array(a, dtype, copy=False, order=order)
         86
         87
    
    ~/miniconda3/lib/python3.7/site-packages/pandas/core/indexes/base.py in __array__(self, dtype)
        660         The array interface, return my values.
        661         """
    --> 662         return np.asarray(self._data, dtype=dtype)
        663
        664     def __array_wrap__(self, result, context=None):
    
    ~/miniconda3/lib/python3.7/site-packages/numpy/core/_asarray.py in asarray(a, dtype, order)
         83
         84     """
    ---> 85     return array(a, dtype, copy=False, order=order)
         86
         87
    
    TypeError: float() argument must be a string or a number, not 'cftime._cftime.DatetimeGregorian'
  3. changed the title [-]Bad rendering of `cftime` time axes[/-] [+]Support rendering of `cftime` time axes[/+] on Feb 10, 2020
  4. bradyrx commented on Feb 10, 2020

    @bradyrx
    CollaboratorAuthor

    I don't have time to check on this right now, but I think that may be that you need to install nc-time-axis (https://github.com/SciTools/nc-time-axis). You usually need to install that to get cftime objects in xarray datasets to plot with their xarray.Dataset.plot() command.

  5. bradyrx commented on Feb 10, 2020

    @bradyrx
    CollaboratorAuthor

    Note that I have that installed in my environment and was still getting issues with proplot. So it didn't extend through to proplot.

  6. lukelbd commented on Feb 10, 2020

    @lukelbd
    Collaborator

    I discovered the problem; will close this soon.

  7. lukelbd commented on Feb 11, 2020

    @lukelbd
    Collaborator

    I decided to also release a new version (v0.5.0), which includes Fabio's colormaps and this fix. Feel free to update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions