Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not converting values when passed a list #47

Closed
aulemahal opened this issue Aug 18, 2020 · 3 comments · Fixed by #78
Closed

Not converting values when passed a list #47

aulemahal opened this issue Aug 18, 2020 · 3 comments · Fixed by #78
Assignees
Labels
Good First Issue A good issue to take on if you're just getting started with nc-time-axis development Type: Bug
Milestone

Comments

@aulemahal
Copy link
Contributor

It appears that some matplotlib method pass lists of coordinates to the converting methods. Such an example is plt.axhspan, that passes [xmin, xmax] to ax.convert_xunits and, thus, down to nc_time_axis.NetCDFTimeConverter.convert. However, the latter tests for np.ndarray but not for lists, so it raises a ValueError.

MWE:

import cftime
import matplotlib.pyplot as plt

x1 = cftime.DatetimeNoLeap(1990, 1, 1)
x2 = cftime.DatetimeNoLeap(1991, 1, 1)
x3 = cftime.DatetimeNoLeap(1992, 1, 1)

plt.plot([x1, x2, x3], [1, 2, 1])
plt.axvspan(x1, x2, color='red', alpha=0.5)

Expected:
image

Result:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~/.conda/envs/xclim-dev/lib/python3.8/site-packages/matplotlib/axis.py in convert_units(self, x)
   1519         try:
-> 1520             ret = self.converter.convert(x, self.units, self)
   1521         except Exception as e:

~/.conda/envs/xclim-dev/lib/python3.8/site-packages/nc_time_axis/__init__.py in convert(cls, value, unit, axis)
    277         if not isinstance(first_value, (CalendarDateTime, cftime.datetime)):
--> 278             raise ValueError('The values must be numbers or instances of '
    279                              '"nc_time_axis.CalendarDateTime" or '

ValueError: The values must be numbers or instances of "nc_time_axis.CalendarDateTime" or "cftime.datetime".

The above exception was the direct cause of the following exception:

ConversionError                           Traceback (most recent call last)
<ipython-input-47-fe6cec84569d> in <module>
      4 
      5 plt.plot([x1, x2, x3], [1, 2, 1])
----> 6 plt.axvspan(x1, x2, color='red', alpha=0.5)

~/.conda/envs/xclim-dev/lib/python3.8/site-packages/matplotlib/pyplot.py in axvspan(xmin, xmax, ymin, ymax, **kwargs)
   2460 @_copy_docstring_and_deprecators(Axes.axvspan)
   2461 def axvspan(xmin, xmax, ymin=0, ymax=1, **kwargs):
-> 2462     return gca().axvspan(xmin, xmax, ymin=ymin, ymax=ymax, **kwargs)
   2463 
   2464 

~/.conda/envs/xclim-dev/lib/python3.8/site-packages/matplotlib/axes/_axes.py in axvspan(self, xmin, xmax, ymin, ymax, **kwargs)
   1105 
   1106         # first we need to strip away the units
-> 1107         xmin, xmax = self.convert_xunits([xmin, xmax])
   1108         ymin, ymax = self.convert_yunits([ymin, ymax])
   1109 

~/.conda/envs/xclim-dev/lib/python3.8/site-packages/matplotlib/artist.py in convert_xunits(self, x)
    173         if ax is None or ax.xaxis is None:
    174             return x
--> 175         return ax.xaxis.convert_units(x)
    176 
    177     def convert_yunits(self, y):

~/.conda/envs/xclim-dev/lib/python3.8/site-packages/matplotlib/axis.py in convert_units(self, x)
   1520             ret = self.converter.convert(x, self.units, self)
   1521         except Exception as e:
-> 1522             raise munits.ConversionError('Failed to convert value(s) to axis '
   1523                                          f'units: {x!r}') from e
   1524         return ret

ConversionError: Failed to convert value(s) to axis units: [cftime.DatetimeNoLeap(1990, 1, 1, 0, 0, 0, 0), cftime.DatetimeNoLeap(1991, 1, 1, 0, 0, 0, 0)]

I hacked this into nc-time-axis (NetCDFTimeConverter.convert):

if isinstance(value, (list, tuple)):
    first_value = value

to make it work. However, I am not an expert of matplotlib and I have no idea if this could be dangerous or if it is appropriate...

@5tefan
Copy link

5tefan commented Oct 2, 2020

I'm also running into this issue with ax.axvspan. My (hopefully temporary) workaround is to call nc_time_axis.NetCDFTimeConverter().convert(bounds, None, None) where bounds contains the two DatetimeGregorian objects for something like:

#...
ax.axvspan(
    *nc_time_axis.NetCDFTimeConverter().convert(bounds, None, None),
    color="red",
    alpha=0.15
)
#...

@bjlittle
Copy link
Member

bjlittle commented Jun 7, 2021

@aulemahal Is this still a live issue that we want to pull into v1.3.0 ?

@aulemahal
Copy link
Contributor Author

Yes it is still a live issue! However, I see no rush to put it in v1.3.0. I'll try to open a PR with a solution, and if it is done in time, we'll have it there!

@aulemahal aulemahal self-assigned this Jun 8, 2021
@aulemahal aulemahal added Good First Issue A good issue to take on if you're just getting started with nc-time-axis development Type: Bug labels Jun 8, 2021
@aulemahal aulemahal added this to the v1.4.0 milestone Jun 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Good First Issue A good issue to take on if you're just getting started with nc-time-axis development Type: Bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants