Coverage for python / lsst / analysis / tools / actions / plot / calculateRange.py: 62%

32 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-05-05 18:53 +0000

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 

22from __future__ import annotations 

23 

24__all__ = ( 

25 "MinMax", 

26 "Med2Mad", 

27 "Asinh", 

28 "Perc", 

29 "Linear", 

30) 

31 

32from typing import cast 

33 

34import numpy as np 

35from astropy.visualization import ( 

36 AsinhStretch, 

37 LinearStretch, 

38 PercentileInterval, 

39) 

40from lsst.pex.config import Field 

41 

42from ...interfaces import Tensor, TensorAction, Vector, VectorAction 

43from ...math import nanMax, nanMedian, nanMin, nanSigmaMad 

44 

45 

46class MinMax(VectorAction): 

47 """Return the maximum and minimum values of an input vector to use as the 

48 minimum and maximum values of a colorbar range. 

49 

50 Parameters 

51 ---------- 

52 data : `Vector` 

53 A vector containing the data whose minimum and maximum are to be 

54 returned. 

55 

56 Returns 

57 ------- 

58 A two-element vector containing the minimum and maximum values of `data`. 

59 """ 

60 

61 def __call__(self, data: Vector, **kwargs) -> Vector: 

62 if len(data) == 0: 

63 return cast(Vector, [np.nan, np.nan]) 

64 else: 

65 return cast(Vector, [nanMin(data), nanMax(data)]) 

66 

67 

68class Med2Mad(VectorAction): 

69 """Return the median +/- 2*nansigmamad values of an input vector to use 

70 as the minimum and maximum values of a colorbar range. 

71 

72 Parameters 

73 ---------- 

74 data : `Vector` 

75 A vector containing the data whose median +/- 2*nansigmamad are to 

76 be returned. 

77 

78 Returns 

79 ------- 

80 A two-element vector containing the median +/- 2*nansigmamad values of 

81 `data`. 

82 """ 

83 

84 def __call__(self, data: Vector, **kwargs) -> Vector: 

85 med = nanMedian(data) 

86 mad = nanSigmaMad(data) 

87 cmin = med - 2 * mad 

88 cmax = med + 2 * mad 

89 return cast(Vector, [cmin, cmax]) 

90 

91 

92class Perc(VectorAction): 

93 """Return the minimum and maximum values of an input vector after 

94 excluding a fraction of values from either end of the distribution. 

95 

96 Parameters 

97 ---------- 

98 data : `Vector` 

99 A vector containing the data whose minimum and maximum are to be 

100 calculated following the exclusion of a fraction of extreme upper 

101 and lower values. 

102 

103 Returns 

104 ------- 

105 A two-element vector containing the minimum and maximum values of 

106 the input vector, following the exclusion of a fraction of extreme 

107 upper and lower values. 

108 """ 

109 

110 percentile = Field[float]( 

111 doc="The fraction of values to keep. The same fraction of values is " 

112 "eliminated from both ends of the distribution. Default: 97.", 

113 default=97.0, 

114 ) 

115 

116 def __call__(self, data, **kwargs): 

117 return PercentileInterval(self.percentile).get_limits(data) 

118 

119 

120class Asinh(VectorAction, TensorAction): 

121 """Transform the input vector/tensor using the asinh stretch. 

122 

123 Parameters 

124 ---------- 

125 data : `Vector` | `Tensor` 

126 A vector or a tensor containing the data to be transformed 

127 using the asinh stretch. 

128 

129 Returns 

130 ------- 

131 A vector or tensor of the same size as the input, transformed 

132 using the asinh stretch. 

133 """ 

134 

135 def __call__(self, data: Vector | Tensor, **kwargs) -> Vector | Tensor: 

136 return AsinhStretch()(data) 

137 

138 

139class Linear(VectorAction, TensorAction): 

140 """Transform the input vector/tensor using the linear stretch. 

141 

142 Parameters 

143 ---------- 

144 data : `Vector` 

145 A vector or a tensor containing the data to be transformed 

146 using the linear stretch. 

147 

148 Returns 

149 ------- 

150 A vector or tensor of the same size as the input, transformed 

151 using the linear stretch. 

152 """ 

153 

154 intercept = Field[float](doc="The offset of the linear stretch. Default: 0.", default=0.0) 

155 

156 slope = Field[float](doc="The slope of the linear stretch. Default: 1.", default=1.0) 

157 

158 def __call__(self, data: Vector | Tensor, **kwargs) -> Vector | Tensor: 

159 return LinearStretch(self.slope, self.intercept)(data)