## SF.net SVN: matplotlib:[7707] trunk/toolkits/basemap/lib/mpl_toolkits/ basemap/netcdftime.py

 SF.net SVN: matplotlib:[7707] trunk/toolkits/basemap/lib/mpl_toolkits/ basemap/netcdftime.py From: - 2009-09-08 12:06:43 ```Revision: 7707 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7707&view=rev Author: jswhit Date: 2009-09-08 12:06:35 +0000 (Tue, 08 Sep 2009) Log Message: ----------- update to latest version from netcdf4-python Modified Paths: -------------- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py =================================================================== --- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py 2009-09-08 01:53:12 UTC (rev 7706) +++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py 2009-09-08 12:06:35 UTC (rev 7707) @@ -934,18 +934,38 @@ 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 = numpy.empty(len(indices), nctime.dtype) - for n,i in enumerate(indices): - t[n] = nctime[i] - assert numpy.all( num2date(t, nctime.units, calendar) == dates) + """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. -def date2index(dates, nctime, calendar=None): + 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] + return numpy.all( num2date(t, nctime.units, calendar) == dates) + + + +def date2index(dates, nctime, calendar=None, select='exact'): """ - date2index(dates, nctime, calendar=None) + date2index(dates, nctime, calendar=None, select='exact') Return indices of a netCDF time variable corresponding to the given dates. @@ -953,7 +973,8 @@ 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. + 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' @@ -961,32 +982,54 @@ 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 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 + # 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. - _check_index(index, dates, nctime, calendar) - - except AssertionError: - - # If check fails, use brute force method. - index[:] = numpy.digitize(num, nctime[:]) - 1 - - # Perform check again. - _check_index(index, dates, nctime, calendar) - + # 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) + + nomatch = num2date(nctime[index], nctime.units) != dates + + if select == 'exact': + if not (num2date(nctime[index], nctime.units) == dates).all(): + raise ValueError, 'Dates not found.' + + elif select == 'before': + index[nomatch] -= 1 + + elif select == 'after': + pass + + elif select == 'nearest': + index[nomatch] = index[nomatch] - 1 * ( num[nomatch] < (nctime[index[nomatch]-1] + nctime[index[nomatch]]) / 2. ) + + else: + raise ValueError, select + # convert numpy scalars or single element arrays to python ints. index = _toscalar(index) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ```

 SF.net SVN: matplotlib:[6836] trunk/toolkits/basemap/lib/mpl_toolkits/ basemap/netcdftime.py From: - 2009-01-26 22:49:05 ```Revision: 6836 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6836&view=rev Author: jswhit Date: 2009-01-26 22:49:01 +0000 (Mon, 26 Jan 2009) Log Message: ----------- bugfixes for date2index Modified Paths: -------------- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py =================================================================== --- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py 2009-01-26 20:27:50 UTC (rev 6835) +++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py 2009-01-26 22:49:01 UTC (rev 6836) @@ -7,7 +7,7 @@ _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' +__version__ = '0.7.1' class datetime: """ @@ -975,22 +975,29 @@ 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() + index = _toscalar(index) # Checking that the index really corresponds to the given date. _check_index(index, dates, nctime, calendar) except AssertionError: + + index = numpy.empty(numpy.alen(dates), int) + # 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() + index = _toscalar(index) # Perform check again. _check_index(index, dates, nctime, calendar) return 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. ```
 SF.net SVN: matplotlib:[6843] trunk/toolkits/basemap/lib/mpl_toolkits/ basemap/netcdftime.py From: - 2009-01-27 17:41:36 ```Revision: 6843 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6843&view=rev Author: jswhit Date: 2009-01-27 17:41:33 +0000 (Tue, 27 Jan 2009) Log Message: ----------- don't use fancy indexing in date2index (won't work for opendap datasets) Modified Paths: -------------- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py =================================================================== --- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py 2009-01-27 12:34:49 UTC (rev 6842) +++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py 2009-01-27 17:41:33 UTC (rev 6843) @@ -937,7 +937,9 @@ def _check_index(indices, dates, nctime, calendar): """Assert that the time indices given correspond to the given dates.""" - t = nctime[indices] + t = numpy.empty(len(indices), nctime.dtype) + for n,i in enumerate(indices): + t[n] = nctime[i] assert numpy.all( num2date(t, nctime.units, calendar) == dates) @@ -974,25 +976,20 @@ dt = t1 - t0 index[:] = (num-t0)/dt - # convert numpy scalars or single element arrays to python ints. - index = _toscalar(index) - # Checking that the index really corresponds to the given date. _check_index(index, dates, nctime, calendar) except AssertionError: - index = numpy.empty(numpy.alen(dates), int) - # If check fails, use brute force method. index[:] = numpy.digitize(num, nctime[:]) - 1 - # convert numpy scalars or single element arrays to python ints. - index = _toscalar(index) - # Perform check again. _check_index(index, dates, nctime, calendar) + # convert numpy scalars or single element arrays to python ints. + index = _toscalar(index) + return index This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ```
 SF.net SVN: matplotlib:[7707] trunk/toolkits/basemap/lib/mpl_toolkits/ basemap/netcdftime.py From: - 2009-09-08 12:06:43 ```Revision: 7707 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7707&view=rev Author: jswhit Date: 2009-09-08 12:06:35 +0000 (Tue, 08 Sep 2009) Log Message: ----------- update to latest version from netcdf4-python Modified Paths: -------------- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py =================================================================== --- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py 2009-09-08 01:53:12 UTC (rev 7706) +++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py 2009-09-08 12:06:35 UTC (rev 7707) @@ -934,18 +934,38 @@ 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 = numpy.empty(len(indices), nctime.dtype) - for n,i in enumerate(indices): - t[n] = nctime[i] - assert numpy.all( num2date(t, nctime.units, calendar) == dates) + """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. -def date2index(dates, nctime, calendar=None): + 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] + return numpy.all( num2date(t, nctime.units, calendar) == dates) + + + +def date2index(dates, nctime, calendar=None, select='exact'): """ - date2index(dates, nctime, calendar=None) + date2index(dates, nctime, calendar=None, select='exact') Return indices of a netCDF time variable corresponding to the given dates. @@ -953,7 +973,8 @@ 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. + 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' @@ -961,32 +982,54 @@ 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 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 + # 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. - _check_index(index, dates, nctime, calendar) - - except AssertionError: - - # If check fails, use brute force method. - index[:] = numpy.digitize(num, nctime[:]) - 1 - - # Perform check again. - _check_index(index, dates, nctime, calendar) - + # 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) + + nomatch = num2date(nctime[index], nctime.units) != dates + + if select == 'exact': + if not (num2date(nctime[index], nctime.units) == dates).all(): + raise ValueError, 'Dates not found.' + + elif select == 'before': + index[nomatch] -= 1 + + elif select == 'after': + pass + + elif select == 'nearest': + index[nomatch] = index[nomatch] - 1 * ( num[nomatch] < (nctime[index[nomatch]-1] + nctime[index[nomatch]]) / 2. ) + + else: + raise ValueError, select + # convert numpy scalars or single element arrays to python ints. index = _toscalar(index) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ```
 SF.net SVN: matplotlib:[7717] trunk/toolkits/basemap/lib/mpl_toolkits/ basemap/netcdftime.py From: - 2009-09-08 17:19:04 ```Revision: 7717 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7717&view=rev Author: jswhit Date: 2009-09-08 17:18:53 +0000 (Tue, 08 Sep 2009) Log Message: ----------- adjust netcdftime since fancy indexing doesn't work in pupynere. Modified Paths: -------------- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py =================================================================== --- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py 2009-09-08 16:48:12 UTC (rev 7716) +++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py 2009-09-08 17:18:53 UTC (rev 7717) @@ -958,7 +958,11 @@ if (indices >= nctime.shape[0]).any(): return False - t = nctime[indices] +# 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) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ```
 SF.net SVN: matplotlib:[7731] trunk/toolkits/basemap/lib/mpl_toolkits/ basemap/netcdftime.py From: - 2009-09-10 11:36:24 ```Revision: 7731 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7731&view=rev Author: jswhit Date: 2009-09-10 11:36:16 +0000 (Thu, 10 Sep 2009) Log Message: ----------- fixes for date2index from David Huard Modified Paths: -------------- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py =================================================================== --- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py 2009-09-10 08:15:48 UTC (rev 7730) +++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/netcdftime.py 2009-09-10 11:36:16 UTC (rev 7731) @@ -966,42 +966,42 @@ 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 + 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. + 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 is None: + + 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. + # This assumes that the times are increasing uniformly. t0, t1 = nctime[:2] dt = t1 - t0 index = numpy.array((num-t0)/dt, int) @@ -1010,36 +1010,39 @@ # 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) - - nomatch = num2date(nctime[index], nctime.units) != dates - + + # 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 not (num2date(nctime[index], nctime.units) == dates).all(): - raise ValueError, 'Dates not found.' - + if len(mismatch) > 0: + raise ValueError, 'Some dates not found.' + elif select == 'before': - index[nomatch] -= 1 - + index[mismatch] -= 1 + elif select == 'after': pass - + elif select == 'nearest': - index[nomatch] = index[nomatch] - 1 * ( num[nomatch] < (nctime[index[nomatch]-1] + nctime[index[nomatch]]) / 2. ) - + 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, select - + raise ValueError("%s is not an option for the `select` argument."%select) + # convert numpy scalars or single element arrays to python ints. - index = _toscalar(index) + return _toscalar(index) - return index - def _toscalar(a): if a.shape in [(),(1,)]: return a.item() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ```