Revision: 6830
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6830&view=rev
Author:   jswhit
Date:     2009-01-26 19:48:04 +0000 (Mon, 26 Jan 2009)

Log Message:
-----------
update netcdftime to version 0.7, add date2index function.

Modified Paths:
--------------
    trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py
    trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py

Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py
===================================================================
--- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py 2009-01-26 
16:39:14 UTC (rev 6829)
+++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py 2009-01-26 
19:48:04 UTC (rev 6830)
@@ -17,6 +17,8 @@
 :func:`num2date`: convert from a numeric time value to a datetime object.
 
 :func:`date2num`: convert from a datetime object to a numeric time value.
+
+:func:`date2index`: compute a time variable index corresponding to a date.
 """
 from matplotlib import __version__ as _matplotlib_version
 from matplotlib.cbook import is_scalar, dedent
@@ -3941,6 +3943,42 @@
     cdftime = netcdftime.utime(units,calendar=calendar)
     return cdftime.date2num(dates)
 
+def date2index(dates, nctime, calendar=None):
+    """
+    Return indices of a netCDF time variable corresponding to the given dates.
+
+    .. tabularcolumns:: |l|L|
+
+    ==============   ====================================================
+    Arguments        Description
+    ==============   ====================================================
+    dates            A datetime object or a sequence of datetime objects.
+                     The datetime objects should not include a
+                     time-zone offset.
+    nctime           A netCDF time variable object.  The nctime object
+                     must have a ``units`` attribute.
+    ==============   ====================================================
+
+    .. tabularcolumns:: |l|L|
+
+    ==============   ====================================================
+    Keywords          Description
+    ==============   ====================================================
+    calendar         describes the calendar used in the time
+                     calculations.  All the values currently defined in 
+                     the CF metadata convention
+                     (http://cf-pcmdi.llnl.gov/documents/cf-conventions/)
+                     are supported.
+                     Valid calendars ``standard``, ``gregorian``,
+                     ``proleptic_gregorian``, ``noleap``, ``365_day``,
+                     ``julian``, ``all_leap``, ``366_day``.
+                     Default is ``proleptic_gregorian``.
+    ==============   ====================================================
+
+    Returns an index or a sequence of indices.
+    """
+    return netcdftime.date2index(dates, nctime, calendar=None)
+
 def maskoceans(lonsin,latsin,datain,inlands=False):
     """
     mask data (``datain``), defined on a grid with latitudes ``latsin``

Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py
===================================================================
--- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py       
2009-01-26 16:39:14 UTC (rev 6829)
+++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py       
2009-01-26 19:48:04 UTC (rev 6830)
@@ -1,14 +1,13 @@
 """
 Performs conversions of netCDF time coordinate data to/from datetime objects.
 """
-import math, re, time
-import numpy as np
+import math, numpy, re, time
 from datetime import datetime as real_datetime
 
 _units = ['days','hours','minutes','seconds','day','hour','minute','second']
 _calendars = 
['standard','gregorian','proleptic_gregorian','noleap','julian','all_leap','365_day','366_day','360_day']
 
-__version__ = '0.6'
+__version__ = '0.7'
 
 class datetime:
     """
@@ -467,8 +466,8 @@
 
 The B{C{calendar}} keyword describes the calendar used in the time 
calculations. 
 All the values currently defined in the U{CF metadata convention 
-<http://www.cgd.ucar.edu/cms/eaton/cf-metadata/CF-1.0.html#time>} are 
-accepted. The default is C{'standard'}, which corresponds to the mixed 
+<http://cf-pcmdi.llnl.gov/documents/cf-conventions/1.1/cf-conventions.html#time-coordinate>}
  
+are accepted. The default is C{'standard'}, which corresponds to the mixed 
 Gregorian/Julian calendar used by the C{udunits library}. Valid calendars 
 are:
 
@@ -534,8 +533,7 @@
 C{'standard'} or C{'gregorian'} calendars.  An exception will be raised if you 
pass 
 a 'datetime-like' object in that range to the C{L{date2num}} class method.
 
-Words of Wisdom from the British MetOffice concerning reference dates 
-U{http://www.metoffice.com/research/hadleycentre/models/GDT/ch26.html}:
+Words of Wisdom from the British MetOffice concerning reference dates:
 
 "udunits implements the mixed Gregorian/Julian calendar system, as 
 followed in England, in which dates prior to 1582-10-15 are assumed to use 
@@ -560,8 +558,8 @@
 
 @keyword calendar: describes the calendar used in the time calculations. 
 All the values currently defined in the U{CF metadata convention 
-<http://www.cgd.ucar.edu/cms/eaton/cf-metadata/CF-1.0.html#time>} are 
-accepted. The default is C{'standard'}, which corresponds to the mixed 
+<http://cf-pcmdi.llnl.gov/documents/cf-conventions/1.1/cf-conventions.html#time-coordinate>}
+are accepted. The default is C{'standard'}, which corresponds to the mixed 
 Gregorian/Julian calendar used by the C{udunits library}. Valid calendars 
 are:
  - C{'gregorian'} or C{'standard'} (default):
@@ -630,7 +628,7 @@
         except:
             isscalar = True
         if not isscalar:
-            date = np.array(date)
+            date = numpy.array(date)
             shape = date.shape
         if self.calendar in 
['julian','standard','gregorian','proleptic_gregorian']:
             if isscalar:
@@ -657,7 +655,7 @@
             else:
                 jdelta = [_360DayFromDate(d)-self._jd0 for d in date.flat]
         if not isscalar:
-            jdelta = np.array(jdelta)
+            jdelta = numpy.array(jdelta)
         # convert to desired units, add time zone offset.
         if self.units in ['second','seconds']:
             jdelta = jdelta*86400. + self.tzoffset*60.
@@ -670,7 +668,7 @@
         if isscalar:
             return jdelta
         else:
-            return np.reshape(jdelta,shape)
+            return numpy.reshape(jdelta,shape)
 
     def num2date(self,time_value):
         """
@@ -682,8 +680,8 @@
 
 Resolution is 1 second.
 
-Works for scalars, sequences and np arrays.
-Returns a scalar if input is a scalar, else returns a np array.
+Works for scalars, sequences and numpy arrays.
+Returns a scalar if input is a scalar, else returns a numpy array.
 
 The datetime instances returned by C{num2date} are 'real' python datetime 
 objects if the date falls in the Gregorian calendar (i.e. 
@@ -700,7 +698,7 @@
         except:
             isscalar = True
         if not isscalar:
-            time_value = np.array(time_value)
+            time_value = numpy.array(time_value, dtype='d')
             shape = time_value.shape
         # convert to desired units, remove time zone offset.
         if self.units in ['second','seconds']:
@@ -735,7 +733,7 @@
         if isscalar:
             return date
         else:
-            return np.reshape(np.array(date),shape)
+            return numpy.reshape(numpy.array(date),shape)
 
 def _parse_date(origin):
     """Parses a date string and returns a tuple
@@ -852,3 +850,147 @@
     for site in sites:
         s = s[:site] + syear + s[site+4:]
     return s
+
+def date2num(dates,units,calendar='standard'):
+    """
+date2num(dates,units,calendar='standard')
+
+Return numeric time values given datetime objects. The units
+of the numeric time values are described by the L{units} argument
+and the L{calendar} keyword. The datetime objects must
+be in UTC with no time-zone offset.  If there is a 
+time-zone offset in C{units}, it will be applied to the
+returned numeric values.
+
+Like the matplotlib C{date2num} function, except that it allows
+for different units and calendars.  Behaves the same if
+C{units = 'days since 0001-01-01 00:00:00'} and 
+C{calendar = 'proleptic_gregorian'}.
+
+...@param dates: A datetime object or a sequence of datetime objects.
+ The datetime objects should not include a time-zone offset.
+
+...@param units: a string of the form C{'B{time units} since B{reference 
time}}'
+ describing the time units. B{C{time units}} can be days, hours, minutes
+ or seconds.  B{C{reference time}} is the time origin. A valid choice
+ would be units=C{'hours since 1800-01-01 00:00:00 -6:00'}.
+
+...@param calendar: describes the calendar used in the time calculations. 
+ All the values currently defined in the U{CF metadata convention 
+ <http://cf-pcmdi.llnl.gov/documents/cf-conventions/>} are supported.
+ Valid calendars C{'standard', 'gregorian', 'proleptic_gregorian'
+ 'noleap', '365_day', '360_day', 'julian', 'all_leap', '366_day'}.
+ Default is C{'standard'}, which is a mixed Julian/Gregorian calendar.
+
+...@return: a numeric time value, or an array of numeric time values.
+
+The maximum resolution of the numeric time values is 1 second.
+    """
+    cdftime = utime(units,calendar=calendar)
+    return cdftime.date2num(dates)
+
+def num2date(times,units,calendar='standard'):
+    """
+num2date(times,units,calendar='standard')
+
+Return datetime objects given numeric time values. The units
+of the numeric time values are described by the C{units} argument
+and the C{calendar} keyword. The returned datetime objects represent 
+UTC with no time-zone offset, even if the specified 
+C{units} contain a time-zone offset.
+
+Like the matplotlib C{num2date} function, except that it allows
+for different units and calendars.  Behaves the same if
+C{units = 'days since 001-01-01 00:00:00'} and 
+C{calendar = 'proleptic_gregorian'}.
+
+...@param times: numeric time values. Maximum resolution is 1 second.
+
+...@param units: a string of the form C{'B{time units} since B{reference 
time}}'
+describing the time units. B{C{time units}} can be days, hours, minutes
+or seconds.  B{C{reference time}} is the time origin. A valid choice
+would be units=C{'hours since 1800-01-01 00:00:00 -6:00'}.
+
+...@param calendar: describes the calendar used in the time calculations. 
+All the values currently defined in the U{CF metadata convention 
+<http://cf-pcmdi.llnl.gov/documents/cf-conventions/>} are supported.
+Valid calendars C{'standard', 'gregorian', 'proleptic_gregorian'
+'noleap', '365_day', '360_day', 'julian', 'all_leap', '366_day'}.
+Default is C{'standard'}, which is a mixed Julian/Gregorian calendar.
+
+...@return: a datetime instance, or an array of datetime instances.
+
+The datetime instances returned are 'real' python datetime 
+objects if the date falls in the Gregorian calendar (i.e. 
+C{calendar='proleptic_gregorian'}, or C{calendar = 'standard'} or 
C{'gregorian'}
+and the date is after 1582-10-15). Otherwise, they are 'phony' datetime 
+objects which support some but not all the methods of 'real' python
+datetime objects.  This is because the python datetime module cannot
+the uses the C{'proleptic_gregorian'} calendar, even before the switch
+occured from the Julian calendar in 1582. The datetime instances
+do not contain a time-zone offset, even if the specified C{units}
+contains one.
+    """
+    cdftime = utime(units,calendar=calendar)
+    return cdftime.num2date(times)
+
+
+def _check_index(indices, dates, nctime, calendar):
+    """Assert that the time indices given correspond to the given dates."""
+    t = nctime[indices]
+    assert numpy.all( num2date(t, nctime.units, calendar) == dates)
+
+
+def date2index(dates, nctime, calendar=None):
+    """
+    date2index(dates, nctime, calendar=None)
+    
+    Return indices of a netCDF time variable corresponding to the given dates.
+    
+    @param dates: A datetime object or a sequence of datetime objects.
+    The datetime objects should not include a time-zone offset.
+    
+    @param nctime: A netCDF time variable object. The nctime object must have a
+    C{units} attribute.
+    
+    @param calendar: Describes the calendar used in the time calculation.
+    Valid calendars C{'standard', 'gregorian', 'proleptic_gregorian'
+    'noleap', '365_day', '360_day', 'julian', 'all_leap', '366_day'}.
+    Default is C{'standard'}, which is a mixed Julian/Gregorian calendar
+    If C{calendar} is None, its value is given by C{nctime.calendar} or
+    C{standard} if no such attribute exists.
+    """
+    # Setting the calendar.
+    if calendar is None:
+        calendar = getattr(nctime, 'calendar', 'standard')
+
+    num = numpy.atleast_1d(date2num(dates, nctime.units, calendar))
+
+    index = numpy.empty(numpy.alen(dates), int)
+
+    # Trying to infer the correct index from the starting time and the stride.
+    try:
+        t0, t1 = nctime[:2]
+        dt = t1 - t0
+        index[:] = (num-t0)/dt
+
+        # convert numpy scalars or single element arrays to python ints.
+        if not len(index.shape) or index.shape == (1,):
+            index = index.item()
+
+        # Checking that the index really corresponds to the given date.
+        _check_index(index, dates, nctime, calendar)
+
+    except AssertionError:
+        # If check fails, use brute force method.
+        index[:] = numpy.digitize(num, nctime[:]) - 1
+
+        # convert numpy scalars or single element arrays to python ints.
+        if not len(index.shape) or index.shape == (1,):
+            index = index.item()
+
+        # Perform check again.
+        _check_index(index, dates, nctime, calendar)
+
+    return index
+


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to