Skip to content

Commit

Permalink
Merge pull request #30 from ocefpaf/use_cftime
Browse files Browse the repository at this point in the history
use cftime
  • Loading branch information
pelson authored May 23, 2018
2 parents 013c5c1 + f1ca7b2 commit da64edd
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 49 deletions.
40 changes: 20 additions & 20 deletions nc_time_axis/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Support for netcdftime axis in matplotlib.
Support for cftime axis in matplotlib.
"""

Expand All @@ -12,7 +12,7 @@
import matplotlib.ticker as mticker
import matplotlib.transforms as mtransforms
import matplotlib.units as munits
import netcdftime
import cftime
import numpy as np

# Define __version__ based on versioneer's interpretation.
Expand All @@ -27,7 +27,7 @@

class CalendarDateTime(object):
"""
Container for :class:`netcdftime.datetime` object and calendar.
Container for :class:`cftime.datetime` object and calendar.
"""
def __init__(self, datetime, calendar):
Expand All @@ -49,7 +49,7 @@ def __repr__(self):

class NetCDFTimeDateFormatter(mticker.Formatter):
"""
Formatter for netcdftime.datetime data.
Formatter for cftime.datetime data.
"""
# Some magic numbers. These seem to work pretty well.
Expand Down Expand Up @@ -81,13 +81,13 @@ def pick_format(self, ndays):

def __call__(self, x, pos=0):
format_string = self.pick_format(ndays=self.locator.ndays)
dt = netcdftime.utime(self.time_units, self.calendar).num2date(x)
dt = cftime.utime(self.time_units, self.calendar).num2date(x)
return dt.strftime(format_string)


class NetCDFTimeDateLocator(mticker.Locator):
"""
Determines tick locations when plotting netcdftime.datetime data.
Determines tick locations when plotting cftime.datetime data.
"""
def __init__(self, max_n_ticks, calendar, date_unit, min_n_ticks=3):
Expand Down Expand Up @@ -143,7 +143,7 @@ def tick_values(self, vmin, vmax):

self.ndays = float(abs(vmax - vmin))

utime = netcdftime.utime(self.date_unit, self.calendar)
utime = cftime.utime(self.date_unit, self.calendar)
lower = utime.num2date(vmin)
upper = utime.num2date(vmax)

Expand All @@ -153,7 +153,7 @@ def tick_values(self, vmin, vmax):
# TODO START AT THE BEGINNING OF A DECADE/CENTURY/MILLENIUM as
# appropriate.
years = self._max_n_locator.tick_values(lower.year, upper.year)
ticks = [netcdftime.datetime(int(year), 1, 1) for year in years]
ticks = [cftime.datetime(int(year), 1, 1) for year in years]
elif resolution == 'MONTHLY':
# TODO START AT THE BEGINNING OF A DECADE/CENTURY/MILLENIUM as
# appropriate.
Expand All @@ -162,27 +162,27 @@ def tick_values(self, vmin, vmax):
for offset in months_offset:
year = lower.year + np.floor((lower.month + offset) / 12)
month = ((lower.month + offset) % 12) + 1
ticks.append(netcdftime.datetime(int(year), int(month), 1))
ticks.append(cftime.datetime(int(year), int(month), 1))
elif resolution == 'DAILY':
# TODO: It would be great if this favoured multiples of 7.
days = self._max_n_locator_days.tick_values(vmin, vmax)
ticks = [utime.num2date(dt) for dt in days]
elif resolution == 'HOURLY':
hour_unit = 'hours since 2000-01-01'
hour_utime = netcdftime.utime(hour_unit, self.calendar)
hour_utime = cftime.utime(hour_unit, self.calendar)
in_hours = hour_utime.date2num([lower, upper])
hours = self._max_n_locator.tick_values(in_hours[0], in_hours[1])
ticks = [hour_utime.num2date(dt) for dt in hours]
elif resolution == 'MINUTELY':
minute_unit = 'minutes since 2000-01-01'
minute_utime = netcdftime.utime(minute_unit, self.calendar)
minute_utime = cftime.utime(minute_unit, self.calendar)
in_minutes = minute_utime.date2num([lower, upper])
minutes = self._max_n_locator.tick_values(in_minutes[0],
in_minutes[1])
ticks = [minute_utime.num2date(dt) for dt in minutes]
elif resolution == 'SECONDLY':
second_unit = 'seconds since 2000-01-01'
second_utime = netcdftime.utime(second_unit, self.calendar)
second_utime = cftime.utime(second_unit, self.calendar)
in_seconds = second_utime.date2num([lower, upper])
seconds = self._max_n_locator.tick_values(in_seconds[0],
in_seconds[1])
Expand All @@ -196,7 +196,7 @@ def tick_values(self, vmin, vmax):

class NetCDFTimeConverter(mdates.DateConverter):
"""
Converter for netcdftime.datetime data.
Converter for cftime.datetime data.
"""
standard_unit = 'days since 2000-01-01'
Expand All @@ -215,8 +215,8 @@ def axisinfo(unit, axis):
date_unit=date_unit)
majfmt = NetCDFTimeDateFormatter(majloc, calendar=calendar,
time_units=date_unit)
datemin = CalendarDateTime(netcdftime.datetime(2000, 1, 1), calendar)
datemax = CalendarDateTime(netcdftime.datetime(2010, 1, 1), calendar)
datemin = CalendarDateTime(cftime.datetime(2000, 1, 1), calendar)
datemax = CalendarDateTime(cftime.datetime(2010, 1, 1), calendar)
return munits.AxisInfo(majloc=majloc, majfmt=majfmt, label='',
default_limits=(datemin, datemax))

Expand All @@ -238,7 +238,7 @@ def default_units(cls, sample_point, axis):
else:
# Deal with a single `sample_point` value.
if not hasattr(sample_point, 'calendar'):
msg = ('Expecting netcdftimes with an extra '
msg = ('Expecting cftimes with an extra '
'"calendar" attribute.')
raise ValueError(msg)
else:
Expand All @@ -249,7 +249,7 @@ def default_units(cls, sample_point, axis):
def convert(cls, value, unit, axis):
"""
Converts value, if it is not already a number or sequence of numbers,
with :func:`netcdftime.utime().date2num`.
with :func:`cftime.utime().date2num`.
"""
shape = None
Expand All @@ -270,11 +270,11 @@ def convert(cls, value, unit, axis):
raise ValueError('The values must be numbers or instances of '
'"nc_time_axis.CalendarDateTime".')

if not isinstance(first_value.datetime, netcdftime.datetime):
if not isinstance(first_value.datetime, cftime.datetime):
raise ValueError('The datetime attribute of the CalendarDateTime '
'object must be of type `netcdftime.datetime`.')
'object must be of type `cftime.datetime`.')

ut = netcdftime.utime(cls.standard_unit, calendar=first_value.calendar)
ut = cftime.utime(cls.standard_unit, calendar=first_value.calendar)

if isinstance(value, CalendarDateTime):
value = [value]
Expand Down
4 changes: 2 additions & 2 deletions nc_time_axis/tests/integration/test_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import matplotlib
matplotlib.use('agg')
import matplotlib.pyplot as plt # nopep8
import netcdftime # nopep8
import cftime # nopep8
import numpy as np # nopep8

import nc_time_axis # nopep8
Expand All @@ -26,7 +26,7 @@ def tearDown(self):
plt.close('all')

def test_360_day_calendar(self):
datetimes = [netcdftime.datetime(1986, month, 30)
datetimes = [cftime.datetime(1986, month, 30)
for month in range(1, 6)]
cal_datetimes = [nc_time_axis.CalendarDateTime(dt, '360_day')
for dt in datetimes]
Expand Down
14 changes: 7 additions & 7 deletions nc_time_axis/tests/unit/test_CalendarDateTime.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,26 @@

import unittest

import netcdftime
import cftime

from nc_time_axis import CalendarDateTime


class Test___eq__(unittest.TestCase):
def setUp(self):
self.cdt = CalendarDateTime(netcdftime.datetime(1967, 7, 22, 3, 6),
self.cdt = CalendarDateTime(cftime.datetime(1967, 7, 22, 3, 6),
'360_day')

def test_equal(self):
self.assertTrue(self.cdt == self.cdt)

def test_diff_cal(self):
other_cdt = CalendarDateTime(netcdftime.datetime(1967, 7, 22, 3, 6),
other_cdt = CalendarDateTime(cftime.datetime(1967, 7, 22, 3, 6),
'365_day')
self.assertFalse(self.cdt == other_cdt)

def test_diff_datetime(self):
other_cdt = CalendarDateTime(netcdftime.datetime(1992, 11, 23, 3, 6),
other_cdt = CalendarDateTime(cftime.datetime(1992, 11, 23, 3, 6),
'360_day')
self.assertFalse(self.cdt == other_cdt)

Expand All @@ -34,19 +34,19 @@ def test_diff_type(self):

class Test__ne__(unittest.TestCase):
def setUp(self):
self.cdt = CalendarDateTime(netcdftime.datetime(1967, 7, 22, 3, 6),
self.cdt = CalendarDateTime(cftime.datetime(1967, 7, 22, 3, 6),
'360_day')

def test_equal(self):
self.assertFalse(self.cdt != self.cdt)

def test_diff_cal(self):
other_cdt = CalendarDateTime(netcdftime.datetime(1967, 7, 22, 3, 6),
other_cdt = CalendarDateTime(cftime.datetime(1967, 7, 22, 3, 6),
'365_day')
self.assertTrue(self.cdt != other_cdt)

def test_diff_datetime(self):
other_cdt = CalendarDateTime(netcdftime.datetime(1992, 11, 23, 3, 6),
other_cdt = CalendarDateTime(cftime.datetime(1992, 11, 23, 3, 6),
'360_day')
self.assertTrue(self.cdt != other_cdt)

Expand Down
32 changes: 16 additions & 16 deletions nc_time_axis/tests/unit/test_NetCDFTimeConverter.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import unittest

import netcdftime
import cftime
import numpy as np

from nc_time_axis import NetCDFTimeConverter, CalendarDateTime
Expand All @@ -16,8 +16,8 @@ def test_axis_default_limits(self):
cal = '360_day'
unit = (cal, 'days since 2000-02-25 00:00:00')
result = NetCDFTimeConverter().axisinfo(unit, None)
expected_dt = [netcdftime.datetime(2000, 1, 1),
netcdftime.datetime(2010, 1, 1)]
expected_dt = [cftime.datetime(2000, 1, 1),
cftime.datetime(2010, 1, 1)]
np.testing.assert_array_equal(
result.default_limits,
[CalendarDateTime(edt, cal) for edt in expected_dt])
Expand All @@ -27,24 +27,24 @@ class Test_default_units(unittest.TestCase):
def test_360_day_calendar_point(self):
calendar = '360_day'
unit = 'days since 2000-01-01'
val = CalendarDateTime(netcdftime.datetime(2014, 8, 12), calendar)
val = CalendarDateTime(cftime.datetime(2014, 8, 12), calendar)
result = NetCDFTimeConverter().default_units(val, None)
self.assertEqual(result, (calendar, unit))

def test_360_day_calendar_list(self):
calendar = '360_day'
unit = 'days since 2000-01-01'
val = [CalendarDateTime(netcdftime.datetime(2014, 8, 12), calendar)]
val = [CalendarDateTime(cftime.datetime(2014, 8, 12), calendar)]
result = NetCDFTimeConverter().default_units(val, None)
self.assertEqual(result, (calendar, unit))

def test_360_day_calendar_nd(self):
# Test the case where the input is an nd-array.
calendar = '360_day'
unit = 'days since 2000-01-01'
val = np.array([[CalendarDateTime(netcdftime.datetime(2014, 8, 12),
val = np.array([[CalendarDateTime(cftime.datetime(2014, 8, 12),
calendar)],
[CalendarDateTime(netcdftime.datetime(2014, 8, 13),
[CalendarDateTime(cftime.datetime(2014, 8, 13),
calendar)]])
result = NetCDFTimeConverter().default_units(val, None)
self.assertEqual(result, (calendar, unit))
Expand All @@ -54,8 +54,8 @@ def test_nonequal_calendars(self):
calendar_1 = '360_day'
calendar_2 = '365_day'
unit = 'days since 2000-01-01'
val = [CalendarDateTime(netcdftime.datetime(2014, 8, 12), calendar_1),
CalendarDateTime(netcdftime.datetime(2014, 8, 13), calendar_2)]
val = [CalendarDateTime(cftime.datetime(2014, 8, 12), calendar_1),
CalendarDateTime(cftime.datetime(2014, 8, 13), calendar_2)]
with self.assertRaisesRegexp(ValueError, 'not all equal'):
NetCDFTimeConverter().default_units(val, None)

Expand Down Expand Up @@ -83,26 +83,26 @@ def test_numeric_iterable(self):
result = NetCDFTimeConverter().convert(val, None, None)
np.testing.assert_array_equal(result, val)

def test_netcdftime(self):
val = CalendarDateTime(netcdftime.datetime(2014, 8, 12), '365_day')
def test_cftime(self):
val = CalendarDateTime(cftime.datetime(2014, 8, 12), '365_day')
result = NetCDFTimeConverter().convert(val, None, None)
np.testing.assert_array_equal(result, 5333.)

def test_netcdftime_np_array(self):
val = np.array([CalendarDateTime(netcdftime.datetime(2012, 6, 4),
def test_cftime_np_array(self):
val = np.array([CalendarDateTime(cftime.datetime(2012, 6, 4),
'360_day')], dtype=np.object)
result = NetCDFTimeConverter().convert(val, None, None)
self.assertEqual(result, np.array([4473.]))

def test_non_netcdftime_datetime(self):
def test_non_cftime_datetime(self):
val = CalendarDateTime(4, '360_day')
msg = 'The datetime attribute of the CalendarDateTime object must ' \
'be of type `netcdftime.datetime`.'
'be of type `cftime.datetime`.'
with self.assertRaisesRegexp(ValueError, msg):
result = NetCDFTimeConverter().convert(val, None, None)

def test_non_CalendarDateTime(self):
val = netcdftime.datetime(1988, 5, 6)
val = cftime.datetime(1988, 5, 6)
msg = 'The values must be numbers or instances of ' \
'"nc_time_axis.CalendarDateTime".'
with self.assertRaisesRegexp(ValueError, msg):
Expand Down
4 changes: 2 additions & 2 deletions nc_time_axis/tests/unit/test_NetCDFTimeDateLocator.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import unittest

import matplotlib.dates as mdates
import netcdftime
import cftime
import numpy as np

from nc_time_axis import NetCDFTimeDateLocator
Expand All @@ -21,7 +21,7 @@ def check(self, max_n_ticks, num1, num2):
locator = NetCDFTimeDateLocator(max_n_ticks=max_n_ticks,
calendar=self.calendar,
date_unit=self.date_unit)
utime = netcdftime.utime(self.date_unit, self.calendar)
utime = cftime.utime(self.date_unit, self.calendar)
return locator.compute_resolution(num1, num2, utime.num2date(num1),
utime.num2date(num2))

Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
name='nc-time-axis',
version=versioneer.get_version(),
cmdclass=versioneer.get_cmdclass(),
description='netcdftime support for matplotlib axis',
description='cftime support for matplotlib axis',
license='BSD3',
author='Laura Dreyer, Philip Elson',
url='https://github.com/scitools/nc-time-axis',
packages=packages,
install_requires = ['matplotlib==1.*',
'netcdf4',
'cftime',
'numpy',
'six'],
tests_require = ['mock', 'pep8'],
Expand Down

0 comments on commit da64edd

Please sign in to comment.