Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

WIP toward getting flake8 to pass; Merge branch 'pep8'

  • Loading branch information...
commit a88198ea11d338c1cae8bf19fa9ff412741b5073 2 parents 1d380bd + ee250d7
@kwgoodman authored
Showing with 46,935 additions and 16,931 deletions.
  1. +3 −2 bottleneck/benchmark/autotimeit.py
  2. +56 −52 bottleneck/benchmark/bench.py
  3. +44 −17 bottleneck/slow/func.py
  4. +107 −75 bottleneck/slow/move.py
  5. +27,741 −8,762 bottleneck/src/func/func.c
  6. +18,250 −7,394 bottleneck/src/move/move.c
  7. +9 −9 bottleneck/src/template/func/allnan.py
  8. +10 −10 bottleneck/src/template/func/anynan.py
  9. +16 −16 bottleneck/src/template/func/argpartsort.py
  10. +4 −3 bottleneck/src/template/func/func.py
  11. +22 −22 bottleneck/src/template/func/median.py
  12. +14 −14 bottleneck/src/template/func/nanargmax.py
  13. +15 −15 bottleneck/src/template/func/nanargmin.py
  14. +21 −21 bottleneck/src/template/func/nanmax.py
  15. +19 −19 bottleneck/src/template/func/nanmean.py
  16. +29 −29 bottleneck/src/template/func/nanmedian.py
  17. +20 −20 bottleneck/src/template/func/nanmin.py
  18. +17 −17 bottleneck/src/template/func/nanrankdata.py
  19. +24 −24 bottleneck/src/template/func/nanstd.py
  20. +16 −16 bottleneck/src/template/func/nansum.py
  21. +26 −26 bottleneck/src/template/func/nanvar.py
  22. +12 −12 bottleneck/src/template/func/nn.py
  23. +18 −18 bottleneck/src/template/func/partsort.py
  24. +19 −19 bottleneck/src/template/func/rankdata.py
  25. +11 −11 bottleneck/src/template/func/replace.py
  26. +11 −11 bottleneck/src/template/func/ss.py
  27. +1 −0  bottleneck/src/template/move/move.py
  28. +26 −26 bottleneck/src/template/move/move_max.py
  29. +13 −13 bottleneck/src/template/move/move_mean.py
  30. +18 −18 bottleneck/src/template/move/move_median.py
  31. +26 −26 bottleneck/src/template/move/move_min.py
  32. +25 −25 bottleneck/src/template/move/move_nanmax.py
  33. +11 −11 bottleneck/src/template/move/move_nanmean.py
  34. +26 −26 bottleneck/src/template/move/move_nanmin.py
  35. +13 −13 bottleneck/src/template/move/move_nanstd.py
  36. +11 −11 bottleneck/src/template/move/move_nansum.py
  37. +15 −15 bottleneck/src/template/move/move_std.py
  38. +14 −14 bottleneck/src/template/move/move_sum.py
  39. +35 −28 bottleneck/src/template/template.py
  40. +31 −2 bottleneck/tests/fast_test.py
  41. +35 −12 bottleneck/tests/func_test.py
  42. +8 −6 bottleneck/tests/input_modifcation_test.py
  43. +36 −6 bottleneck/tests/list_input_test.py
  44. +19 −5 bottleneck/tests/move_test.py
  45. +4 −4 sandbox/setup.py
  46. +34 −36 setup.py
View
5 bottleneck/benchmark/autotimeit.py
@@ -1,18 +1,19 @@
import timeit
+
def autotimeit(stmt, setup='pass', repeat=3, mintime=0.2):
timer = timeit.Timer(stmt, setup)
number, time1 = autoscaler(timer, mintime)
time2 = timer.repeat(repeat=repeat-1, number=number)
return min(time2 + [time1]) / number
+
def autoscaler(timer, mintime):
number = 1
for i in range(12):
time = timer.timeit(number)
if time > mintime:
- return number, time
+ return number, time
number *= 10
raise RuntimeError('function is too fast to test')
-
View
108 bottleneck/benchmark/bench.py
@@ -10,7 +10,8 @@
def bench(mode='fast', dtype='float64', axis=1,
- shapes=[(10,10),(100,100),(1000,1000),(10,10),(100,100),(1000,1000)],
+ shapes=[(10, 10), (100, 100), (1000, 1000), (10, 10), (100, 100),
+ (1000, 1000)],
nans=[False, False, False, True, True, True]):
"""
Bottleneck benchmark.
@@ -39,7 +40,7 @@ def bench(mode='fast', dtype='float64', axis=1,
A benchmark report is printed to stdout.
"""
-
+
try:
import scipy as sp
SCIPY = True
@@ -64,12 +65,12 @@ def bench(mode='fast', dtype='float64', axis=1,
print("%sScipy (sp) Cannot import, skipping scipy benchmarks" % tab)
print("%sSpeed is NumPy or SciPy time divided by Bottleneck time" % tab)
tup = (tab, dtype, axis)
- print("%sNaN means one-third NaNs; %s and axis=%s are used" % tup )
+ print("%sNaN means one-third NaNs; %s and axis=%s are used" % tup)
if mode == 'fast':
print("%sHigh-level functions used (mode='fast')" % tab)
- elif mode == 'faster':
+ elif mode == 'faster':
print("%sLow-level functions used (mode='faster')" % tab)
-
+
print('')
header = [" "*14]
for nan in nans:
@@ -97,6 +98,7 @@ def bench(mode='fast', dtype='float64', axis=1,
for test in suite:
print("%s%s" % (test["name"].ljust(15), test['ref']))
+
def timer(statements, setups):
speed = []
if len(statements) != 2:
@@ -108,6 +110,7 @@ def timer(statements, setups):
speed.append(t1 / t0)
return speed
+
def getarray(shape, dtype, nans=False):
arr = np.arange(np.prod(shape), dtype=dtype)
if nans and issubclass(arr.dtype.type, np.inexact):
@@ -116,14 +119,15 @@ def getarray(shape, dtype, nans=False):
rs = np.random.RandomState(shape)
rs.shuffle(arr)
return arr.reshape(*shape)
-
+
+
def benchsuite(mode, shapes, dtype, axis, nans):
if mode not in ('fast', 'faster'):
raise ValueError("`mode` must be 'fast' or 'faster'")
suite = []
-
+
def getsetups(setup, shapes, nans):
template = """import numpy as np
import bottleneck as bn
@@ -144,13 +148,13 @@ def getsetups(setup, shapes, nans):
code = "bn.median(a, axis=AXIS)"
else:
code = "func(a)"
- run['statements'] = [code, "np.median(a, axis=AXIS)"]
+ run['statements'] = [code, "np.median(a, axis=AXIS)"]
setup = """
func, a = bn.func.median_selector(a, axis=AXIS)
- """
+ """
run['setups'] = getsetups(setup, shapes, nans)
suite.append(run)
-
+
# nanmedian
run = {}
run['name'] = "nanmedian"
@@ -160,14 +164,14 @@ def getsetups(setup, shapes, nans):
code = "bn.nanmedian(a, axis=AXIS)"
else:
code = "func(a)"
- run['statements'] = [code, "scipy_nanmedian(a, axis=AXIS)"]
+ run['statements'] = [code, "scipy_nanmedian(a, axis=AXIS)"]
setup = """
from bottleneck.slow.func import scipy_nanmedian
func, a = bn.func.nanmedian_selector(a, axis=AXIS)
"""
run['setups'] = getsetups(setup, shapes, nans)
suite.append(run)
-
+
# nansum
run = {}
run['name'] = "nansum"
@@ -177,10 +181,10 @@ def getsetups(setup, shapes, nans):
code = "bn.nansum(a, axis=AXIS)"
else:
code = "func(a)"
- run['statements'] = [code, "np.nansum(a, axis=AXIS)"]
+ run['statements'] = [code, "np.nansum(a, axis=AXIS)"]
setup = """
func, a = bn.func.nansum_selector(a, axis=AXIS)
- """
+ """
run['setups'] = getsetups(setup, shapes, nans)
suite.append(run)
@@ -193,13 +197,13 @@ def getsetups(setup, shapes, nans):
code = "bn.nanmax(a, axis=AXIS)"
else:
code = "func(a)"
- run['statements'] = [code, "np.nanmax(a, axis=AXIS)"]
+ run['statements'] = [code, "np.nanmax(a, axis=AXIS)"]
setup = """
func, a = bn.func.nanmax_selector(a, axis=AXIS)
- """
+ """
run['setups'] = getsetups(setup, shapes, nans)
suite.append(run)
-
+
# nanmean
run = {}
run['name'] = "nanmean"
@@ -209,7 +213,7 @@ def getsetups(setup, shapes, nans):
code = "bn.nanmean(a, axis=AXIS)"
else:
code = "func(a)"
- run['statements'] = [code, "scipy_nanmean(a, axis=AXIS)"]
+ run['statements'] = [code, "scipy_nanmean(a, axis=AXIS)"]
setup = """
from bottleneck.slow.func import scipy_nanmean
func, a = bn.func.nanmean_selector(a, axis=AXIS)
@@ -226,14 +230,14 @@ def getsetups(setup, shapes, nans):
code = "bn.nanstd(a, axis=AXIS)"
else:
code = "func(a, 0)"
- run['statements'] = [code, "scipy_nanstd(a, axis=AXIS)"]
+ run['statements'] = [code, "scipy_nanstd(a, axis=AXIS)"]
setup = """
from bottleneck.slow.func import scipy_nanstd
func, a = bn.func.nanstd_selector(a, axis=AXIS)
"""
run['setups'] = getsetups(setup, shapes, nans)
suite.append(run)
-
+
# nanargmax
run = {}
run['name'] = "nanargmax"
@@ -243,7 +247,7 @@ def getsetups(setup, shapes, nans):
code = "bn.nanargmax(a, axis=AXIS)"
else:
code = "func(a)"
- run['statements'] = [code, "np.nanargmax(a, axis=AXIS)"]
+ run['statements'] = [code, "np.nanargmax(a, axis=AXIS)"]
setup = """
func, a = bn.func.nanargmax_selector(a, axis=AXIS)
"""
@@ -259,14 +263,14 @@ def getsetups(setup, shapes, nans):
code = "bn.ss(a, axis=AXIS)"
else:
code = "func(a)"
- run['statements'] = [code, "scipy_ss(a, axis=AXIS)"]
+ run['statements'] = [code, "scipy_ss(a, axis=AXIS)"]
setup = """
from bottleneck.slow.func import scipy_ss
func, a = bn.func.ss_selector(a, axis=AXIS)
- """
+ """
run['setups'] = getsetups(setup, shapes, nans)
suite.append(run)
-
+
# rankdata
run = {}
run['name'] = "rankdata"
@@ -276,14 +280,14 @@ def getsetups(setup, shapes, nans):
code = "bn.rankdata(a, axis=AXIS)"
else:
code = "func(a)"
- run['statements'] = [code, "bn.slow.rankdata(a, axis=AXIS)"]
+ run['statements'] = [code, "bn.slow.rankdata(a, axis=AXIS)"]
setup = """
ignore = bn.slow.rankdata(a, axis=AXIS)
func, a = bn.func.rankdata_selector(a, axis=AXIS)
"""
run['setups'] = getsetups(setup, shapes, nans)
suite.append(run)
-
+
# partsort
run = {}
run['name'] = "partsort"
@@ -293,7 +297,7 @@ def getsetups(setup, shapes, nans):
code = "bn.partsort(a, n=n, axis=AXIS)"
else:
code = "func(a, n)"
- run['statements'] = [code, "np.sort(a, axis=AXIS)"]
+ run['statements'] = [code, "np.sort(a, axis=AXIS)"]
setup = """
if AXIS is None: n = a.size
else: n = a.shape[AXIS]
@@ -302,7 +306,7 @@ def getsetups(setup, shapes, nans):
"""
run['setups'] = getsetups(setup, shapes, nans)
suite.append(run)
-
+
# argpartsort
run = {}
run['name'] = "argpartsort"
@@ -312,7 +316,7 @@ def getsetups(setup, shapes, nans):
code = "bn.argpartsort(a, n=n, axis=AXIS)"
else:
code = "func(a, n)"
- run['statements'] = [code, "np.argsort(a, axis=AXIS)"]
+ run['statements'] = [code, "np.argsort(a, axis=AXIS)"]
setup = """
if AXIS is None: n = a.size
else: n = a.shape[AXIS]
@@ -331,14 +335,14 @@ def getsetups(setup, shapes, nans):
code = "bn.replace(a, np.nan, 0)"
else:
code = "func(a, np.nan, 0)"
- run['statements'] = [code, "replace(a, np.nan, 0)"]
+ run['statements'] = [code, "replace(a, np.nan, 0)"]
setup = """
from bottleneck.slow.func import replace
func = bn.func.replace_selector(a)
- """
+ """
run['setups'] = getsetups(setup, shapes, nans)
suite.append(run)
-
+
# anynan
run = {}
run['name'] = "anynan"
@@ -348,10 +352,10 @@ def getsetups(setup, shapes, nans):
code = "bn.anynan(a, axis=AXIS)"
else:
code = "func(a)"
- run['statements'] = [code, "np.isnan(a).any(axis=AXIS)"]
+ run['statements'] = [code, "np.isnan(a).any(axis=AXIS)"]
setup = """
func, a = bn.func.anynan_selector(a, axis=AXIS)
- """
+ """
run['setups'] = getsetups(setup, shapes, nans)
suite.append(run)
@@ -365,7 +369,7 @@ def getsetups(setup, shapes, nans):
code = "bn.move_sum(a, window=w, axis=AXIS)"
else:
code = "func(a, w)"
- run['statements'] = [code, "scipy_move_sum(a, window=w, axis=AXIS)"]
+ run['statements'] = [code, "scipy_move_sum(a, window=w, axis=AXIS)"]
setup = """
from bottleneck.slow.move import move_sum as scipy_move_sum
w = a.shape[AXIS] // 5
@@ -375,7 +379,7 @@ def getsetups(setup, shapes, nans):
run['setups'] = getsetups(setup, shapes, nans)
if axis != 'None':
suite.append(run)
-
+
# move_nansum
run = {}
run['name'] = "move_nansum"
@@ -386,7 +390,7 @@ def getsetups(setup, shapes, nans):
code = "bn.move_nansum(a, window=w, axis=AXIS)"
else:
code = "func(a, w)"
- run['statements'] = [code, "scipy_move_nansum(a, window=w, axis=AXIS)"]
+ run['statements'] = [code, "scipy_move_nansum(a, window=w, axis=AXIS)"]
setup = """
from bottleneck.slow.move import move_nansum as scipy_move_nansum
w = a.shape[AXIS] // 5
@@ -396,7 +400,7 @@ def getsetups(setup, shapes, nans):
run['setups'] = getsetups(setup, shapes, nans)
if axis != 'None':
suite.append(run)
-
+
# move_mean
run = {}
run['name'] = "move_mean"
@@ -407,7 +411,7 @@ def getsetups(setup, shapes, nans):
code = "bn.move_mean(a, window=w, axis=AXIS)"
else:
code = "func(a, w)"
- run['statements'] = [code, "scipy_move_mean(a, window=w, axis=AXIS)"]
+ run['statements'] = [code, "scipy_move_mean(a, window=w, axis=AXIS)"]
setup = """
from bottleneck.slow.move import move_mean as scipy_move_mean
w = a.shape[AXIS] // 5
@@ -417,7 +421,7 @@ def getsetups(setup, shapes, nans):
run['setups'] = getsetups(setup, shapes, nans)
if axis != 'None':
suite.append(run)
-
+
# move_nanmean
run = {}
run['name'] = "move_nanmean"
@@ -428,7 +432,7 @@ def getsetups(setup, shapes, nans):
code = "bn.move_nanmean(a, window=w, axis=AXIS)"
else:
code = "func(a, w)"
- run['statements'] = [code, "scipy_move_nanmean(a, window=w, axis=AXIS)"]
+ run['statements'] = [code, "scipy_move_nanmean(a, window=w, axis=AXIS)"]
setup = """
from bottleneck.slow.move import move_nanmean as scipy_move_nanmean
w = a.shape[AXIS] // 5
@@ -438,7 +442,7 @@ def getsetups(setup, shapes, nans):
run['setups'] = getsetups(setup, shapes, nans)
if axis != 'None':
suite.append(run)
-
+
# move_std
run = {}
run['name'] = "move_std"
@@ -449,7 +453,7 @@ def getsetups(setup, shapes, nans):
code = "bn.move_std(a, window=w, axis=AXIS)"
else:
code = "func(a, w, 0)"
- run['statements'] = [code, "scipy_move_std(a, window=w, axis=AXIS)"]
+ run['statements'] = [code, "scipy_move_std(a, window=w, axis=AXIS)"]
setup = """
from bottleneck.slow.move import move_std as scipy_move_std
w = a.shape[AXIS] // 5
@@ -459,7 +463,7 @@ def getsetups(setup, shapes, nans):
run['setups'] = getsetups(setup, shapes, nans)
if axis != 'None':
suite.append(run)
-
+
# move_nanstd
run = {}
run['name'] = "move_nanstd"
@@ -470,7 +474,7 @@ def getsetups(setup, shapes, nans):
code = "bn.move_nanstd(a, window=w, axis=AXIS)"
else:
code = "func(a, w, 0)"
- run['statements'] = [code, "scipy_move_nanstd(a, window=w, axis=AXIS)"]
+ run['statements'] = [code, "scipy_move_nanstd(a, window=w, axis=AXIS)"]
setup = """
from bottleneck.slow.move import move_nanstd as scipy_move_nanstd
w = a.shape[AXIS] // 5
@@ -480,7 +484,7 @@ def getsetups(setup, shapes, nans):
run['setups'] = getsetups(setup, shapes, nans)
if axis != 'None':
suite.append(run)
-
+
# move_max
run = {}
run['name'] = "move_max"
@@ -491,7 +495,7 @@ def getsetups(setup, shapes, nans):
code = "bn.move_max(a, window=w, axis=AXIS)"
else:
code = "func(a, w)"
- run['statements'] = [code, "scipy_move_max(a, window=w, axis=AXIS)"]
+ run['statements'] = [code, "scipy_move_max(a, window=w, axis=AXIS)"]
setup = """
from bottleneck.slow.move import move_max as scipy_move_max
w = a.shape[AXIS] // 5
@@ -501,7 +505,7 @@ def getsetups(setup, shapes, nans):
run['setups'] = getsetups(setup, shapes, nans)
if axis != 'None':
suite.append(run)
-
+
# move_nanmax
run = {}
run['name'] = "move_nanmax"
@@ -512,7 +516,7 @@ def getsetups(setup, shapes, nans):
code = "bn.move_nanmax(a, window=w, axis=AXIS)"
else:
code = "func(a, w)"
- run['statements'] = [code, "scipy_move_nanmax(a, window=w, axis=AXIS)"]
+ run['statements'] = [code, "scipy_move_nanmax(a, window=w, axis=AXIS)"]
setup = """
from bottleneck.slow.move import move_nanmax as scipy_move_nanmax
w = a.shape[AXIS] // 5
@@ -522,14 +526,14 @@ def getsetups(setup, shapes, nans):
run['setups'] = getsetups(setup, shapes, nans)
if axis != 'None':
suite.append(run)
-
+
# Strip leading spaces from setup code
for i, run in enumerate(suite):
for j in range(len(run['setups'])):
t = run['setups'][j]
t = '\n'.join([z.strip() for z in t.split('\n')])
suite[i]['setups'][j] = t
-
+
# Set dtype and axis in setups
for i, run in enumerate(suite):
for j in range(len(run['setups'])):
@@ -546,4 +550,4 @@ def getsetups(setup, shapes, nans):
t = t.replace('AXIS', axis)
suite[i]['statements'][j] = t
- return suite
+ return suite
View
61 bottleneck/slow/func.py
@@ -8,6 +8,7 @@
rankdata_func = None
+
def median(arr, axis=None):
"Slow median function used for unaccelerated ndim/dtype combinations."
arr = np.asarray(arr)
@@ -17,6 +18,7 @@ def median(arr, axis=None):
y = y.astype(arr.dtype)
return y
+
def nansum(arr, axis=None):
"Slow nansum function used for unaccelerated ndim/dtype combinations."
arr = np.asarray(arr)
@@ -28,6 +30,7 @@ def nansum(arr, axis=None):
y = y.astype(arr.dtype)
return y
+
def nanmedian(arr, axis=None):
"Slow nanmedian function used for unaccelerated ndim/dtype combinations."
arr = np.asarray(arr)
@@ -44,6 +47,7 @@ def nanmedian(arr, axis=None):
y = y[()]
return y
+
def nanmean(arr, axis=None):
"Slow nanmean function used for unaccelerated ndim/dtype combinations."
arr = np.asarray(arr)
@@ -53,12 +57,14 @@ def nanmean(arr, axis=None):
y = y.astype(arr.dtype)
return y
+
def nanvar(arr, axis=None, ddof=0):
"Slow nanvar function used for unaccelerated ndim/dtype combinations."
arr = np.asarray(arr)
y = nanstd(arr, axis=axis, ddof=ddof)
return y * y
+
def nanstd(arr, axis=None, ddof=0):
"Slow nanstd function used for unaccelerated ndim/dtype combinations."
arr = np.asarray(arr)
@@ -68,7 +74,7 @@ def nanstd(arr, axis=None, ddof=0):
bias = False
else:
raise ValueError("With NaNs ddof must be 0 or 1.")
- if axis != None:
+ if axis is not None:
# Older versions of scipy can't handle negative axis?
if axis < 0:
axis += arr.ndim
@@ -84,30 +90,35 @@ def nanstd(arr, axis=None, ddof=0):
y = y.astype(arr.dtype)
return y
+
def nanmin(arr, axis=None):
"Slow nanmin function used for unaccelerated ndim/dtype combinations."
- y = np.nanmin(arr, axis=axis)
+ y = np.nanmin(arr, axis=axis)
if not hasattr(y, "dtype"):
# Numpy 1.5.1 doesn't return object with dtype when input is all NaN
y = arr.dtype.type(y)
return y
+
def nanmax(arr, axis=None):
"Slow nanmax function used for unaccelerated ndim/dtype combinations."
- y = np.nanmax(arr, axis=axis)
+ y = np.nanmax(arr, axis=axis)
if not hasattr(y, "dtype"):
# Numpy 1.5.1 doesn't return object with dtype when input is all NaN
y = arr.dtype.type(y)
return y
+
def nanargmin(arr, axis=None):
"Slow nanargmin function used for unaccelerated ndim/dtype combinations."
return np.nanargmin(arr, axis=axis)
+
def nanargmax(arr, axis=None):
"Slow nanargmax function used for unaccelerated ndim/dtype combinations."
return np.nanargmax(arr, axis=axis)
+
def rankdata(arr, axis=None):
"Slow rankdata function used for unaccelerated ndim/dtype combinations."
global rankdata_func
@@ -133,6 +144,7 @@ def rankdata(arr, axis=None):
y[ijslice] = rankdata_func(arr[ijslice].astype('float'))
return y
+
def nanrankdata(arr, axis=None):
"Slow nanrankdata function used for unaccelerated ndim/dtype combinations."
arr = np.asarray(arr)
@@ -153,10 +165,12 @@ def nanrankdata(arr, axis=None):
y[ijslice] = x1d
return y
+
def ss(arr, axis=0):
"Slow sum of squares used for unaccelerated ndim/dtype combinations."
return scipy_ss(arr, axis)
+
def nn(arr, arr0, axis=1):
"Slow nearest neighbor used for unaccelerated ndim/dtype combinations."
arr = np.array(arr, copy=False)
@@ -168,21 +182,24 @@ def nn(arr, arr0, axis=1):
if axis == 1:
d = (arr - arr0) ** 2
elif axis == 0:
- d = (arr - arr0.reshape(-1,1)) ** 2
+ d = (arr - arr0.reshape(-1, 1)) ** 2
else:
raise ValueError("`axis` must be 0 or 1.")
d = d.sum(axis)
idx = np.argmin(d)
- return np.sqrt(d[idx]), idx
+ return np.sqrt(d[idx]), idx
+
def partsort(arr, n, axis=-1):
"Slow partial sort used for unaccelerated ndim/dtype combinations."
return np.sort(arr, axis)
+
def argpartsort(arr, n, axis=-1):
"Slow partial argsort used for unaccelerated ndim/dtype combinations."
return np.argsort(arr, axis)
+
def replace(arr, old, new):
"Slow replace (inplace) used for unaccelerated ndim/dtype combinations."
if type(arr) is not np.ndarray:
@@ -201,10 +218,12 @@ def replace(arr, old, new):
mask = arr == old
np.putmask(arr, mask, new)
+
def anynan(arr, axis=None):
"Slow check for Nans used for unaccelerated ndim/dtype combinations."
return np.isnan(arr).any(axis)
+
def allnan(arr, axis=None):
"Slow check for all Nans used for unaccelerated ndim/dtype combinations."
return np.isnan(arr).all(axis)
@@ -221,6 +240,7 @@ def allnan(arr, axis=None):
# nanmedian taken from scipy trunk on Dec 17, 2010.
# rankdata taken from scipy HEAD on Mar 16, 2011.
+
def scipy_nanmean(x, axis=0):
"""
Compute the mean over the given axis ignoring nans.
@@ -253,13 +273,14 @@ def scipy_nanmean(x, axis=0):
1.0
"""
- x, axis = _chk_asarray(x,axis)
+ x, axis = _chk_asarray(x, axis)
x = x.copy()
Norig = x.shape[axis]
- factor = 1.0-np.sum(np.isnan(x),axis)*1.0/Norig
+ factor = 1.0-np.sum(np.isnan(x), axis)*1.0/Norig
x[np.isnan(x)] = 0
- return np.mean(x,axis)/factor
+ return np.mean(x, axis)/factor
+
def scipy_nanstd(x, axis=0, bias=False):
"""
@@ -300,28 +321,29 @@ def scipy_nanstd(x, axis=0, bias=False):
2.9154759474226504
"""
- x, axis = _chk_asarray(x,axis)
+ x, axis = _chk_asarray(x, axis)
x = x.copy()
Norig = x.shape[axis]
- Nnan = np.sum(np.isnan(x),axis)*1.0
+ Nnan = np.sum(np.isnan(x), axis)*1.0
n = Norig - Nnan
x[np.isnan(x)] = 0.
- m1 = np.sum(x,axis)/n
+ m1 = np.sum(x, axis)/n
if axis:
d = (x - np.expand_dims(m1, axis))**2.0
else:
d = (x - m1)**2.0
- m2 = np.sum(d,axis)-(m1*m1)*Nnan
+ m2 = np.sum(d, axis)-(m1*m1)*Nnan
if bias:
m2c = m2 / n
else:
m2c = m2 / (n - 1.)
return np.sqrt(m2c)
+
def _nanmedian(arr1d): # This only works on 1d arrays
"""Private function for rank a arrays. Compute the median ignoring Nan.
@@ -336,11 +358,12 @@ def _nanmedian(arr1d): # This only works on 1d arrays
The median.
"""
cond = 1-np.isnan(arr1d)
- x = np.sort(np.compress(cond,arr1d,axis=-1))
+ x = np.sort(np.compress(cond, arr1d, axis=-1))
if x.size == 0:
return np.nan
return np.median(x)
+
# Feb 2011: patched nanmedian to handle nanmedian(a, 1) with a = np.ones((2,0))
def scipy_nanmedian(x, axis=0):
"""
@@ -396,13 +419,14 @@ def scipy_nanmedian(x, axis=0):
shape.pop(axis)
if 0 in shape:
x = np.empty(shape)
- else:
+ else:
x = x.copy()
x = np.apply_along_axis(_nanmedian, axis, x)
if x.ndim == 0:
x = float(x.item())
return x
+
def _chk_asarray(a, axis):
if axis is None:
a = np.ravel(a)
@@ -412,6 +436,7 @@ def _chk_asarray(a, axis):
outaxis = axis
return a, outaxis
+
def fastsort(a):
"""
Sort an array and provide the argsort.
@@ -432,6 +457,7 @@ def fastsort(a):
as_ = a[it]
return as_, it
+
def scipy_rankdata(a):
"""
Ranks the data, dealing with ties appropriately.
@@ -452,7 +478,7 @@ def scipy_rankdata(a):
Examples
--------
- >>> stats.rankdata([0, 2, 2, 3])
+ >>> scipy_rankdata([0, 2, 2, 3])
array([ 1. , 2.5, 2.5, 4. ])
"""
@@ -465,14 +491,15 @@ def scipy_rankdata(a):
for i in range(n):
sumranks += i
dupcount += 1
- if i==n-1 or svec[i] != svec[i+1]:
+ if i == n-1 or svec[i] != svec[i+1]:
averank = sumranks / float(dupcount) + 1
- for j in range(i-dupcount+1,i+1):
+ for j in range(i-dupcount+1, i+1):
newarray[ivec[j]] = averank
sumranks = 0
dupcount = 0
return newarray
+
def scipy_ss(a, axis=0):
"""
Squares each element of the input array, and returns the square(s) of that.
View
182 bottleneck/slow/move.py
@@ -20,10 +20,11 @@
# SUM -----------------------------------------------------------------------
+
def move_sum(arr, window, axis=-1, method='loop'):
"""
Slow move_sum for unaccelerated ndim/dtype combinations.
-
+
Parameters
----------
arr : array_like
@@ -69,10 +70,11 @@ def move_sum(arr, window, axis=-1, method='loop'):
y = y.astype(arr.dtype)
return y
+
def move_nansum(arr, window, axis=-1, method='loop'):
"""
Slow move_nansum for unaccelerated ndim/dtype combinations.
-
+
Parameters
----------
arr : array_like
@@ -96,7 +98,7 @@ def move_nansum(arr, window, axis=-1, method='loop'):
The moving sum of the input array along the specified axis, ignoring
NaNs. (A window with all NaNs returns NaN for the window sum.) The
output has the same shape as the input.
-
+
Examples
--------
>>> arr = np.array([1, 2, np.nan, 4])
@@ -119,10 +121,11 @@ def move_nansum(arr, window, axis=-1, method='loop'):
y = y.astype(arr.dtype)
return y
+
def move_sum_filter(arr, window, axis=-1):
"""
Moving window sum along the specified axis using the filter method.
-
+
Parameters
----------
arr : array_like
@@ -132,7 +135,7 @@ def move_sum_filter(arr, window, axis=-1):
axis : int, optional
The axis over which to perform the moving sum. By default the moving
sum is taken over the last axis (-1).
-
+
Returns
-------
y : ndarray
@@ -141,7 +144,7 @@ def move_sum_filter(arr, window, axis=-1):
Notes
-----
- The calculation of the sums uses scipy.ndimage.convolve1d.
+ The calculation of the sums uses scipy.ndimage.convolve1d.
Examples
--------
@@ -158,9 +161,9 @@ def move_sum_filter(arr, window, axis=-1):
from scipy.ndimage import convolve1d
except ImportError:
raise ValueError("'filter' method requires SciPy.")
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -171,10 +174,11 @@ def move_sum_filter(arr, window, axis=-1):
output=arr)
return arr
+
def move_nansum_filter(arr, window, axis=-1):
"""
Moving sum (ignoring NaNs) along specified axis using the filter method.
-
+
Parameters
----------
arr : array_like
@@ -184,7 +188,7 @@ def move_nansum_filter(arr, window, axis=-1):
axis : int, optional
The axis over which to perform the moving sum. By default the moving
sum is taken over the last axis (-1).
-
+
Returns
-------
y : ndarray
@@ -194,11 +198,11 @@ def move_nansum_filter(arr, window, axis=-1):
Notes
-----
- The calculation of the sums uses scipy.ndimage.convolve1d.
+ The calculation of the sums uses scipy.ndimage.convolve1d.
Examples
--------
- >>> from bottleneck.slow.move import move_sum_filter
+ >>> from bottleneck.slow.move import move_nansum_filter
>>> arr = np.array([1, 2, np.nan, 4, 5, 6, 7])
>>> move_nansum_filter(arr, window=2, axis=0)
array([ NaN, 3., 2., 4., 9., 11., 13.])
@@ -211,9 +215,9 @@ def move_nansum_filter(arr, window, axis=-1):
from scipy.ndimage import convolve1d
except ImportError:
raise ValueError("'filter' method requires SciPy.")
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -232,10 +236,11 @@ def move_nansum_filter(arr, window, axis=-1):
# MEAN -------------------------------------------------------------------
+
def move_mean(arr, window, axis=-1, method='loop'):
"""
Slow move_mean for unaccelerated ndim/dtype combinations.
-
+
Parameters
----------
arr : array_like
@@ -264,7 +269,7 @@ def move_mean(arr, window, axis=-1, method='loop'):
>>> arr = np.array([1, 2, 3, 4])
>>> bn.slow.move_mean(arr, window=2, axis=0)
array([ NaN, 1.5, 2.5, 3.5])
-
+
"""
arr = np.array(arr, copy=False)
if method == 'filter':
@@ -281,10 +286,11 @@ def move_mean(arr, window, axis=-1, method='loop'):
y = y.astype(arr.dtype)
return y
+
def move_nanmean(arr, window, axis=-1, method='loop'):
"""
Slow move_nanmean for unaccelerated ndim/dtype combinations.
-
+
Parameters
----------
arr : array_like
@@ -308,13 +314,13 @@ def move_nanmean(arr, window, axis=-1, method='loop'):
The moving mean of the input array along the specified axis, ignoring
NaNs. (A window with all NaNs returns NaN for the window mean.) The
output has the same shape as the input.
-
+
Examples
--------
>>> arr = np.array([1, 2, np.nan, 4])
>>> bn.slow.move_nanmean(arr, window=2, axis=0)
array([ NaN, 1.5, 2. , 4. ])
-
+
"""
arr = np.array(arr, copy=False)
if method == 'filter':
@@ -331,6 +337,7 @@ def move_nanmean(arr, window, axis=-1, method='loop'):
y = y.astype(arr.dtype)
return y
+
def move_mean_filter(arr, window, axis=-1):
"Moving window mean implemented with a filter."
arr = np.array(arr, copy=False)
@@ -340,9 +347,9 @@ def move_mean_filter(arr, window, axis=-1):
from scipy.ndimage import convolve1d
except ImportError:
raise ValueError("'filter' method requires SciPy.")
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -354,6 +361,7 @@ def move_mean_filter(arr, window, axis=-1):
output=arr)
return arr
+
def move_nanmean_filter(arr, window, axis=-1):
"Moving window nanmean implemented with a filter."
arr = np.array(arr, copy=False)
@@ -363,9 +371,9 @@ def move_nanmean_filter(arr, window, axis=-1):
from scipy.ndimage import convolve1d
except ImportError:
raise ValueError("'filter' method requires SciPy.")
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -385,10 +393,11 @@ def move_nanmean_filter(arr, window, axis=-1):
# VAR -----------------------------------------------------------------------
+
def move_var(arr, window, axis=-1, method='loop', ddof=0):
"""
Slow move_var for unaccelerated ndim/dtype combinations.
-
+
Parameters
----------
arr : array_like
@@ -417,7 +426,7 @@ def move_var(arr, window, axis=-1, method='loop', ddof=0):
>>> arr = np.array([1, 2, 3, 4])
>>> bn.slow.move_var(arr, window=2, axis=0)
array([ NaN, 0.25, 0.25, 0.25])
-
+
"""
arr = np.array(arr, copy=False)
if ddof != 0:
@@ -436,10 +445,11 @@ def move_var(arr, window, axis=-1, method='loop', ddof=0):
y = y.astype(arr.dtype)
return y
+
def move_nanvar(arr, window, axis=-1, method='loop', ddof=0):
"""
Slow move_nanvar for unaccelerated ndim/dtype combinations.
-
+
Parameters
----------
arr : array_like
@@ -469,7 +479,7 @@ def move_nanvar(arr, window, axis=-1, method='loop', ddof=0):
>>> arr = np.array([1, 2, np.nan, 4, 5])
>>> bn.slow.move_nanvar(arr, window=3, axis=0)
array([ NaN, NaN, 0.25, 1. , 0.25])
-
+
"""
arr = np.array(arr, copy=False)
if ddof != 0:
@@ -488,6 +498,7 @@ def move_nanvar(arr, window, axis=-1, method='loop', ddof=0):
y = y.astype(arr.dtype)
return y
+
def move_var_filter(arr, window, axis=-1):
"Moving window variance implemented with a filter."
arr = np.array(arr, copy=False)
@@ -497,9 +508,9 @@ def move_var_filter(arr, window, axis=-1):
from scipy.ndimage import convolve1d
except ImportError:
raise ValueError("'filter' method requires SciPy.")
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -512,9 +523,10 @@ def move_var_filter(arr, window, axis=-1):
arr *= arr
convolve1d(arr, w, axis=axis, mode='constant', cval=np.nan, origin=x0,
output=arr)
- arr -= y
+ arr -= y
return arr
+
def move_nanvar_filter(arr, window, axis=-1):
"Moving window variance ignoring NaNs, implemented with a filter."
arr = np.array(arr, copy=False)
@@ -524,9 +536,9 @@ def move_nanvar_filter(arr, window, axis=-1):
from scipy.ndimage import convolve1d
except ImportError:
raise ValueError("'filter' method requires SciPy.")
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -551,10 +563,11 @@ def move_nanvar_filter(arr, window, axis=-1):
# STD -----------------------------------------------------------------------
+
def move_std(arr, window, axis=-1, method='loop', ddof=0):
"""
Moving window standard deviation along the specified axis.
-
+
Parameters
----------
arr : array_like
@@ -584,7 +597,7 @@ def move_std(arr, window, axis=-1, method='loop', ddof=0):
>>> arr = np.array([1, 2, 3, 4])
>>> bn.slow.move_std(arr, window=2)
array([ NaN, 0.5, 0.5, 0.5])
-
+
"""
arr = np.array(arr, copy=False)
if ddof != 0:
@@ -603,10 +616,11 @@ def move_std(arr, window, axis=-1, method='loop', ddof=0):
y = y.astype(arr.dtype)
return y
+
def move_nanstd(arr, window, axis=-1, method='loop', ddof=0):
"""
Moving window standard deviation along the specified axis, ignoring NaNs.
-
+
Parameters
----------
arr : array_like
@@ -636,7 +650,7 @@ def move_nanstd(arr, window, axis=-1, method='loop', ddof=0):
--------
>>> arr = np.array([1, 2, np.nan, 4, 5])
>>> bn.slow.move_nanstd(arr, window=3)
- array([ NaN, NaN, 0.5, 1. , 0.5])
+ array([ NaN, NaN, 0.5, 1. , 0.5])
"""
arr = np.array(arr, copy=False)
@@ -656,12 +670,13 @@ def move_nanstd(arr, window, axis=-1, method='loop', ddof=0):
y = y.astype(arr.dtype)
return y
+
def move_std_filter(arr, window, axis=-1):
"Moving window standard deviation implemented with a filter."
arr = np.array(arr, copy=False)
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -669,12 +684,13 @@ def move_std_filter(arr, window, axis=-1):
np.sqrt(y, y)
return y
+
def move_nanstd_filter(arr, window, axis=-1):
- "Moving window standard deviation ignoring NaNs, implemented with a filter."
+ "Moving window standard deviation ignoring NaNs, implemented with filter."
arr = np.array(arr, copy=False)
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -684,10 +700,11 @@ def move_nanstd_filter(arr, window, axis=-1):
# MIN -----------------------------------------------------------------------
+
def move_min(arr, window, axis=-1, method='loop'):
"""
Slow move_min for unaccelerated ndim/dtype combinations.
-
+
Parameters
----------
arr : array_like
@@ -715,7 +732,7 @@ def move_min(arr, window, axis=-1, method='loop'):
--------
>>> arr = np.array([1, 2, 3, 4])
>>> bn.slow.move_min(arr, window=2)
- array([ NaN, 1., 2., 3.])
+ array([ NaN, 1., 2., 3.])
"""
if method == 'filter':
@@ -728,10 +745,11 @@ def move_min(arr, window, axis=-1, method='loop'):
raise ValueError("`method` must be 'filter', 'strides', or 'loop'.")
return y
+
def move_nanmin(arr, window, axis=-1, method='loop'):
"""
Slow move_nanmin for unaccelerated ndim/dtype combinations.
-
+
Parameters
----------
arr : array_like
@@ -760,7 +778,7 @@ def move_nanmin(arr, window, axis=-1, method='loop'):
--------
>>> arr = np.array([1, 2, np.nan, 4, 5])
>>> bn.slow.move_nanmin(arr, window=2)
- array([ NaN, 1., 2., 4., 4.])
+ array([ NaN, 1., 2., 4., 4.])
"""
if method == 'filter':
@@ -773,6 +791,7 @@ def move_nanmin(arr, window, axis=-1, method='loop'):
raise ValueError("`method` must be 'filter', 'strides', or 'loop'.")
return y
+
def move_min_filter(arr, window, axis=-1):
"Moving window minimium implemented with a filter."
arr = np.array(arr, copy=False)
@@ -782,9 +801,9 @@ def move_min_filter(arr, window, axis=-1):
from scipy.ndimage import minimum_filter1d
except ImportError:
raise ValueError("'filter' method requires SciPy.")
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -794,6 +813,7 @@ def move_min_filter(arr, window, axis=-1):
origin=x0, output=y)
return y
+
def move_nanmin_filter(arr, window, axis=-1):
"Moving window minimium ignoring NaNs, implemented with a filter."
global minimum_filter1d, convolve1d
@@ -808,9 +828,9 @@ def move_nanmin_filter(arr, window, axis=-1):
from scipy.ndimage import convolve1d
except ImportError:
raise ValueError("'filter' method requires SciPy.")
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -828,12 +848,13 @@ def move_nanmin_filter(arr, window, axis=-1):
arr[nrr == window] = np.nan
return arr
+
def move_nanmin_loop(arr, window, axis=-1):
"Moving window minimium ignoring NaNs, implemented with a python loop."
arr = np.array(arr, copy=False)
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -845,12 +866,13 @@ def move_nanmin_loop(arr, window, axis=-1):
y[m == window] = np.nan
return y
+
def move_nanmin_strides(arr, window, axis=-1):
"Moving window minimium ignoring NaNs, implemented with stides tricks."
arr = np.array(arr, copy=False)
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -864,10 +886,11 @@ def move_nanmin_strides(arr, window, axis=-1):
# MAX -----------------------------------------------------------------------
+
def move_max(arr, window, axis=-1, method='loop'):
"""
Slow move_max for unaccelerated ndim/dtype combinations.
-
+
Parameters
----------
arr : array_like
@@ -895,7 +918,7 @@ def move_max(arr, window, axis=-1, method='loop'):
--------
>>> arr = np.array([1, 2, 3, 4])
>>> bn.slow.move_max(arr, window=2)
- array([ NaN, 2., 3., 4.])
+ array([ NaN, 2., 3., 4.])
"""
if method == 'filter':
@@ -908,10 +931,11 @@ def move_max(arr, window, axis=-1, method='loop'):
raise ValueError("`method` must be 'filter', 'strides', or 'loop'.")
return y
+
def move_nanmax(arr, window, axis=-1, method='loop'):
"""
Slow move_nanmax for unaccelerated ndim/dtype combinations, ignoring NaNs.
-
+
Parameters
----------
arr : array_like
@@ -953,6 +977,7 @@ def move_nanmax(arr, window, axis=-1, method='loop'):
raise ValueError("`method` must be 'filter', 'strides', or 'loop'.")
return y
+
def move_max_filter(arr, window, axis=-1):
"Moving window maximium implemented with a filter."
arr = np.array(arr, copy=False)
@@ -962,9 +987,9 @@ def move_max_filter(arr, window, axis=-1):
from scipy.ndimage import maximum_filter1d
except ImportError:
raise ValueError("'filter' method requires SciPy.")
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -974,6 +999,7 @@ def move_max_filter(arr, window, axis=-1):
origin=x0, output=y)
return y
+
def move_nanmax_filter(arr, window, axis=-1):
"Moving window maximium ignoring NaNs, implemented with a filter."
arr = np.array(arr, copy=False)
@@ -988,9 +1014,9 @@ def move_nanmax_filter(arr, window, axis=-1):
from scipy.ndimage import convolve1d
except ImportError:
raise ValueError("'filter' method requires SciPy.")
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -1008,12 +1034,13 @@ def move_nanmax_filter(arr, window, axis=-1):
arr[nrr == window] = np.nan
return arr
+
def move_nanmax_loop(arr, window, axis=-1):
"Moving window maximium ignoring NaNs, implemented with a python loop."
arr = np.array(arr, copy=False)
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -1025,12 +1052,13 @@ def move_nanmax_loop(arr, window, axis=-1):
y[m == window] = np.nan
return y
+
def move_nanmax_strides(arr, window, axis=-1):
"Moving window maximium ignoring NaNs, implemented with stides tricks."
arr = np.array(arr, copy=False)
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -1044,10 +1072,11 @@ def move_nanmax_strides(arr, window, axis=-1):
# MEDIAN --------------------------------------------------------------------
+
def move_median(arr, window, axis=-1, method='loop'):
"""
Slow moving window median along the specified axis.
-
+
Parameters
----------
arr : array_like
@@ -1092,10 +1121,11 @@ def move_median(arr, window, axis=-1, method='loop'):
# GENERAL --------------------------------------------------------------------
+
def move_func(func, arr, window, axis=-1, method='loop', **kwargs):
"""
Generic moving window function along the specified axis.
-
+
Parameters
----------
func : function
@@ -1142,12 +1172,13 @@ def move_func(func, arr, window, axis=-1, method='loop', **kwargs):
raise ValueError(msg)
return y
+
def move_func_loop(func, arr, window, axis=-1, **kwargs):
"Generic moving window function implemented with a python loop."
arr = np.array(arr, copy=False)
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -1159,14 +1190,15 @@ def move_func_loop(func, arr, window, axis=-1, **kwargs):
idx1[axis] = slice(i + 1 - window, i + 1)
idx2[axis] = i
y[idx2] = func(arr[idx1], axis=axis, **kwargs)
- return y
+ return y
+
def move_func_strides(func, arr, window, axis=-1, **kwargs):
"Generic moving window function implemented with strides."
arr = np.array(arr, copy=False)
- if axis == None:
+ if axis is None:
raise ValueError("An `axis` value of None is not supported.")
- if window < 1:
+ if window < 1:
raise ValueError("`window` must be at least 1.")
if window > arr.shape[axis]:
raise ValueError("`window` is too long.")
@@ -1187,12 +1219,12 @@ def move_func_strides(func, arr, window, axis=-1, **kwargs):
if axis == 1:
arr = arr.T
strides = arr.strides
- shape = (arr.shape[0] - window + 1, window, arr.shape[1])
- strides = (strides[0],) + strides
+ shape = (arr.shape[0] - window + 1, window, arr.shape[1])
+ strides = (strides[0],) + strides
z = as_strided(arr, shape=shape, strides=strides)
y = func(z, axis=1, **kwargs)
if axis == 1:
- y = y.T
+ y = y.T
elif ndim == 3:
if axis > 0:
arr = arr.swapaxes(0, axis)
@@ -1207,7 +1239,7 @@ def move_func_strides(func, arr, window, axis=-1, **kwargs):
raise ValueError("Only 1d, 2d, and 3d input arrays are supported.")
ynan = np.empty(arrshape0)
ynan.fill(np.nan)
- index = [slice(None)] * ndim
+ index = [slice(None)] * ndim
index[axis] = slice(window - 1, None)
ynan[index] = y
return ynan
View
36,503 bottleneck/src/func/func.c
27,741 additions, 8,762 deletions not shown
View
25,644 bottleneck/src/move/move.c
18,250 additions, 7,394 deletions not shown
View
18 bottleneck/src/template/func/allnan.py
@@ -92,7 +92,7 @@ def NAME_NDIMd_DTYPE_axisAXIS(np.ndarray[np.DTYPE_t, ndim=NDIM] a):
# Int dtypes (not axis=None) ------------------------------------------------
ints = deepcopy(floats)
-ints['dtypes'] = INT_DTYPES
+ints['dtypes'] = INT_DTYPES
loop = {}
loop[2] = """\
@@ -119,7 +119,7 @@ def NAME_NDIMd_DTYPE_axisAXIS(np.ndarray[np.DTYPE_t, ndim=NDIM] a):
# Int dtypes (axis=None) ----------------------------------------------------
-ints_None = deepcopy(ints)
+ints_None = deepcopy(ints)
ints_None['axisNone'] = True
loop = {}
@@ -226,7 +226,7 @@ def allnan(arr, axis=None):
def allnan_selector(arr, axis):
"""
Return allnan function and array that matches `arr` and `axis`.
-
+
Under the hood Bottleneck uses a separate Cython function for each
combination of ndim, dtype, and axis. A lot of the overhead in bn.allnan()
is in checking that `axis` is within range, converting `arr` into an
@@ -241,7 +241,7 @@ def allnan_selector(arr, axis):
Input array. If `arr` is not an array, a conversion is attempted.
axis : {int, None}
Axis along which NaNs are searched.
-
+
Returns
-------
func : function
@@ -256,16 +256,16 @@ def allnan_selector(arr, axis):
Create a numpy array:
>>> arr = np.array([1.0, 2.0, 3.0])
-
+
Obtain the function needed to determine if `arr` contains all NaNs:
>>> func, a = bn.func.allnan_selector(arr, axis=0)
>>> func
<function allnan_1d_float64_axisNone>
-
+
Use the returned function and array to determine is all elements are
NaN:
-
+
>>> func(a)
False
@@ -273,7 +273,7 @@ def allnan_selector(arr, axis):
cdef np.ndarray a
if type(arr) is np.ndarray:
a = arr
- else:
+ else:
a = np.array(arr, copy=False)
cdef int ndim = PyArray_NDIM(a)
cdef int dtype = PyArray_TYPE(a)
@@ -292,4 +292,4 @@ def allnan_selector(arr, axis):
tup = (str(ndim), str(a.dtype), str(axis))
raise TypeError("Unsupported ndim/dtype/axis (%s/%s/%s)." % tup)
return func, a
-'''
+'''
View
20 bottleneck/src/template/func/anynan.py
@@ -92,7 +92,7 @@ def NAME_NDIMd_DTYPE_axisAXIS(np.ndarray[np.DTYPE_t, ndim=NDIM] a):
# Int dtypes (not axis=None) ------------------------------------------------
ints = deepcopy(floats)
-ints['dtypes'] = INT_DTYPES
+ints['dtypes'] = INT_DTYPES
loop = {}
loop[2] = """\
@@ -111,7 +111,7 @@ def NAME_NDIMd_DTYPE_axisAXIS(np.ndarray[np.DTYPE_t, ndim=NDIM] a):
# Int dtypes (axis=None) ----------------------------------------------------
-ints_None = deepcopy(ints)
+ints_None = deepcopy(ints)
ints_None['axisNone'] = True
loop = {}
@@ -186,7 +186,7 @@ def anynan(arr, axis=None):
>>> bn.anynan(a)
True
>>> bn.anynan(a, axis=0)
- array([False, True], dtype=bool)
+ array([False, True], dtype=bool)
"""
func, arr = anynan_selector(arr, axis)
@@ -195,7 +195,7 @@ def anynan(arr, axis=None):
def anynan_selector(arr, axis):
"""
Return anynan function and array that matches `arr` and `axis`.
-
+
Under the hood Bottleneck uses a separate Cython function for each
combination of ndim, dtype, and axis. A lot of the overhead in bn.anynan()
is in checking that `axis` is within range, converting `arr` into an
@@ -210,7 +210,7 @@ def anynan_selector(arr, axis):
Input array. If `arr` is not an array, a conversion is attempted.
axis : {int, None}
Axis along which NaNs are searched.
-
+
Returns
-------
func : function
@@ -225,16 +225,16 @@ def anynan_selector(arr, axis):
Create a numpy array:
>>> arr = np.array([1.0, 2.0, 3.0])
-
+
Obtain the function needed to determine if there are any NaN in `arr`:
>>> func, a = bn.func.anynan_selector(arr, axis=0)
>>> func
<function anynan_1d_float64_axisNone>
-
+
Use the returned function and array to determine if there are any
NaNs:
-
+
>>> func(a)
False
@@ -242,7 +242,7 @@ def anynan_selector(arr, axis):
cdef np.ndarray a
if type(arr) is np.ndarray:
a = arr
- else:
+ else:
a = np.array(arr, copy=False)
cdef int ndim = PyArray_NDIM(a)
cdef int dtype = PyArray_TYPE(a)
@@ -261,4 +261,4 @@ def anynan_selector(arr, axis):
tup = (str(ndim), str(a.dtype), str(axis))
raise TypeError("Unsupported ndim/dtype/axis (%s/%s/%s)." % tup)
return func, a
-'''
+'''
View
32 bottleneck/src/template/func/argpartsort.py
@@ -20,7 +20,7 @@
raise ValueError(PARTSORT_ERR_MSG % (n, nAXIS))
l = 0
r = nAXIS - 1
- with nogil:
+ with nogil:
while l < r:
x = b[k]
i = l
@@ -41,7 +41,7 @@
if j < k: l = i
if k < i: r = j
return y
-"""
+"""
loop[2] = """\
for i0 in range(n0):
for i1 in range(n1):
@@ -50,7 +50,7 @@
return y
if (n < 1) or (n > nAXIS):
raise ValueError(PARTSORT_ERR_MSG % (n, nAXIS))
- for iINDEX0 in range(nINDEX0):
+ for iINDEX0 in range(nINDEX0):
l = 0
r = nAXIS - 1
while l < r:
@@ -122,7 +122,7 @@
@cython.wraparound(False)
def NAME_NDIMd_DTYPE_axisAXIS(np.ndarray[np.DTYPE_t, ndim=NDIM] a, int n):
"Partial sort of NDIMd array with dtype=DTYPE along axis=AXIS."
- cdef np.npy_intp i, j = 0, l, r, k = n-1, itmp
+ cdef np.npy_intp i, j = 0, l, r, k = n-1, itmp
cdef np.DTYPE_t x, tmp
cdef np.ndarray[np.DTYPE_t, ndim=NDIM] b = PyArray_Copy(a)
"""
@@ -132,7 +132,7 @@ def NAME_NDIMd_DTYPE_axisAXIS(np.ndarray[np.DTYPE_t, ndim=NDIM] a, int n):
# Int dtypes (not axis=None) ------------------------------------------------
ints = deepcopy(floats)
-ints['dtypes'] = INT_DTYPES
+ints['dtypes'] = INT_DTYPES
# Slow, unaccelerated ndim/dtype --------------------------------------------
@@ -157,7 +157,7 @@ def NAME_NDIMd_DTYPE_axisAXIS(np.ndarray[np.DTYPE_t, ndim=NDIM] a, int n):
# Select smallest k elements code used for inner loop of argpartsort method:
# http://projects.scipy.org/numpy/attachment/ticket/1213/quickselect.pyx
# (C) 2009 Sturla Molden
-# SciPy license
+# SciPy license
#
# From the original C function (code in public domain) in:
# Fast median search: an ANSI C implementation
@@ -191,7 +191,7 @@ def argpartsort(arr, n, axis=-1):
----------
arr : array_like
Input array. If `arr` is not an array, a conversion is attempted.
- n : int
+ n : int
The indices of the `n` smallest elements will appear in the first `n`
elements of the output array along the given `axis`.
axis : {int, None}, optional
@@ -208,7 +208,7 @@ def argpartsort(arr, n, axis=-1):
See Also
--------
bottleneck.partsort: Partial sorting of array elements along given axis.
-
+
Notes
-----
Unexpected results may occur if the input array contains NaN.
@@ -218,7 +218,7 @@ def argpartsort(arr, n, axis=-1):
Create a numpy array:
>>> a = np.array([1, 0, 3, 4, 2])
-
+
Find the indices that partially sort that array so that the first 3
elements are the smallest 3 elements:
@@ -231,7 +231,7 @@ def argpartsort(arr, n, axis=-1):
>>> a[index]
array([1, 0, 2, 4, 3])
-
+
"""
func, arr = argpartsort_selector(arr, axis)
return func(arr, n)
@@ -239,7 +239,7 @@ def argpartsort(arr, n, axis=-1):
def argpartsort_selector(arr, axis):
"""
Return argpartsort function and array that matches `arr` and `axis`.
-
+
Under the hood Bottleneck uses a separate Cython function for each
combination of ndim, dtype, and axis. A lot of the overhead in
bn.argpartsort() is in checking that `axis` is within range, converting
@@ -255,7 +255,7 @@ def argpartsort_selector(arr, axis):
Input array. If `arr` is not an array, a conversion is attempted.
axis : {int, None}
Axis along which to partially sort.
-
+
Returns
-------
func : function
@@ -271,14 +271,14 @@ def argpartsort_selector(arr, axis):
Create a numpy array:
>>> arr = np.array([1, 0, 3, 4, 2])
-
+
Obtain the function needed to find the indices of a partial sort of `arr`
along axis=0:
>>> func, a = bn.func.argpartsort_selector(arr, axis=0)
>>> func
<function argpartsort_1d_int64_axis0>
-
+
Use the returned function and array to find the indices of the partial
sort:
@@ -289,7 +289,7 @@ def argpartsort_selector(arr, axis):
cdef np.ndarray a
if type(arr) is np.ndarray:
a = arr
- else:
+ else:
a = np.array(arr, copy=False)
cdef tuple key
cdef int ndim = PyArray_NDIM(a)
@@ -313,4 +313,4 @@ def argpartsort_selector(arr, axis):
tup = (str(ndim), str(a.dtype), str(axis))
raise TypeError("Unsupported ndim/dtype/axis (%s/%s/%s)." % tup)
return func, a
-'''
+'''
View
7 bottleneck/src/template/func/func.py
@@ -56,7 +56,7 @@
from numpy cimport NPY_FLOAT64 as NPY_float64
from numpy cimport (PyArray_EMPTY, PyArray_TYPE, PyArray_NDIM,
PyArray_SIZE, PyArray_DIMS, import_array,
- PyArray_ArgSort, NPY_QUICKSORT, NPY_CORDER,
+ PyArray_ArgSort, NPY_QUICKSORT, NPY_CORDER,
PyArray_Ravel, PyArray_FillWithScalar, PyArray_Copy,
NPY_BOOL)
@@ -94,8 +94,8 @@
cdef extern from "math.h":
double sqrt(double x)
-
-PARTSORT_ERR_MSG = "`n` (=%d) must be between 1 and %d, inclusive."
+
+PARTSORT_ERR_MSG = "`n` (=%d) must be between 1 and %d, inclusive."
include "nanmax.pyx"
include "nanmin.pyx"
@@ -118,6 +118,7 @@
include "allnan.pyx"
"""
+
def funcpyx(funcs=funcs):
for func in funcs:
template(funcs[func])
View
44 bottleneck/src/template/func/median.py
@@ -16,8 +16,8 @@
return np.FLOAT(NAN)
k = nAXIS >> 1
l = 0
- r = nAXIS - 1
- with nogil:
+ r = nAXIS - 1
+ with nogil:
while l < r:
x = b[k]
i = l
@@ -34,7 +34,7 @@
if i > j: break
if j < k: l = i
if k < i: r = j
- if nAXIS % 2 == 0:
+ if nAXIS % 2 == 0:
amax = MINDTYPE
for i in range(k):
ai = b[i]
@@ -43,12 +43,12 @@
return np.FLOAT(0.5 * (b[k] + amax))
else:
return np.FLOAT(b[k])
-"""
+"""
loop[2] = """\
if nINDEX1 == 0:
PyArray_FillWithScalar(y, NAN)
return y
- for iINDEX0 in range(nINDEX0):
+ for iINDEX0 in range(nINDEX0):
k = nAXIS >> 1
l = 0
r = nAXIS - 1
@@ -68,7 +68,7 @@
if i > j: break
if j < k: l = i
if k < i: r = j
- if nAXIS % 2 == 0:
+ if nAXIS % 2 == 0:
amax = MINDTYPE
for i in range(k):
ai = b[INDEXREPLACE|i|]
@@ -76,7 +76,7 @@
amax = ai
y[INDEXPOP] = 0.5 * (b[INDEXREPLACE|k|] + amax)
else:
- y[INDEXPOP] = CASTb[INDEXREPLACE|k|]
+ y[INDEXPOP] = CASTb[INDEXREPLACE|k|]
return y
"""
loop[3] = """\
@@ -104,7 +104,7 @@
if i > j: break
if j < k: l = i
if k < i: r = j
- if nAXIS % 2 == 0:
+ if nAXIS % 2 == 0:
amax = MINDTYPE
for i in range(k):
ai = b[INDEXREPLACE|i|]
@@ -112,7 +112,7 @@
amax = ai
y[INDEXPOP] = 0.5 * (b[INDEXREPLACE|k|] + amax)
else:
- y[INDEXPOP] = CASTb[INDEXREPLACE|k|]
+ y[INDEXPOP] = CASTb[INDEXREPLACE|k|]
return y
"""
@@ -129,7 +129,7 @@
@cython.wraparound(False)
def NAME_NDIMd_DTYPE_axisAXIS(np.ndarray[np.DTYPE_t, ndim=NDIM] a):
"Median of NDIMd array with dtype=DTYPE along axis=AXIS."
- cdef np.npy_intp i, j = 0, l, r, k
+ cdef np.npy_intp i, j = 0, l, r, k
cdef np.DTYPE_t x, tmp, amax, ai
cdef np.ndarray[np.DTYPE_t, ndim=NDIM] b = PyArray_Copy(a)
"""
@@ -142,7 +142,7 @@ def NAME_NDIMd_DTYPE_axisAXIS(np.ndarray[np.DTYPE_t, ndim=NDIM] a):
# Int dtypes (not axis=None) ------------------------------------------------
ints = deepcopy(floats)
-ints['dtypes'] = INT_DTYPES
+ints['dtypes'] = INT_DTYPES
ints['force_output_dtype'] = 'float64'
ints['loop'] = {}
ints['loop'][1] = loop[1].replace('FLOAT', 'float64')
@@ -172,7 +172,7 @@ def NAME_NDIMd_DTYPE_axisAXIS(np.ndarray[np.DTYPE_t, ndim=NDIM] a):
# Select smallest k elements code used for inner loop of median method:
# http://projects.scipy.org/numpy/attachment/ticket/1213/quickselect.pyx
# (C) 2009 Sturla Molden
-# SciPy license
+# SciPy license
#
# From the original C function (code in public domain) in:
# Fast median search: an ANSI C implementation
@@ -203,11 +203,11 @@ def median(arr, axis=None):
y : ndarray
An array with the same shape as `arr`, except that the specified axis
has been removed. If `arr` is a 0d array, or if axis is None, a scalar
- is returned. `float64` return values are used for integer inputs.
-
+ is returned. `float64` return values are used for integer inputs.
+
See also
--------
- bottleneck.nanmedian: Median along specified axis ignoring NaNs.
+ bottleneck.nanmedian: Median along specified axis ignoring NaNs.
Notes
-----
@@ -226,7 +226,7 @@ def median(arr, axis=None):
array([ 6.5, 4.5, 2.5])
>>> bn.median(a, axis=1)
array([ 7., 2.])
-
+
"""
func, arr = median_selector(arr, axis)
return func(arr)
@@ -234,7 +234,7 @@ def median(arr, axis=None):
def median_selector(arr, axis):
"""
Return median function and array that matches `arr` and `axis`.
-
+
Under the hood Bottleneck uses a separate Cython function for each
combination of ndim, dtype, and axis. A lot of the overhead in
bn.median() is in checking that `axis` is within range, converting `arr`
@@ -250,7 +250,7 @@ def median_selector(arr, axis):
Input array. If `arr` is not an array, a conversion is attempted.
axis : {int, None}
Axis along which the median is to be computed.
-
+
Returns
-------
func : function
@@ -266,13 +266,13 @@ def median_selector(arr, axis):
Create a numpy array:
>>> arr = np.array([1.0, 2.0, 3.0]) <