Coverage for python/lsst/analysis/tools/math.py: 19%

85 statements  

« prev     ^ index     » next       coverage.py v7.5.1, created at 2024-05-16 04:38 -0700

1# This file is part of analysis_tools. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (https://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# This program is free software: you can redistribute it and/or modify 

10# it under the terms of the GNU General Public License as published by 

11# the Free Software Foundation, either version 3 of the License, or 

12# (at your option) any later version. 

13# 

14# This program is distributed in the hope that it will be useful, 

15# but WITHOUT ANY WARRANTY; without even the implied warranty of 

16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

17# GNU General Public License for more details. 

18# 

19# You should have received a copy of the GNU General Public License 

20# along with this program. If not, see <https://www.gnu.org/licenses/>. 

21 

22__all__ = ( 

23 "cos", 

24 "divide", 

25 "fluxToMag", 

26 "nanMax", 

27 "nanMean", 

28 "nanMin", 

29 "nanMedian", 

30 "nanSigmaMad", 

31 "nanStd", 

32 "sigmaMad", 

33 "sin", 

34 "sqrt", 

35) 

36 

37import warnings 

38from typing import cast 

39 

40import astropy.units as u 

41import numpy as np 

42import scipy.stats as sps 

43 

44from .interfaces import Scalar, Vector 

45from .warning_control import ( 

46 filterwarnings_action, 

47 numpy_all_nan, 

48 numpy_all_nan_slice, 

49 numpy_divide_zero_divide, 

50 numpy_divide_zero_log, 

51 numpy_divide_zero_log10, 

52 numpy_dof_zero, 

53 numpy_invalid_value_cos, 

54 numpy_invalid_value_divide, 

55 numpy_invalid_value_log, 

56 numpy_invalid_value_log10, 

57 numpy_invalid_value_sin, 

58 numpy_invalid_value_sqrt, 

59 numpy_invalid_value_subtract, 

60 numpy_mean_empty, 

61) 

62 

63 

64def cos(values: Scalar | Vector) -> Scalar | Vector: 

65 """Return the sqrt of values.""" 

66 with warnings.catch_warnings(): 

67 warnings.filterwarnings(filterwarnings_action, numpy_invalid_value_cos) 

68 result = np.cos(values) 

69 return result 

70 

71 

72def divide(dividend: Scalar | Vector, divisor: Scalar | Vector) -> Scalar | Vector: 

73 """Return dividend/divisor.""" 

74 with warnings.catch_warnings(): 

75 warnings.filterwarnings(filterwarnings_action, numpy_divide_zero_divide) 

76 warnings.filterwarnings(filterwarnings_action, numpy_invalid_value_divide) 

77 result = dividend / divisor 

78 return result 

79 

80 

81def fluxToMag( 

82 flux: Scalar | Vector, 

83 flux_unit: u.Unit | str = u.nJy, 

84 return_millimags: bool = False, 

85) -> Scalar | Vector: 

86 """Convert fluxes to magnitudes. 

87 

88 Parameters 

89 ---------- 

90 flux 

91 The flux(es) to convert. 

92 flux_unit 

93 The flux unit, as an object or string. Default astropy.units.nJy. 

94 return_millimags 

95 Whether to return millimags instead of mags. 

96 

97 Returns 

98 ------- 

99 mags 

100 The magnitude(s) converted from the flux(es). 

101 """ 

102 if not isinstance(flux_unit, u.Unit): 

103 flux_unit = u.Unit(flux_unit) 

104 with warnings.catch_warnings(): 

105 warnings.filterwarnings(filterwarnings_action, numpy_divide_zero_log10) 

106 warnings.filterwarnings(filterwarnings_action, numpy_invalid_value_log10) 

107 mag = (np.array(flux) * flux_unit).to(u.ABmag).value # type: ignore 

108 if return_millimags: 

109 mag *= 1000 

110 return mag 

111 

112 

113def log(values: Scalar | Vector) -> Scalar | Vector: 

114 """Return the natural logarithm of values.""" 

115 with warnings.catch_warnings(): 

116 warnings.filterwarnings(filterwarnings_action, numpy_divide_zero_log) 

117 warnings.filterwarnings(filterwarnings_action, numpy_invalid_value_log) 

118 result = np.log(values) 

119 return result 

120 

121 

122def log10(values: Scalar | Vector) -> Scalar | Vector: 

123 """Return the natural logarithm of values.""" 

124 with warnings.catch_warnings(): 

125 warnings.filterwarnings(filterwarnings_action, numpy_divide_zero_log10) 

126 warnings.filterwarnings(filterwarnings_action, numpy_invalid_value_log10) 

127 result = np.log10(values) 

128 return result 

129 

130 

131def nanSigmaMad(vector: Vector) -> Scalar: 

132 """Return the sigma_MAD of a vector.""" 

133 with warnings.catch_warnings(): 

134 # This is needed to catch inf median in sigma_mad 

135 warnings.filterwarnings(filterwarnings_action, numpy_invalid_value_subtract) 

136 result = cast(Scalar, sps.median_abs_deviation(vector, scale="normal", nan_policy="omit")) 

137 return result 

138 

139 

140def nanMax(vector: Vector) -> Scalar: 

141 """Return the max of a vector.""" 

142 with warnings.catch_warnings(): 

143 warnings.filterwarnings(filterwarnings_action, numpy_all_nan) 

144 result = float(np.nanmax(vector)) 

145 return cast(Scalar, result) 

146 

147 

148def nanMean(vector: Vector) -> Scalar: 

149 """Return the mean of a vector.""" 

150 with warnings.catch_warnings(): 

151 warnings.filterwarnings(filterwarnings_action, numpy_all_nan_slice) 

152 warnings.filterwarnings(filterwarnings_action, numpy_mean_empty) 

153 result = float(np.nanmean(vector)) 

154 return cast(Scalar, result) 

155 

156 

157def nanMedian(vector: Vector) -> Scalar: 

158 """Return the median of a vector.""" 

159 with warnings.catch_warnings(): 

160 warnings.filterwarnings(filterwarnings_action, numpy_all_nan_slice) 

161 warnings.filterwarnings(filterwarnings_action, numpy_mean_empty) 

162 result = float(np.nanmedian(vector)) 

163 return cast(Scalar, result) 

164 

165 

166def nanMin(vector: Vector) -> Scalar: 

167 """Return the max of a vector.""" 

168 with warnings.catch_warnings(): 

169 warnings.filterwarnings(filterwarnings_action, numpy_all_nan) 

170 result = float(np.nanmin(vector)) 

171 return cast(Scalar, result) 

172 

173 

174def nanStd(vector: Vector) -> Scalar: 

175 with warnings.catch_warnings(): 

176 warnings.filterwarnings(filterwarnings_action, numpy_dof_zero) 

177 result = float(np.nanstd(vector)) 

178 return cast(Scalar, result) 

179 

180 

181def sigmaMad(vector: Vector) -> Scalar: 

182 return cast(Scalar, sps.median_abs_deviation(vector, scale="normal", nan_policy="propagate")) 

183 

184 

185def sin(values: Scalar | Vector) -> Scalar | Vector: 

186 """Return the sin of values.""" 

187 with warnings.catch_warnings(): 

188 warnings.filterwarnings(filterwarnings_action, numpy_invalid_value_sin) 

189 result = np.sin(values) 

190 return result 

191 

192 

193def sqrt(values: Scalar | Vector) -> Scalar | Vector: 

194 """Return the sqrt of values.""" 

195 with warnings.catch_warnings(): 

196 warnings.filterwarnings(filterwarnings_action, numpy_invalid_value_sqrt) 

197 result = np.sqrt(values) 

198 return result