Coverage for src/hdmf/array.py: 50%

137 statements  

« prev     ^ index     » next       coverage.py v7.2.5, created at 2023-07-21 22:12 +0000

1from abc import abstractmethod, ABCMeta 

2 

3import numpy as np 

4 

5 

6class Array: 

7 

8 def __init__(self, data): 

9 self.__data = data 

10 if hasattr(data, 'dtype'): 10 ↛ 13line 10 didn't jump to line 13, because the condition on line 10 was never false

11 self.dtype = data.dtype 

12 else: 

13 tmp = data 

14 while isinstance(tmp, (list, tuple)): 

15 tmp = tmp[0] 

16 self.dtype = type(tmp) 

17 

18 @property 

19 def data(self): 

20 return self.__data 

21 

22 def __len__(self): 

23 return len(self.__data) 

24 

25 def get_data(self): 

26 return self.__data 

27 

28 def __getidx__(self, arg): 

29 return self.__data[arg] 

30 

31 def __sliceiter(self, arg): 

32 return (x for x in range(*arg.indices(len(self)))) 

33 

34 def __getitem__(self, arg): 

35 if isinstance(arg, list): 35 ↛ 36line 35 didn't jump to line 36, because the condition on line 35 was never true

36 idx = list() 

37 for i in arg: 

38 if isinstance(i, slice): 

39 idx.extend(x for x in self.__sliceiter(i)) 

40 else: 

41 idx.append(i) 

42 return np.fromiter((self.__getidx__(x) for x in idx), dtype=self.dtype) 

43 elif isinstance(arg, slice): 

44 return np.fromiter((self.__getidx__(x) for x in self.__sliceiter(arg)), dtype=self.dtype) 

45 elif isinstance(arg, tuple): 45 ↛ 46line 45 didn't jump to line 46, because the condition on line 45 was never true

46 return (self.__getidx__(arg[0]), self.__getidx__(arg[1])) 

47 else: 

48 return self.__getidx__(arg) 

49 

50 

51class AbstractSortedArray(Array, metaclass=ABCMeta): 

52 ''' 

53 An abstract class for representing sorted array 

54 ''' 

55 

56 @abstractmethod 

57 def find_point(self, val): 

58 pass 

59 

60 def get_data(self): 

61 return self 

62 

63 def __lower(self, other): 

64 ins = self.find_point(other) 

65 return ins 

66 

67 def __upper(self, other): 

68 ins = self.__lower(other) 

69 while self[ins] == other: 

70 ins += 1 

71 return ins 

72 

73 def __lt__(self, other): 

74 ins = self.__lower(other) 

75 return slice(0, ins) 

76 

77 def __le__(self, other): 

78 ins = self.__upper(other) 

79 return slice(0, ins) 

80 

81 def __gt__(self, other): 

82 ins = self.__upper(other) 

83 return slice(ins, len(self)) 

84 

85 def __ge__(self, other): 

86 ins = self.__lower(other) 

87 return slice(ins, len(self)) 

88 

89 @staticmethod 

90 def __sort(a): 

91 if isinstance(a, tuple): 

92 return a[0] 

93 else: 

94 return a 

95 

96 def __eq__(self, other): 

97 if isinstance(other, list): 97 ↛ 98line 97 didn't jump to line 98, because the condition on line 97 was never true

98 ret = list() 

99 for i in other: 

100 eq = self == i 

101 ret.append(eq) 

102 ret = sorted(ret, key=self.__sort) 

103 tmp = list() 

104 for i in range(1, len(ret)): 

105 a, b = ret[i - 1], ret[i] 

106 if isinstance(a, tuple): 

107 if isinstance(b, tuple): 

108 if a[1] >= b[0]: 

109 b[0] = a[0] 

110 else: 

111 tmp.append(slice(*a)) 

112 else: 

113 if b > a[1]: 

114 tmp.append(slice(*a)) 

115 elif b == a[1]: 

116 a[1] == b + 1 

117 else: 

118 ret[i] = a 

119 else: 

120 if isinstance(b, tuple): 

121 if a < b[0]: 

122 tmp.append(a) 

123 else: 

124 if b - a == 1: 

125 ret[i] = (a, b) 

126 else: 

127 tmp.append(a) 

128 if isinstance(ret[-1], tuple): 

129 tmp.append(slice(*ret[-1])) 

130 else: 

131 tmp.append(ret[-1]) 

132 ret = tmp 

133 return ret 

134 elif isinstance(other, tuple): 134 ↛ 135line 134 didn't jump to line 135, because the condition on line 134 was never true

135 ge = self >= other[0] 

136 ge = ge.start 

137 lt = self < other[1] 

138 lt = lt.stop 

139 if ge == lt: 

140 return ge 

141 else: 

142 return slice(ge, lt) 

143 else: 

144 lower = self.__lower(other) 

145 upper = self.__upper(other) 

146 d = upper - lower 

147 if d == 1: 147 ↛ 149line 147 didn't jump to line 149, because the condition on line 147 was never false

148 return lower 

149 elif d == 0: 

150 return None 

151 else: 

152 return slice(lower, upper) 

153 

154 def __ne__(self, other): 

155 eq = self == other 

156 if isinstance(eq, tuple): 156 ↛ 157line 156 didn't jump to line 157, because the condition on line 156 was never true

157 return [slice(0, eq[0]), slice(eq[1], len(self))] 

158 else: 

159 return [slice(0, eq), slice(eq + 1, len(self))] 

160 

161 

162class SortedArray(AbstractSortedArray): 

163 ''' 

164 A class for wrapping sorted arrays. This class overrides 

165 <,>,<=,>=,==, and != to leverage the sorted content for 

166 efficiency. 

167 ''' 

168 

169 def __init__(self, array): 

170 super().__init__(array) 

171 

172 def find_point(self, val): 

173 return np.searchsorted(self.data, val) 

174 

175 

176class LinSpace(SortedArray): 

177 

178 def __init__(self, start, stop, step): 

179 self.start = start 

180 self.stop = stop 

181 self.step = step 

182 self.dtype = float if any(isinstance(s, float) for s in (start, stop, step)) else int 

183 self.__len = int((stop - start) / step) 

184 

185 def __len__(self): 

186 return self.__len 

187 

188 def find_point(self, val): 

189 nsteps = (val - self.start) / self.step 

190 fl = int(nsteps) 

191 if fl == nsteps: 191 ↛ 194line 191 didn't jump to line 194, because the condition on line 191 was never false

192 return int(fl) 

193 else: 

194 return int(fl + 1) 

195 

196 def __getidx__(self, arg): 

197 return self.start + self.step * arg