Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/bottleneck/tests/util.py: 9%

124 statements  

« prev     ^ index     » next       coverage.py v7.2.2, created at 2023-03-23 06:06 +0000

1import numpy as np 

2import bottleneck as bn 

3 

4INT_DTYPES = [np.int64, np.int32] 

5FLOAT_DTYPES = [np.float64, np.float32] 

6DTYPES = tuple(FLOAT_DTYPES + INT_DTYPES) 

7 

8 

9def get_functions(module_name, as_string=False): 

10 """Returns a list of functions, optionally as string function names""" 

11 if module_name == "all": 

12 funcs = [] 

13 funcs_in_dict = func_dict() 

14 for key in funcs_in_dict: 

15 for func in funcs_in_dict[key]: 

16 funcs.append(func) 

17 else: 

18 funcs = func_dict()[module_name] 

19 if as_string: 

20 funcs = [f.__name__ for f in funcs] 

21 return funcs 

22 

23 

24def func_dict(): 

25 d = {} 

26 d["reduce"] = [ 

27 bn.nansum, 

28 bn.nanmean, 

29 bn.nanstd, 

30 bn.nanvar, 

31 bn.nanmin, 

32 bn.nanmax, 

33 bn.median, 

34 bn.nanmedian, 

35 bn.ss, 

36 bn.nanargmin, 

37 bn.nanargmax, 

38 bn.anynan, 

39 bn.allnan, 

40 ] 

41 d["move"] = [ 

42 bn.move_sum, 

43 bn.move_mean, 

44 bn.move_std, 

45 bn.move_var, 

46 bn.move_min, 

47 bn.move_max, 

48 bn.move_argmin, 

49 bn.move_argmax, 

50 bn.move_median, 

51 bn.move_rank, 

52 ] 

53 d["nonreduce"] = [bn.replace] 

54 d["nonreduce_axis"] = [ 

55 bn.partition, 

56 bn.argpartition, 

57 bn.rankdata, 

58 bn.nanrankdata, 

59 bn.push, 

60 ] 

61 return d 

62 

63 

64# --------------------------------------------------------------------------- 

65 

66 

67def arrays(func_name, dtypes=DTYPES): 

68 return array_iter(array_generator, func_name, dtypes) 

69 

70 

71def array_iter(arrays_func, *args): 

72 for a in arrays_func(*args): 

73 if a.ndim < 2: 

74 yield a 

75 # this is good for an extra check but in everyday development it 

76 # is a pain because it doubles the unit test run time 

77 # elif a.ndim == 3: 

78 # for axes in permutations(range(a.ndim)): 

79 # yield np.transpose(a, axes) 

80 else: 

81 yield a 

82 yield a.T 

83 

84 

85def array_generator(func_name, dtypes): 

86 """Iterator that yields arrays to use for unit testing.""" 

87 

88 f_dtypes = list(set(dtypes) & set(FLOAT_DTYPES)) 

89 

90 # define nan and inf 

91 if func_name in ("partition", "argpartition"): 

92 nan = 0 

93 else: 

94 nan = np.nan 

95 if func_name in ("move_sum", "move_mean", "move_std", "move_var"): 

96 # these functions can't handle inf 

97 inf = 8 

98 else: 

99 inf = np.inf 

100 

101 # nan and inf 

102 for dtype in f_dtypes: 

103 yield np.array([inf, nan], dtype=dtype) 

104 yield np.array([inf, -inf], dtype=dtype) 

105 yield np.array([nan, 2, 3], dtype=dtype) 

106 yield np.array([-inf, 2, 3], dtype=dtype) 

107 if func_name != "nanargmin": 

108 yield np.array([nan, inf], dtype=dtype) 

109 

110 # byte swapped 

111 yield np.array([1, 2, 3], dtype=">f4") 

112 yield np.array([1, 2, 3], dtype="<f4") 

113 

114 # make sure slow is callable 

115 yield np.array([1, 2, 3], dtype=np.float16) 

116 

117 # regression tests 

118 for dtype in dtypes: 

119 yield np.array([1, 2, 3], dtype=dtype) + 1e9 # check that move_std is robust 

120 yield np.array([0, 0, 0], dtype=dtype) # nanargmax/nanargmin 

121 

122 for dtype in f_dtypes: 

123 yield np.array([1, nan, nan, 2], dtype=dtype) # nanmedian 

124 

125 yield np.array([2 ** 31], dtype=np.int64) # overflows on windows 

126 

127 for dtype in dtypes: 

128 yield np.array([[1, 2], [3, 4]], dtype=dtype)[..., np.newaxis] # issue #183 

129 

130 # ties 

131 for dtype in dtypes: 

132 yield np.array([0, 0, 0], dtype=dtype) 

133 yield np.array([1, 1, 1], dtype=dtype) 

134 

135 # 0d input 

136 if not func_name.startswith("move"): 

137 for dtype in dtypes: 

138 yield np.array(-9, dtype=dtype) 

139 yield np.array(0, dtype=dtype) 

140 yield np.array(9, dtype=dtype) 

141 if dtype in f_dtypes: 

142 yield np.array(-inf, dtype=dtype) 

143 yield np.array(inf, dtype=dtype) 

144 yield np.array(nan, dtype=dtype) 

145 

146 # automate a bunch of arrays to test 

147 ss = {} 

148 ss[0] = {"size": 0, "shapes": [(0,), (0, 0), (2, 0), (2, 0, 1)]} 

149 ss[1] = {"size": 8, "shapes": [(8,)]} 

150 ss[2] = {"size": 12, "shapes": [(2, 6), (3, 4)]} 

151 ss[3] = {"size": 16, "shapes": [(2, 2, 4)]} 

152 ss[4] = {"size": 24, "shapes": [(1, 2, 3, 4)]} 

153 for seed in (1, 2): 

154 rs = np.random.RandomState(seed) 

155 for ndim in ss: 

156 size = ss[ndim]["size"] 

157 shapes = ss[ndim]["shapes"] 

158 for dtype in dtypes: 

159 a = np.arange(size, dtype=dtype) 

160 if issubclass(a.dtype.type, np.inexact): 

161 if func_name not in ("nanargmin", "nanargmax"): 

162 # numpy can't handle eg np.nanargmin([np.nan, np.inf]) 

163 idx = rs.rand(*a.shape) < 0.2 

164 a[idx] = inf 

165 idx = rs.rand(*a.shape) < 0.2 

166 a[idx] = nan 

167 idx = rs.rand(*a.shape) < 0.2 

168 a[idx] *= -1 

169 rs.shuffle(a) 

170 for shape in shapes: 

171 yield a.reshape(shape) 

172 

173 # non-contiguous arrays 

174 for dtype in dtypes: 

175 yield np.array([[1, 2], [3, 4]], dtype=dtype)[:, [1]] # gh 161 

176 

177 for dtype in dtypes: 

178 # 1d 

179 a = np.arange(12).astype(dtype) 

180 for start in range(3): 

181 for step in range(1, 3): 

182 yield a[start::step] # don't use astype here; copy created 

183 for dtype in dtypes: 

184 # 2d 

185 a = np.arange(12).reshape(4, 3).astype(dtype) 

186 yield a[::2] 

187 yield a[:, ::2] 

188 yield a[::2][:, ::2] 

189 for dtype in dtypes: 

190 # 3d 

191 a = np.arange(24).reshape(2, 3, 4).astype(dtype) 

192 for start in range(2): 

193 for step in range(1, 2): 

194 yield a[start::step] 

195 yield a[:, start::step] 

196 yield a[:, :, start::step] 

197 yield a[start::step][::2] 

198 yield a[start::step][::2][:, ::2] 

199 

200 

201def array_order(a): 

202 f = a.flags 

203 string = [] 

204 if f.c_contiguous: 

205 string.append("C") 

206 if f.f_contiguous: 

207 string.append("F") 

208 if len(string) == 0: 

209 string.append("N") 

210 return ",".join(string)