Printing a cube coordinate should not cause a ValueError

266 views
Skip to first unread message

LeonH

unread,
Aug 1, 2014, 12:56:59 PM8/1/14
to scitoo...@googlegroups.com
This has happened twice to me now, so I thought I would bring it up. The introduction of printing actual dates when a cube or a time coordinate is printed is great. Unfortunately, it doesn't work if one has a non-standard time unit.

>>> print cube.coord('time')[0]
Traceback (most recent call last):
 
File "<stdin>", line 1, in <module>
 
File "/project/avd/iris/live/pre-release/iris/coords.py", line 546, in __str__
    points
= self._str_dates(self.points)
 
File "/project/avd/iris/live/pre-release/iris/coords.py", line 529, in _str_dates
    date_obj_array
= self.units.num2date(dates_as_numbers)
 
File "/project/avd/iris/live/pre-release/iris/unit.py", line 1981, in num2date
    cdf_utime
= self.utime()
 
File "/project/avd/iris/live/pre-release/iris/unit.py", line 1902, in utime
   
return netcdftime.utime(str(self).rstrip(" UTC"), self.calendar)
 
File "/usr/local/sci/lib/python2.7/site-packages/netcdftime.py", line 609, in __init__
    units
, tzoffset, self.origin = _dateparse(unit_string)
 
File "/usr/local/sci/lib/python2.7/site-packages/netcdftime.py", line 463, in _dateparse
   
raise ValueError("units must be one of 'seconds', 'minutes', 'hours' or 'days' (or singular version of these), got '%s'" % units)
ValueError: units must be one of 'seconds', 'minutes', 'hours' or 'days' (or singular version of these), got 'months'


The problem is that the unit is "months since 2014-01-01 00:00:00". It appears time units can only have "'seconds', 'minutes', 'hours' or 'days'".

I think this is an unnecessary error and iris should be able to cope with it. It is a print statement, you don't expect that to fail!!

There are two obvious solutions:
1. Start supporting 'months' and 'years' (the two cases I've come across)
2. Set the function cube.coord('time').units.is_time_reference() to return False when the coordinate is non-standard

Andrew Dawson

unread,
Aug 1, 2014, 2:37:48 PM8/1/14
to scitoo...@googlegroups.com
I think this is a bug and probably deserves a ticket. However I'm not fond of either of your two solutions. I think supporting month and year is a design choice of the netcdftime library since these have some ambiguity. I also think a lot of people would be disappointed to find out that their time coordinates are no longer classified as time! guess_coord_axis() uses is_time_reference() to detect time dimensions, changing this would mean you would no longer be able to select this coordinate using cube.coord(axis='T'). Perhaps a simpler approach would be just to catch this exception when trying to convert the coordinate points to time strings and fall back to the method used for non-time coordinates.

LeonH

unread,
Aug 3, 2015, 11:37:45 AM8/3/15
to Iris
I guess no-one thought it was important that printing a cube fails gracefully. I have found another cube that won't print.
>>> print c[0].coord('time')


Traceback (most recent call last):

 
File "<pyshell#18>", line 1, in <module>
   
print c[0].coord('time')
 
File "/opt/ukmo/iris/default/linux64/site-packages/iris/coords.py", line 555, in __str__
    points
= self._str_dates(self.points)
 
File "/opt/ukmo/iris/default/linux64/site-packages/iris/coords.py", line 543, in _str_dates
    date_obj_array
, formatter={'numpystr': str}, **kwargs)
 
File "/usr/local/sci/lib/python2.7/site-packages/numpy/core/arrayprint.py", line 454, in array2string
    separator
, prefix, formatter=formatter)
 
File "/usr/local/sci/lib/python2.7/site-packages/numpy/core/arrayprint.py", line 328, in _array2string
    _summaryEdgeItems
, summary_insert)[:-1]
 
File "/usr/local/sci/lib/python2.7/site-packages/numpy/core/arrayprint.py", line 500, in _formatArray
    word
= format_function(a[-1])
 
File "/usr/local/sci/lib/python2.7/site-packages/netcdftime.py", line 51, in __repr__
   
return self.strftime(self.format)
 
File "/usr/local/sci/lib/python2.7/site-packages/netcdftime.py", line 47, in strftime
   
return _strftime(self,format)
 
File "/usr/local/sci/lib/python2.7/site-packages/netcdftime.py", line 864, in _strftime
    s1
= time.strftime(fmt, (year,) + timetuple[1:])
ValueError: day of month out of range
>>> print c[0].coord('time').points
[  2.20752000e+08]
>>> print c[0].coord('time').units
seconds since
1976-01-01 00:00:00
>>> ap.iris.__version__
'1.8.1'



Andrew Dawson

unread,
Aug 3, 2015, 12:43:57 PM8/3/15
to Iris
I guess no-one thought it was important that printing a cube fails gracefully.

Well, did you open an issue as suggested in the initial reply?

Groups is great for discussion but actual bugs need to be raised in the issue tracker. There are a lot of things on the developers' to-do list and more things added all the time, so something that doesn't have a corresponding ticket is not likely to win any attention. Also, you can always submit a pull request yourself if you want, contributions are always welcome.

Jonny Williams

unread,
Oct 31, 2016, 1:24:10 AM10/31/16
to Iris
Hi there

I was just wondering if there was a solution to this as yet?

I am getting the error below in my Jupyter notebook...

Many thansk!

woa=woa[0]

print(woa)

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-138-e806e4f44a2b> in <module>()
      2 woa=woa[0]
      3 
----> 4 print(woa)

/opt/niwa/anaconda/Anaconda-2.4.1-Python-2.7/lib/python2.7/site-packages/iris/cube.py in __str__(self)
   2128             return self.summary()
   2129         else:
-> 2130             return self.summary().encode(errors='replace')
   2131 
   2132     def __unicode__(self):

/opt/niwa/anaconda/Anaconda-2.4.1-Python-2.7/lib/python2.7/site-packages/iris/cube.py in summary(self, shorten, name_padding)
   2028                         if coord.units.is_time_reference():
   2029                             coord_cell_cpoint = coord.units.num2date(
-> 2030                                 coord_cell.point)
   2031                             if coord_cell.bound is not None:
   2032                                 coord_cell_cbound = coord.units.num2date(

/opt/niwa/anaconda/Anaconda-2.4.1-Python-2.7/lib/python2.7/site-packages/cf_units/__init__.pyc in num2date(self, time_value)
   2072 
   2073         """
-> 2074         cdf_utime = self.utime()
   2075         return cdf_utime.num2date(time_value)

/opt/niwa/anaconda/Anaconda-2.4.1-Python-2.7/lib/python2.7/site-packages/cf_units/__init__.pyc in utime(self)
   1993         if self.calendar is None:
   1994             raise ValueError('Unit has undefined calendar')
-> 1995         return netcdftime.utime(str(self).rstrip(" UTC"), self.calendar)
   1996 
   1997     def date2num(self, date):

/opt/niwa/anaconda/Anaconda-2.4.1-Python-2.7/lib/python2.7/site-packages/netcdftime/netcdftime.pyc in __init__(self, unit_string, calendar)
    664             raise ValueError(
    665                 "calendar must be one of %s, got '%s'" % (str(_calendars), calendar))
--> 666         units, tzoffset, self.origin = _dateparse(unit_string)
    667         self.tzoffset = tzoffset  # time zone offset in minutes
    668         self.units = units

/opt/niwa/anaconda/Anaconda-2.4.1-Python-2.7/lib/python2.7/site-packages/netcdftime/netcdftime.pyc in _dateparse(timestr)
    512     if units not in _units:
    513         raise ValueError(
--> 514             "units must be one of 'seconds', 'minutes', 'hours' or 'days' (or singular version of these), got '%s'" % units)
    515     if timestr_split[1].lower() != 'since':
    516         raise ValueError("no 'since' in unit_string")


ValueError: units must be one of 'seconds', 'minutes', 'hours' or 'days' (or singular version of these), got 'months'

DeeKay

unread,
Feb 10, 2017, 5:48:14 AM2/10/17
to Iris
Hi everyone,

We have finally made some progress towards fixing this issue - see https://github.com/SciTools/iris/pull/2354 and https://github.com/SciTools/cf_units/pull/72. The situation was not as simple as it might have first appeared as it originated in a discrepancy between the functionality of two libraries (`netcdftime` and `UDUNITS2`) that Iris depends on. Further details on this are available in the descriptions of the two linked PRs. 

When these PRs are merged you will no longer see an exception raised if you try to print a cube that has a time coordinate measured in months or years. These PRs also provide an interim workaround to the more concerning problem, which is that we cannot convert between datetimes and numbers (by using `num2date` or `date2num`) for such time coordinates, because of the non-support of `netcdftime` for such time units. In the medium term we hope to introduce a new system for dealing with time units to Iris, which we hope will fix these issues completely rather than working around them.

Peter Watson

unread,
Jul 27, 2018, 6:57:05 AM7/27/18
to SciTools (iris, cartopy, cf_units, etc.) - https://github.com/scitools
Hi, I had this issue when reading in data with a time coordinate in months using Iris 2.1.0, though the error message has changed to "ValueError: Time units with interval of "months", "years" (or singular of these) cannot be processed, got 'months'." Is there a workaround for this, or a simple way to convert the time units?
Reply all
Reply to author
Forward
0 new messages