Skip to content

Commit

Permalink
enable datetime find_nearest)
Browse files Browse the repository at this point in the history
  • Loading branch information
scivision committed May 24, 2017
1 parent 46fd5ef commit 639a715
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 28 deletions.
6 changes: 5 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ Date conversions used in the sciences.

Install
=======
::
from PyPi::

pip install sciencedates
or from this repo::

python setup.py develop

Examples
========
Expand Down
43 changes: 22 additions & 21 deletions sciencedates/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import division
from datetime import timedelta,datetime, time
from pytz import UTC
from numpy import atleast_1d, empty_like, atleast_2d,nan,empty,datetime64,ndarray,asarray,absolute,asanyarray,nanargmin, isnan
import numpy as np
from dateutil.parser import parse
from xarray import DataArray
#
Expand All @@ -18,10 +18,10 @@ def datetime2yd(T):
utsec: seconds from midnight utc
"""
T = forceutc(T)
T = atleast_1d(T)
T = np.atleast_1d(T)

utsec=empty_like(T,dtype=float)
yd = empty_like(T,dtype=int)
utsec= np.empty_like(T, float)
yd = np.empty_like(T, int)
for i,t in enumerate(T):
utsec[i] = dt2utsec(t)
yd[i] = t.year*1000 + int(t.strftime('%j'))
Expand Down Expand Up @@ -51,7 +51,7 @@ def yd2datetime(yd,utsec=None):
return dt


def datetime2gtd(T,glon=nan):
def datetime2gtd(T, glon=np.nan):
"""
Inputs:
T: Numpy 1-D array of datetime.datetime OR string suitable for dateutil.parser.parse
Expand All @@ -62,10 +62,11 @@ def datetime2gtd(T,glon=nan):
utsec: seconds from midnight utc
stl: local solar time
"""
T = atleast_1d(T); glon=atleast_2d(glon)
iyd=empty_like(T,dtype=int)
utsec=empty_like(T,dtype=float)
stl = empty((T.size,glon.shape[0],glon.shape[1]))
T = np.atleast_1d(T)
glon= np.atleast_2d(glon)
iyd= np.empty_like(T, int)
utsec=np.empty_like(T, float)
stl = np.empty((T.size, glon.shape[0], glon.shape[1]))

for i,t in enumerate(T):
t = forceutc(t)
Expand Down Expand Up @@ -98,12 +99,12 @@ def forceutc(t):
#%% polymorph to datetime
if isinstance(t,str):
t = parse(t)
elif isinstance(t,datetime64):
elif isinstance(t, np.datetime64):
t=t.astype('M8[ms]').astype('O') #for Numpy 1.10 at least...
elif isinstance(t,datetime):
pass
elif isinstance(t,(ndarray,list,tuple)):
return asarray([forceutc(T) for T in t])
elif isinstance(t,(np.ndarray,list,tuple)):
return np.asarray([forceutc(T) for T in t])
else:
raise TypeError('datetime only input')
#%% enforce UTC on datetime
Expand Down Expand Up @@ -184,32 +185,32 @@ def find_nearest(x,x0):
http://stackoverflow.com/questions/2566412/find-nearest-value-in-numpy-array
"""
x = asanyarray(x) #for indexing upon return
x0 = atleast_1d(x0)
x = np.asanyarray(x) #for indexing upon return
x0 = np.atleast_1d(x0)
#%%
if x.size==0 or x0.size==0:
raise ValueError('empty input(s)')

assert x0.ndim in (0,1),'2-D x0 not handled yet'
#%%
ind = empty_like(x0,dtype=int)
ind = np.empty_like(x0,dtype=int)

# NOTE: not trapping IndexError (all-nan) becaues returning None can surprise with slice indexing
for i,xi in enumerate(x0):
if xi is None or isnan(xi):
raise ValueError('x0 must NOT be None or NaN to avoid surprising None return value')
if xi is not None and (isinstance(xi,datetime) or np.isfinite(xi)):
ind[i] = np.nanargmin(abs(x-xi))
else:
ind[i] = nanargmin(absolute(x-xi))
raise ValueError('x0 must NOT be None or NaN to avoid surprising None return value')

return ind.squeeze()[()], x[ind].squeeze()[()] # [()] to pop scalar from 0d array while being OK with ndim>0

def INCORRECTRESULT_using_bisect(x,X0): #pragma: no cover
X0 = atleast_1d(X0)
X0 = np.atleast_1d(X0)
x.sort()
ind = [bisect(x,x0) for x0 in X0]

x = asanyarray(x)
return asanyarray(ind),x[ind]
x = np.asanyarray(x)
return np.asanyarray(ind),x[ind]

if __name__ == '__main__':
from bisect import bisect
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

setup(name='sciencedates',
packages=['sciencedates'],
version = '1.2.4',
version = '1.2.5',
description='Date conversions used in the sciences.',
author = 'Michael Hirsch, Ph.D.',
url = 'https://github.com/scivision/sciencedates',
Expand Down
14 changes: 9 additions & 5 deletions tests/test.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
from datetime import datetime
from pytz import timezone, UTC
from numpy.testing import run_module_suite,assert_allclose,assert_almost_equal
from numpy.testing import run_module_suite,assert_allclose,assert_equal
#
import sciencedates as sd

Expand Down Expand Up @@ -36,12 +36,16 @@ def test_gtd():
assert iyd[0]==183
assert_allclose(utsec[0],43200)
assert_allclose(stl[0],14.8)


def test_findnearest():
indf,xf = sd.find_nearest([10,15,12,20,14,33],[32,12.01])
assert_almost_equal(indf,[5,2])
assert_almost_equal(xf,[33.,12.])
assert_allclose(indf,[5,2])
assert_allclose(xf,[33.,12.])

indf,xf = sd.find_nearest((datetime(2012,1,1,12), datetime(2012,1,1,11)), datetime(2012,1,1,11,30))
assert_equal(indf,0)
assert_equal(xf,datetime(2012,1,1,12))

if __name__ == '__main__':
run_module_suite()

0 comments on commit 639a715

Please sign in to comment.