|
From: <js...@us...> - 2011-02-12 13:56:51
|
Revision: 8977
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8977&view=rev
Author: jswhit
Date: 2011-02-12 13:56:44 +0000 (Sat, 12 Feb 2011)
Log Message:
-----------
remove more vestiges of netcdf support
Modified Paths:
--------------
trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py
Removed Paths:
-------------
trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdf.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 2011-02-12 13:54:34 UTC (rev 8976)
+++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py 2011-02-12 13:56:44 UTC (rev 8977)
@@ -11,12 +11,6 @@
:func:`shiftgrid`: shifts global lat/lon grids east or west.
:func:`addcyclic`: Add cyclic (wraparound) point in longitude.
-
-: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
@@ -38,7 +32,7 @@
import numpy as np
import numpy.ma as ma
from shapelib import ShapeFile
-import _geoslib, netcdftime
+import _geoslib
# basemap data files now installed in lib/matplotlib/toolkits/basemap/data
# check to see if environment variable BASEMAPDATA set to a directory,
@@ -3974,160 +3968,6 @@
else:
return corners
-def num2date(times,units='days since 0001-01-01 00:00:00',calendar='proleptic_gregorian'):
- """
- Return datetime objects given numeric time values. The units
- of the numeric time values are described by the ``units`` argument
- and the ``calendar`` keyword. The returned datetime objects represent
- UTC with no time-zone offset, even if the specified
- units contain a time-zone offset.
-
- Default behavior is the same as the matplotlib.dates.num2date function
- but the reference time and calendar can be changed via the
- ``units`` and ``calendar`` keywords.
-
- .. tabularcolumns:: |l|L|
-
- ============== ====================================================
- Arguments Description
- ============== ====================================================
- times numeric time values. Maximum resolution is 1 second.
- ============== ====================================================
-
- .. tabularcolumns:: |l|L|
-
- ============== ====================================================
- Keywords Description
- ============== ====================================================
- units a string of the form '<time units> since
- <reference time>' describing the units and
- origin of the time coordinate.
- <time units> can be days, hours, minutes
- or seconds. <reference time> is the time origin.
- Default is 'days since 0001-01-01 00:00:00'.
- 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 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.
- calendar=``proleptic_gregorian``, or calendar = ``standard``
- or ``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. The datetime instances do not contain
- a time-zone offset, even if the specified units contains one.
- """
- cdftime = netcdftime.utime(units,calendar=calendar)
- return cdftime.num2date(times)
-
-def date2num(dates,units='days since 0001-01-01 00:00:00',calendar='proleptic_gregorian'):
- """
- Return numeric time values given datetime objects. The units
- of the numeric time values are described by the ``units`` argument
- and the ``calendar`` keyword. The datetime objects must
- be in UTC with no time-zone offset. If there is a
- time-zone offset in units, it will be applied to the
- returned numeric values.
-
- Default behavior is the same as the matplotlib.dates.date2num function
- but the reference time and calendar can be changed via the
- ``units`` and ``calendar`` keywords.
-
- .. 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.
- ============== ====================================================
-
- .. tabularcolumns:: |l|L|
-
- ============== ====================================================
- Keywords Description
- ============== ====================================================
- units a string of the form '<time units> since
- <reference time>' describing the units and
- origin of the time coordinate.
- <time units> can be days, hours, minutes
- or seconds. <reference time> is the time origin.
- Default is 'days since 0001-01-01 00:00:00'.
- 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 a numeric time value, or an array of numeric time values.
-
- The maximum resolution of the numeric time values is 1 second.
- """
- cdftime = netcdftime.utime(units,calendar=calendar)
- return cdftime.date2num(dates)
-
-def date2index(dates, nctime, calendar=None,select='exact'):
- """
- 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``.
- If ``calendar=None``, will use ``calendar`` attribute
- of ``nctime`` object, and if that attribute does
- not exist calendar is set to ``standard``.
- Default is ``None``.
- select The index selection method. ``exact`` will return the
- indices perfectly matching the dates given.
- ``before`` and ``after`` will return the indices
- corresponding to the dates just before or after
- the given dates if an exact match cannot be found.
- ``nearest`` will return the indices that
- correspond to the closest dates. Default ``exact``.
- ============== ====================================================
-
- Returns an index or a sequence of indices.
- """
- return netcdftime.date2index(dates, nctime, calendar=calendar, select=select)
-
def maskoceans(lonsin,latsin,datain,inlands=False):
"""
mask data (``datain``), defined on a grid with latitudes ``latsin``
Deleted: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdf.py
===================================================================
--- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdf.py 2011-02-12 13:54:34 UTC (rev 8976)
+++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdf.py 2011-02-12 13:56:44 UTC (rev 8977)
@@ -1,81 +0,0 @@
-from numpy import ma, squeeze
-from pupynere import netcdf_file, _unmaskandscale
-from dap.client import open as open_remote
-from dap.dtypes import ArrayType, GridType, typemap
-
-_typecodes = dict([[_v,_k] for _k,_v in typemap.items()])
-
-class _RemoteFile(object):
- """A NetCDF file reader. API is the same as Scientific.IO.NetCDF."""
-
- def __init__(self, file, maskandscale=False, cache=None,\
- username=None, password=None, verbose=False):
- self._buffer = open_remote(file,cache=cache,\
- username=username,password=password,verbose=verbose)
- self._maskandscale = maskandscale
- self._parse()
-
- def read(self, size=-1):
- """Alias for reading the file buffer."""
- return self._buffer.read(size)
-
- def _parse(self):
- """Initial parsing of the header."""
- # Read header info.
- self._dim_array()
- self._gatt_array()
- self._var_array()
-
- def _dim_array(self):
- """Read a dict with dimensions names and sizes."""
- self.dimensions = {}
- self._dims = []
- for k,d in self._buffer.iteritems():
- if (isinstance(d, ArrayType) or isinstance(d, GridType)) and len(d.shape) == 1 and k == d.dimensions[0]:
- name = k
- length = len(d)
- self.dimensions[name] = length
- self._dims.append(name) # preserve dim order
-
- def _gatt_array(self):
- """Read global attributes."""
- self.__dict__.update(self._buffer.attributes)
-
- def _var_array(self):
- """Read all variables."""
- # Read variables.
- self.variables = {}
- for k,d in self._buffer.iteritems():
- if isinstance(d, GridType) or isinstance(d, ArrayType):
- name = k
- self.variables[name] = _RemoteVariable(d,self._maskandscale)
-
- def close(self):
- # this is a no-op provided for compatibility
- pass
-
-class _RemoteVariable(object):
- def __init__(self, var, maskandscale):
- self._var = var
- self._maskandscale = maskandscale
- self.dtype = var.type
- self.shape = var.shape
- self.dimensions = var.dimensions
- self.__dict__.update(var.attributes)
-
- def __getitem__(self, index):
- datout = squeeze(self._var.__getitem__(index))
- # automatically
- # - remove singleton dimensions
- # - create a masked array using missing_value or _FillValue attribute
- # - apply scale_factor and add_offset to packed integer data
- if self._maskandscale:
- return _unmaskandscale(self,datout)
- else:
- return datout
-
- def __len__(self):
- return self.shape[0]
-
- def typecode(self):
- return _typecodes[self.dtype]
Deleted: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py
===================================================================
--- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py 2011-02-12 13:54:34 UTC (rev 8976)
+++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py 2011-02-12 13:56:44 UTC (rev 8977)
@@ -1,1050 +0,0 @@
-"""
-Performs conversions of netCDF time coordinate data to/from datetime objects.
-"""
-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.7.1'
-
-class datetime:
- """
-Phony datetime object which mimics the python datetime object,
-but allows for dates that don't exist in the proleptic gregorian calendar.
-Doesn't do timedelta operations, doesn't overload + and -.
-
-Has strftime, timetuple and __repr__ methods. The format
-of the string produced by __repr__ is controlled by self.format
-(default %Y-%m-%d %H:%M:%S).
-
-Instance variables are year,month,day,hour,minute,second,dayofwk,dayofyr
-and format.
- """
- def __init__(self,year,month,day,hour=0,minute=0,second=0,dayofwk=-1,dayofyr=1):
- """dayofyr set to 1 by default - otherwise time.strftime will complain"""
- self.year=year
- self.month=month
- self.day=day
- self.hour=hour
- self.minute=minute
- self.dayofwk=dayofwk
- self.dayofyr=dayofyr
- self.second=second
- self.format='%Y-%m-%d %H:%M:%S'
- def strftime(self,format=None):
- if format is None:
- format = self.format
- return _strftime(self,format)
- def timetuple(self):
- return (self.year,self.month,self.day,self.hour,self.minute,self.second,self.dayofwk,self.dayofyr,-1)
- def __repr__(self):
- return self.strftime(self.format)
-
-def JulianDayFromDate(date,calendar='standard'):
-
- """
-
-creates a Julian Day from a 'datetime-like' object. Returns the fractional
-Julian Day (resolution 1 second).
-
-if calendar='standard' or 'gregorian' (default), Julian day follows Julian
-Calendar on and before 1582-10-5, Gregorian calendar after 1582-10-15.
-
-if calendar='proleptic_gregorian', Julian Day follows gregorian calendar.
-
-if calendar='julian', Julian Day follows julian calendar.
-
-Algorithm:
-
-Meeus, Jean (1998) Astronomical Algorithms (2nd Edition). Willmann-Bell,
-Virginia. p. 63
-
- """
-
- # based on redate.py by David Finlayson.
-
- year=date.year; month=date.month; day=date.day
- hour=date.hour; minute=date.minute; second=date.second
- # Convert time to fractions of a day
- day = day + hour/24.0 + minute/1440.0 + second/86400.0
-
- # Start Meeus algorithm (variables are in his notation)
- if (month < 3):
- month = month + 12
- year = year - 1
-
- A = int(year/100)
-
- jd = int(365.25 * (year + 4716)) + int(30.6001 * (month + 1)) + \
- day - 1524.5
-
- # optionally adjust the jd for the switch from
- # the Julian to Gregorian Calendar
- # here assumed to have occurred the day after 1582 October 4
- if calendar in ['standard','gregorian']:
- if jd >= 2299170.5:
- # 1582 October 15 (Gregorian Calendar)
- B = 2 - A + int(A/4)
- elif jd < 2299160.5:
- # 1582 October 5 (Julian Calendar)
- B = 0
- else:
- raise ValueError, 'impossible date (falls in gap between end of Julian calendar and beginning of Gregorian calendar'
- elif calendar == 'proleptic_gregorian':
- B = 2 - A + int(A/4)
- elif calendar == 'julian':
- B = 0
- else:
- raise ValueError, 'unknown calendar, must be one of julian,standard,gregorian,proleptic_gregorian, got %s' % calendar
-
- # adjust for Julian calendar if necessary
- jd = jd + B
-
- return jd
-
-def _NoLeapDayFromDate(date):
-
- """
-
-creates a Julian Day for a calendar with no leap years from a datetime
-instance. Returns the fractional Julian Day (resolution 1 second).
-
- """
-
- year=date.year; month=date.month; day=date.day
- hour=date.hour; minute=date.minute; second=date.second
- # Convert time to fractions of a day
- day = day + hour/24.0 + minute/1440.0 + second/86400.0
-
- # Start Meeus algorithm (variables are in his notation)
- if (month < 3):
- month = month + 12
- year = year - 1
-
- jd = int(365. * (year + 4716)) + int(30.6001 * (month + 1)) + \
- day - 1524.5
-
- return jd
-
-def _AllLeapFromDate(date):
-
- """
-
-creates a Julian Day for a calendar where all years have 366 days from
-a 'datetime-like' object.
-Returns the fractional Julian Day (resolution 1 second).
-
- """
-
- year=date.year; month=date.month; day=date.day
- hour=date.hour; minute=date.minute; second=date.second
- # Convert time to fractions of a day
- day = day + hour/24.0 + minute/1440.0 + second/86400.0
-
- # Start Meeus algorithm (variables are in his notation)
- if (month < 3):
- month = month + 12
- year = year - 1
-
- jd = int(366. * (year + 4716)) + int(30.6001 * (month + 1)) + \
- day - 1524.5
-
- return jd
-
-def _360DayFromDate(date):
-
- """
-
-creates a Julian Day for a calendar where all months have 30 daysfrom
-a 'datetime-like' object.
-Returns the fractional Julian Day (resolution 1 second).
-
- """
-
- year=date.year; month=date.month; day=date.day
- hour=date.hour; minute=date.minute; second=date.second
- # Convert time to fractions of a day
- day = day + hour/24.0 + minute/1440.0 + second/86400.0
-
- jd = int(360. * (year + 4716)) + int(30. * (month - 1)) + day
-
- return jd
-
-def DateFromJulianDay(JD,calendar='standard'):
- """
-
-returns a 'datetime-like' object given Julian Day. Julian Day is a
-fractional day with a resolution of 1 second.
-
-if calendar='standard' or 'gregorian' (default), Julian day follows Julian
-Calendar on and before 1582-10-5, Gregorian calendar after 1582-10-15.
-
-if calendar='proleptic_gregorian', Julian Day follows gregorian calendar.
-
-if calendar='julian', Julian Day follows julian calendar.
-
-The datetime object is a 'real' datetime object if the date falls in
-the Gregorian calendar (i.e. calendar='proleptic_gregorian', or
-calendar = 'standard'/'gregorian' and the date is after 1582-10-15).
-Otherwise, it's a 'phony' datetime object which is actually an instance
-of netcdftime.datetime.
-
-
-Algorithm:
-
-Meeus, Jean (1998) Astronomical Algorithms (2nd Edition). Willmann-Bell,
-Virginia. p. 63
-
- """
-
- # based on redate.py by David Finlayson.
-
- if JD < 0:
- raise ValueError, 'Julian Day must be positive'
-
- dayofwk = int(math.fmod(int(JD + 1.5),7))
- (F, Z) = math.modf(JD + 0.5)
- Z = int(Z)
- if calendar in ['standard','gregorian']:
- if JD < 2299160.5:
- A = Z
- else:
- alpha = int((Z - 1867216.25)/36524.25)
- A = Z + 1 + alpha - int(alpha/4)
-
- elif calendar == 'proleptic_gregorian':
- alpha = int((Z - 1867216.25)/36524.25)
- A = Z + 1 + alpha - int(alpha/4)
- elif calendar == 'julian':
- A = Z
- else:
- raise ValueError, 'unknown calendar, must be one of julian,standard,gregorian,proleptic_gregorian, got %s' % calendar
-
- B = A + 1524
- C = int((B - 122.1)/365.25)
- D = int(365.25 * C)
- E = int((B - D)/30.6001)
-
- # Convert to date
- day = B - D - int(30.6001 * E) + F
- nday = B-D-123
- if nday <= 305:
- dayofyr = nday+60
- else:
- dayofyr = nday-305
- if E < 14:
- month = E - 1
- else:
- month = E - 13
-
- if month > 2:
- year = C - 4716
- else:
- year = C - 4715
-
- # a leap year?
- leap = 0
- if year % 4 == 0:
- leap = 1
- if calendar == 'proleptic_gregorian' or \
- (calendar in ['standard','gregorian'] and JD >= 2299160.5):
- if year % 100 == 0 and year % 400 != 0:
- print year % 100, year % 400
- leap = 0
- if leap and month > 2:
- dayofyr = dayofyr + leap
-
- # Convert fractions of a day to time
- (dfrac, days) = math.modf(day/1.0)
- (hfrac, hours) = math.modf(dfrac * 24.0)
- (mfrac, minutes) = math.modf(hfrac * 60.0)
- seconds = round(mfrac * 60.0) # seconds are rounded
-
- if seconds > 59:
- seconds = 0
- minutes = minutes + 1
- if minutes > 59:
- minutes = 0
- hours = hours + 1
- if hours > 23:
- hours = 0
- days = days + 1
-
- # return a 'real' datetime instance if calendar is gregorian.
- if calendar == 'proleptic_gregorian' or \
- (calendar in ['standard','gregorian'] and JD >= 2299160.5):
- return real_datetime(year,month,int(days),int(hours),int(minutes),int(seconds))
- else:
- # or else, return a 'datetime-like' instance.
- return datetime(year,month,int(days),int(hours),int(minutes),int(seconds),dayofwk,dayofyr)
-
-def _DateFromNoLeapDay(JD):
- """
-
-returns a 'datetime-like' object given Julian Day for a calendar with no leap
-days. Julian Day is a fractional day with a resolution of 1 second.
-
- """
-
- # based on redate.py by David Finlayson.
-
- if JD < 0:
- raise ValueError, 'Julian Day must be positive'
-
- dayofwk = int(math.fmod(int(JD + 1.5),7))
- (F, Z) = math.modf(JD + 0.5)
- Z = int(Z)
- A = Z
- B = A + 1524
- C = int((B - 122.1)/365.)
- D = int(365. * C)
- E = int((B - D)/30.6001)
-
- # Convert to date
- day = B - D - int(30.6001 * E) + F
- nday = B-D-123
- if nday <= 305:
- dayofyr = nday+60
- else:
- dayofyr = nday-305
- if E < 14:
- month = E - 1
- else:
- month = E - 13
-
- if month > 2:
- year = C - 4716
- else:
- year = C - 4715
-
- # Convert fractions of a day to time
- (dfrac, days) = math.modf(day/1.0)
- (hfrac, hours) = math.modf(dfrac * 24.0)
- (mfrac, minutes) = math.modf(hfrac * 60.0)
- seconds = round(mfrac * 60.0) # seconds are rounded
-
- if seconds > 59:
- seconds = 0
- minutes = minutes + 1
- if minutes > 59:
- minutes = 0
- hours = hours + 1
- if hours > 23:
- hours = 0
- days = days + 1
-
- return datetime(year,month,int(days),int(hours),int(minutes),int(seconds), dayofwk, dayofyr)
-
-def _DateFromAllLeap(JD):
- """
-
-returns a 'datetime-like' object given Julian Day for a calendar where all
-years have 366 days.
-Julian Day is a fractional day with a resolution of 1 second.
-
- """
-
- # based on redate.py by David Finlayson.
-
- if JD < 0:
- raise ValueError, 'Julian Day must be positive'
-
- dayofwk = int(math.fmod(int(JD + 1.5),7))
- (F, Z) = math.modf(JD + 0.5)
- Z = int(Z)
- A = Z
- B = A + 1524
- C = int((B - 122.1)/366.)
- D = int(366. * C)
- E = int((B - D)/30.6001)
-
- # Convert to date
- day = B - D - int(30.6001 * E) + F
- nday = B-D-123
- if nday <= 305:
- dayofyr = nday+60
- else:
- dayofyr = nday-305
- if E < 14:
- month = E - 1
- else:
- month = E - 13
- if month > 2:
- dayofyr = dayofyr+1
-
- if month > 2:
- year = C - 4716
- else:
- year = C - 4715
-
- # Convert fractions of a day to time
- (dfrac, days) = math.modf(day/1.0)
- (hfrac, hours) = math.modf(dfrac * 24.0)
- (mfrac, minutes) = math.modf(hfrac * 60.0)
- seconds = round(mfrac * 60.0) # seconds are rounded
-
- if seconds > 59:
- seconds = 0
- minutes = minutes + 1
- if minutes > 59:
- minutes = 0
- hours = hours + 1
- if hours > 23:
- hours = 0
- days = days + 1
-
- return datetime(year,month,int(days),int(hours),int(minutes),int(seconds), dayofwk, dayofyr)
-
-def _DateFrom360Day(JD):
- """
-
-returns a 'datetime-like' object given Julian Day for a calendar where all
-months have 30 days.
-Julian Day is a fractional day with a resolution of 1 second.
-
- """
-
- if JD < 0:
- raise ValueError, 'Julian Day must be positive'
-
- #jd = int(360. * (year + 4716)) + int(30. * (month - 1)) + day
- (F, Z) = math.modf(JD)
- year = int((Z-0.5)/360.) - 4716
- dayofyr = JD - (year+4716)*360
- month = int((dayofyr-0.5)/30)+1
- day = dayofyr - (month-1)*30 + F
-
- # Convert fractions of a day to time
- (dfrac, days) = math.modf(day/1.0)
- (hfrac, hours) = math.modf(dfrac * 24.0)
- (mfrac, minutes) = math.modf(hfrac * 60.0)
- seconds = round(mfrac * 60.0) # seconds are rounded
-
- if seconds > 59:
- seconds = 0
- minutes = minutes + 1
- if minutes > 59:
- minutes = 0
- hours = hours + 1
- if hours > 23:
- hours = 0
- days = days + 1
-
- return datetime(year,month,int(days),int(hours),int(minutes),int(seconds),-1, int(dayofyr))
-
-def _dateparse(timestr):
- """parse a string of the form time-units since yyyy-mm-dd hh:mm:ss
- return a tuple (units, datetimeinstance)"""
- timestr_split = timestr.split()
- units = timestr_split[0].lower()
- if units not in _units:
- raise ValueError,"units must be one of 'seconds', 'minutes', 'hours' or 'days' (or singular version of these), got '%s'" % units
- if timestr_split[1].lower() != 'since':
- raise ValueError,"no 'since' in unit_string"
- # parse the date string.
- n = timestr.find('since')+6
- year,month,day,hour,minute,second,utc_offset = _parse_date(timestr[n:])
- return units, utc_offset, datetime(year, month, day, hour, minute, second)
-
-class utime:
- """
-Performs conversions of netCDF time coordinate
-data to/from datetime objects.
-
-To initialize: C{t = utime(unit_string,calendar='standard')}
-
-where
-
-B{C{unit_string}} is a string of the form
-C{'time-units since <time-origin>'} defining the time units.
-
-Valid time-units are days, hours, minutes and seconds (the singular forms
-are also accepted). An example unit_string would be C{'hours
-since 0001-01-01 00:00:00'}.
-
-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://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):
-
-Mixed Gregorian/Julian calendar as defined by udunits.
-
-C{'proleptic_gregorian'}:
-
-A Gregorian calendar extended to dates before 1582-10-15. That is, a year
-is a leap year if either (i) it is divisible by 4 but not by 100 or (ii)
-it is divisible by 400.
-
-C{'noleap'} or C{'365_day'}:
-
-Gregorian calendar without leap years, i.e., all years are 365 days long.
-all_leap or 366_day Gregorian calendar with every year being a leap year,
-i.e., all years are 366 days long.
-
-C{'360_day'}:
-
-All years are 360 days divided into 30 day months.
-
-C{'julian'}:
-
-Proleptic Julian calendar, extended to dates after 1582-10-5. A year is a
-leap year if it is divisible by 4.
-
-The C{L{num2date}} and C{L{date2num}} class methods can used to convert datetime
-instances to/from the specified time units using the specified calendar.
-
-The datetime instances returned by C{num2date} are 'real' python datetime
-objects if the date falls in the Gregorian calendar (i.e.
-C{calendar='proleptic_gregorian', 'standard'} or C{'gregorian'} and
-the date is after 1582-10-15). Otherwise, they are 'phony' datetime
-objects which are actually instances of C{L{netcdftime.datetime}}. This is
-because the python datetime module cannot handle the weird dates in some
-calendars (such as C{'360_day'} and C{'all_leap'}) which don't exist in any real
-world calendar.
-
-
-Example usage:
-
->>> from netcdftime import utime
->>> from datetime import datetime
->>> cdftime = utime('hours since 0001-01-01 00:00:00')
->>> date = datetime.now()
->>> print date
-2006-03-17 16:04:02.561678
->>>
->>> t = cdftime.date2num(date)
->>> print t
-17577328.0672
->>>
->>> date = cdftime.num2date(t)
->>> print date
-2006-03-17 16:04:02
->>>
-
-The resolution of the transformation operation is 1 second.
-
-Warning: Dates between 1582-10-5 and 1582-10-15 do not exist in the
-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:
-
-"udunits implements the mixed Gregorian/Julian calendar system, as
-followed in England, in which dates prior to 1582-10-15 are assumed to use
-the Julian calendar. Other software cannot be relied upon to handle the
-change of calendar in the same way, so for robustness it is recommended
-that the reference date be later than 1582. If earlier dates must be used,
-it should be noted that udunits treats 0 AD as identical to 1 AD."
-
-@ivar origin: datetime instance defining the origin of the netCDF time variable.
-@ivar calendar: the calendar used (as specified by the C{calendar} keyword).
-@ivar unit_string: a string defining the the netCDF time variable.
-@ivar units: the units part of C{unit_string} (i.e. 'days', 'hours', 'seconds').
- """
- def __init__(self,unit_string,calendar='standard'):
- """
-@param unit_string: a string of the form
-C{'time-units since <time-origin>'} defining the time units.
-
-Valid time-units are days, hours, minutes and seconds (the singular forms
-are also accepted). An example unit_string would be C{'hours
-since 0001-01-01 00:00:00'}.
-
-@keyword 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/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):
- Mixed Gregorian/Julian calendar as defined by udunits.
- - C{'proleptic_gregorian'}:
- A Gregorian calendar extended to dates before 1582-10-15. That is, a year
- is a leap year if either (i) it is divisible by 4 but not by 100 or (ii)
- it is divisible by 400.
- - C{'noleap'} or C{'365_day'}:
- Gregorian calendar without leap years, i.e., all years are 365 days long.
- - C{'all_leap'} or C{'366_day'}:
- Gregorian calendar with every year being a leap year, i.e.,
- all years are 366 days long.
- -C{'360_day'}:
- All years are 360 days divided into 30 day months.
- -C{'julian'}:
- Proleptic Julian calendar, extended to dates after 1582-10-5. A year is a
- leap year if it is divisible by 4.
-
-@returns: A class instance which may be used for converting times from netCDF
-units to datetime objects.
- """
- if calendar in _calendars:
- self.calendar = calendar
- else:
- raise ValueError, "calendar must be one of %s, got '%s'" % (str(_calendars),calendar)
- units, tzoffset, self.origin = _dateparse(unit_string)
- self.tzoffset = tzoffset # time zone offset in minutes
- self.units = units
- self.unit_string = unit_string
- if self.calendar in ['noleap','365_day'] and self.origin.month == 2 and self.origin.day == 29:
- raise ValueError, 'cannot specify a leap day as the reference time with the noleap calendar'
- if self.calendar == '360_day' and self.origin.day > 30:
- raise ValueError, 'there are only 30 days in every month with the 360_day calendar'
- if self.calendar in ['noleap','365_day']:
- self._jd0 = _NoLeapDayFromDate(self.origin)
- elif self.calendar in ['all_leap','366_day']:
- self._jd0 = _AllLeapFromDate(self.origin)
- elif self.calendar == '360_day':
- self._jd0 = _360DayFromDate(self.origin)
- else:
- self._jd0 = JulianDayFromDate(self.origin,calendar=self.calendar)
-
- def date2num(self,date):
- """
-Returns C{time_value} in units described by L{unit_string}, using
-the specified L{calendar}, given a 'datetime-like' object.
-
-The datetime object must represent UTC with no time-zone offset.
-If there is a time-zone offset implied by L{unit_string}, it will
-be applied to the returned numeric values.
-
-Resolution is 1 second.
-
-If C{calendar = 'standard'} or C{'gregorian'} (indicating
-that the mixed Julian/Gregorian calendar is to be used), an
-exception will be raised if the 'datetime-like' object describes
-a date between 1582-10-5 and 1582-10-15.
-
-Works for scalars, sequences and numpy arrays.
-Returns a scalar if input is a scalar, else returns a numpy array.
- """
- isscalar = False
- try:
- date[0]
- except:
- isscalar = True
- if not isscalar:
- date = numpy.array(date)
- shape = date.shape
- if self.calendar in ['julian','standard','gregorian','proleptic_gregorian']:
- if isscalar:
- jdelta = JulianDayFromDate(date,self.calendar)-self._jd0
- else:
- jdelta = [JulianDayFromDate(d,self.calendar)-self._jd0 for d in date.flat]
- elif self.calendar in ['noleap','365_day']:
- if date.month == 2 and date.day == 29:
- raise ValueError, 'there is no leap day in the noleap calendar'
- if isscalar:
- jdelta = _NoLeapDayFromDate(date) - self._jd0
- else:
- jdelta = [_NoLeapDayFromDate(d)-self._jd0 for d in date.flat]
- elif self.calendar in ['all_leap','366_day']:
- if isscalar:
- jdelta = _AllLeapFromDate(date) - self._jd0
- else:
- jdelta = [_AllLeapFromDate(d)-self._jd0 for d in date.flat]
- elif self.calendar == '360_day':
- if self.calendar == '360_day' and date.day > 30:
- raise ValueError, 'there are only 30 days in every month with the 360_day calendar'
- if isscalar:
- jdelta = _360DayFromDate(date) - self._jd0
- else:
- jdelta = [_360DayFromDate(d)-self._jd0 for d in date.flat]
- if not isscalar:
- jdelta = numpy.array(jdelta)
- # convert to desired units, add time zone offset.
- if self.units in ['second','seconds']:
- jdelta = jdelta*86400. + self.tzoffset*60.
- elif self.units in ['minute','minutes']:
- jdelta = jdelta*1440. + self.tzoffset
- elif self.units in ['hour','hours']:
- jdelta = jdelta*24. + self.tzoffset/60.
- elif self.units in ['day','days']:
- jdelta = jdelta + self.tzoffset/1440.
- if isscalar:
- return jdelta
- else:
- return numpy.reshape(jdelta,shape)
-
- def num2date(self,time_value):
- """
-Return a 'datetime-like' object given a C{time_value} in units
-described by L{unit_string}, using L{calendar}.
-
-dates are in UTC with no offset, even if L{unit_string} contains
-a time zone offset from UTC.
-
-Resolution is 1 second.
-
-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.
-C{calendar='proleptic_gregorian'}, or C{calendar = 'standard'/'gregorian'} and
-the date is after 1582-10-15). Otherwise, they are 'phony' datetime
-objects which are actually instances of netcdftime.datetime. This is
-because the python datetime module cannot handle the weird dates in some
-calendars (such as C{'360_day'} and C{'all_leap'}) which
-do not exist in any real world calendar.
- """
- isscalar = False
- try:
- time_value[0]
- except:
- isscalar = True
- if not isscalar:
- 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']:
- jdelta = time_value/86400. - self.tzoffset/1440.
- elif self.units in ['minute','minutes']:
- jdelta = time_value/1440. - self.tzoffset/1440.
- elif self.units in ['hour','hours']:
- jdelta = time_value/24. - self.tzoffset/1440.
- elif self.units in ['day','days']:
- jdelta = time_value - self.tzoffset/1440.
- jd = self._jd0 + jdelta
- if self.calendar in ['julian','standard','gregorian','proleptic_gregorian']:
- if not isscalar:
- date = [DateFromJulianDay(j,self.calendar) for j in jd.flat]
- else:
- date = DateFromJulianDay(jd,self.calendar)
- elif self.calendar in ['noleap','365_day']:
- if not isscalar:
- date = [_DateFromNoLeapDay(j) for j in jd.flat]
- else:
- date = _DateFromNoLeapDay(jd)
- elif self.calendar in ['all_leap','366_day']:
- if not isscalar:
- date = [_DateFromAllLeap(j) for j in jd.flat]
- else:
- date = _DateFromAllLeap(jd)
- elif self.calendar == '360_day':
- if not isscalar:
- date = [_DateFrom360Day(j) for j in jd.flat]
- else:
- date = _DateFrom360Day(jd)
- if isscalar:
- return date
- else:
- return numpy.reshape(numpy.array(date),shape)
-
-def _parse_date(origin):
- """Parses a date string and returns a tuple
- (year,month,day,hour,minute,second,utc_offset).
- utc_offset is in minutes.
-
- This function parses the 'origin' part of the time unit. It should be
- something like::
-
- 2004-11-03 14:42:27.0 +2:00
-
- Lots of things are optional; just the date is mandatory.
-
- by Roberto De Almeida
-
- excerpted from coards.py - http://cheeseshop.python.org/pypi/coards/
- """
- # yyyy-mm-dd [hh:mm:ss[.s][ [+-]hh[:][mm]]]
- p = re.compile( r'''(?P<year>\d{1,4}) # yyyy
- - #
- (?P<month>\d{1,2}) # mm or m
- - #
- (?P<day>\d{1,2}) # dd or d
- #
- (?: # [optional time and timezone]
- \s #
- (?P<hour>\d{1,2}) # hh or h
- : #
- (?P<min>\d{1,2}) # mm or m
- (?:
- \:
- (?P<sec>\d{1,2}) # ss or s (optional)
- )?
- #
- (?: # [optional decisecond]
- \. # .
- (?P<dsec>\d) # s
- )? #
- (?: # [optional timezone]
- \s #
- (?P<ho>[+-]? # [+ or -]
- \d{1,2}) # hh or h
- :? # [:]
- (?P<mo>\d{2})? # [mm]
- )? #
- )? #
- $ # EOL
- ''', re.VERBOSE)
-
- m = p.match(origin.strip())
- if m:
- c = m.groupdict(0)
- # UTC offset.
- offset = int(c['ho'])*60 + int(c['mo'])
- return int(c['year']),int(c['month']),int(c['day']),int(c['hour']),int(c['min']),int(c['sec']),offset
-
- raise Exception('Invalid date origin: %s' % origin)
-
-# remove the unsupposed "%s" command. But don't
-# do it if there's an even number of %s before the s
-# because those are all escaped. Can't simply
-# remove the s because the result of
-# %sY
-# should be %Y if %s isn't supported, not the
-# 4 digit year.
-_illegal_s = re.compile(r"((^|[^%])(%%)*%s)")
-
-def _findall(text, substr):
- # Also finds overlaps
- sites = []
- i = 0
- while 1:
- j = text.find(substr, i)
- if j == -1:
- break
- sites.append(j)
- i=j+1
- return sites
-
-# Every 28 years the calendar repeats, except through century leap
-# years where it's 6 years. But only if you're using the Gregorian
-# calendar. ;)
-
-def _strftime(dt, fmt):
- if _illegal_s.search(fmt):
- raise TypeError("This strftime implementation does not handle %s")
- # don't use strftime method at all.
- #if dt.year > 1900:
- # return dt.strftime(fmt)
-
- year = dt.year
- # For every non-leap year century, advance by
- # 6 years to get into the 28-year repeat cycle
- delta = 2000 - year
- off = 6*(delta // 100 + delta // 400)
- year = year + off
-
- # Move to around the year 2000
- year = year + ((2000 - year)//28)*28
- timetuple = dt.timetuple()
- s1 = time.strftime(fmt, (year,) + timetuple[1:])
- sites1 = _findall(s1, str(year))
-
- s2 = time.strftime(fmt, (year+28,) + timetuple[1:])
- sites2 = _findall(s2, str(year+28))
-
- sites = []
- for site in sites1:
- if site in sites2:
- sites.append(site)
-
- s = s1
- syear = "%4d" % (dt.year,)
- 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):
- """Return True if the time indices given correspond to the given dates,
- False otherwise.
-
- Parameters:
-
- indices : sequence of integers
- Positive integers indexing the time variable.
-
- dates : sequence of datetime objects
- Reference dates.
-
- nctime : netCDF Variable object
- NetCDF time object.
-
- calendar : string
- Calendar of nctime.
- """
- if (indices <0).any():
- return False
-
- if (indices >= nctime.shape[0]).any():
- return False
-
-# t = nctime[indices]
-# fancy indexing not available, fall back on this.
- t=[]
- for ind in indices:
- t.append(nctime[ind])
- return numpy.all( num2date(t, nctime.units, calendar) == dates)
-
-
-def date2index(dates, nctime, calendar=None, select='exact'):
- """
- date2index(dates, nctime, calendar=None, select='exact')
-
- 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. The entries are assumed to be stored in increasing
- order.
-
- @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.
-
- @param select: C{'exact', 'before', 'after', 'nearest'}
- The index selection method. C{exact} will return the indices perfectly
- matching the dates given. C{before} and C{after} will return the indices
- corresponding to the dates just before or just after the given dates if
- an exact match cannot be found. C{nearest} will return the indices that
- correpond to the closest dates.
- """
- # Setting the calendar.
-
- if calendar == None:
- calendar = getattr(nctime, 'calendar', 'standard')
-
- num = numpy.atleast_1d(date2num(dates, nctime.units, calendar))
-
- # Trying to infer the correct index from the starting time and the stride.
- # This assumes that the times are increasing uniformly.
- t0, t1 = nctime[:2]
- dt = t1 - t0
- index = numpy.array((num-t0)/dt, int)
-
- # Checking that the index really corresponds to the given date.
- # If the times do not correspond, then it means that the times
- # are not increasing uniformly and we try the bisection method.
- if not _check_index(index, dates, nctime, calendar):
-
- # Use the bisection method. Assumes the dates are ordered.
- import bisect
-
- index = numpy.array([bisect.bisect_left(nctime, n) for n in num], int)
-
- # Find the dates for which the match is not perfect.
- # Use list comprehension instead of the simpler `nctime[index]` since
- # not all time objects support numpy integer indexing (eg dap).
- ncnum = numpy.squeeze([nctime[i] for i in index])
- mismatch = numpy.nonzero(ncnum != num)[0]
-
- if select == 'exact':
- if len(mismatch) > 0:
- raise ValueError, 'Some dates not found.'
-
- elif select == 'before':
- index[mismatch] -= 1
-
- elif select == 'after':
- pass
-
- elif select == 'nearest':
- nearest_to_left = num[mismatch] < numpy.array( [nctime[i-1] + nctime[i] for i in index[mismatch]]) / 2.
- index[mismatch] = index[mismatch] - 1 * nearest_to_left
-
- else:
- raise ValueError("%s is not an option for the `select` argument."%select)
-
- # convert numpy scalars or single element arrays to python ints.
- return _toscalar(index)
-
-
-def _toscalar(a):
- if a.shape in [(),(1,)]:
- return a.item()
- else:
- return a
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|