Coverage for src/foapy/ma/_order.py: 100%

23 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-05-17 20:45 +0000

1import numpy as np 

2import numpy.ma as ma 

3 

4from foapy import order as general_order 

5from foapy.exceptions import Not1DArrayException 

6 

7 

8def order(X, return_alphabet=False) -> np.ma.MaskedArray: 

9 """ 

10 Find array sequence in order of their appearance 

11 

12 Parameters 

13 ---------- 

14 X: masked_array 

15 Array to get unique values. 

16 

17 return_alphabet: bool, optional 

18 If True also return array's alphabet 

19 

20 Returns 

21 ------- 

22 result: masked_array or Exception. 

23 Exception if not d1 array, masked_array otherwise. 

24 

25 Examples 

26 -------- 

27 

28 ----1---- 

29 >>> import foapy.ma as ma 

30 >>> a = ['a', 'b', 'a', 'c', 'd'] 

31 >>> b = ma.order(a) 

32 >>> b 

33 [ 

34 [0, -- 0, -- --] 

35 [-- 1 -- -- --] 

36 [-- -- -- 2, --] 

37 [-- -- -- -- 3] 

38 ] 

39 

40 ----2---- 

41 >>> import foapy.ma as ma 

42 >>> a = ['a', 'b', 'a', 'c', 'd'] 

43 >>> result, alphabet = ma.order(a, True) 

44 >>> result 

45 [ 

46 [0, -- 0, -- --] 

47 [-- 1 -- -- --] 

48 [-- -- -- 2, --] 

49 [-- -- -- -- 3] 

50 ] 

51 >>> alphabet 

52 ['a', 'b', 'c', 'd'] 

53 

54 ----3---- 

55 >>> import foapy.ma as ma 

56 >>> a = [1, 4, 1000, 4, 15] 

57 >>> b = ma.order(a) 

58 >>> b 

59 [ 

60 [0 -- -- -- --] 

61 [-- 1 -- 1 --] 

62 [-- -- 2 -- --] 

63 [-- -- -- -- 3] 

64 ] 

65 

66 ----4---- 

67 >>> import foapy.ma as ma 

68 >>> a = ["a", "c", "c", "e", "d", "a"] 

69 >>> b = ma.order(a) 

70 >>> b 

71 [ 

72 [0 -- -- -- -- 0] 

73 [-- 1 1 -- -- --] 

74 [-- -- -- 2 -- --] 

75 [-- -- -- -- 3 --] 

76 ] 

77 

78 ----5---- 

79 >>> import foapy.ma as ma 

80 >>> a = [1, 2, 2, 3, 4, 1] 

81 >>> b = ma.order(a) 

82 >>> b 

83 [ 

84 [0 -- -- -- -- 0] 

85 [-- 1 1 -- -- --] 

86 [-- -- -- 2 -- --] 

87 [-- -- -- -- 3 --] 

88 ] 

89 

90 ----6---- 

91 >>> import foapy.ma as ma 

92 >>> a = ["ATC", "CGT", "ATC"] 

93 >>> b = ma.order(a) 

94 >>> b 

95 [ 

96 [0 -- 0] 

97 [-- 1 --] 

98 ] 

99 

100 ----7---- 

101 >>> import foapy.ma as ma 

102 >>> a = [] 

103 >>> b = ma.order(a) 

104 >>> b 

105 [] 

106 

107 ----8---- 

108 >>> import foapy.ma as ma 

109 >>> a = [[2, 2, 2], [2, 2, 2]] 

110 >>> b = ma.order(a) 

111 >>> b 

112 Exception 

113 

114 ----9---- 

115 >>> import foapy.ma as ma 

116 >>> a = [[[1], [3]], [[6], [9]], [[6], [3]]] 

117 >>> b = ma.order(a) 

118 >>> b 

119 Exception 

120 """ 

121 

122 if X.ndim > 1: # Checking for d1 array 

123 raise Not1DArrayException( 

124 {"message": f"Incorrect array form. Expected d1 array, exists {X.ndim}"} 

125 ) 

126 

127 order, alphabet_values = general_order(ma.getdata(X), return_alphabet=True) 

128 

129 power = len(alphabet_values) 

130 length = len(X) 

131 

132 result_data = np.tile(order, power).reshape(power, length) 

133 alphabet_indecies = np.arange(power).reshape(power, 1) 

134 result_mask = result_data != alphabet_indecies 

135 

136 indecies_selector = np.any(~np.logical_or(result_mask, ma.getmaskarray(X)), axis=1) 

137 

138 if np.any(indecies_selector): 

139 result_data = result_data[indecies_selector] 

140 result_mask = result_mask[indecies_selector] 

141 else: 

142 # If all items are masked we need define empty array explicity 

143 # otherwise, the result shape would be (0, length) 

144 # that affect compare arrays 

145 # (test tests/test_ma_order.py::TestMaOrder::test_void_int_values_with_mask) 

146 result_data = [] 

147 result_mask = [] 

148 

149 result = ma.masked_array(result_data, mask=result_mask) 

150 

151 if return_alphabet: # Checking for get alphabet (optional) 

152 return result, alphabet_values[indecies_selector] 

153 return result