Coverage for python/lsst/analysis/tools/actions/vector/mathActions.py: 59%

102 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-01-27 10:59 +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/>. 

21from __future__ import annotations 

22 

23__all__ = ( 

24 "ConstantValue", 

25 "AddVector", 

26 "SubtractVector", 

27 "MultiplyVector", 

28 "DivideVector", 

29 "SquareVector", 

30 "SqrtVector", 

31 "RaiseFromBaseVector", 

32 "RaiseToPowerVector", 

33 "Log10Vector", 

34 "FractionalDifference", 

35) 

36 

37import logging 

38 

39import numpy as np 

40from lsst.pex.config import Field 

41from lsst.pex.config.configurableActions import ConfigurableActionField 

42 

43from ...interfaces import KeyedData, KeyedDataSchema, Vector, VectorAction 

44from ...math import divide, log10, sqrt 

45 

46_LOG = logging.getLogger(__name__) 

47 

48 

49class ConstantValue(VectorAction): 

50 """Return a constant scalar value.""" 

51 

52 value = Field[float](doc="A single constant value", optional=False) 

53 

54 def getInputSchema(self) -> KeyedDataSchema: 

55 return () 

56 

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

58 return np.array([self.value]) 

59 

60 

61class AddVector(VectorAction): 

62 """Calculate (A+B).""" 

63 

64 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A") 

65 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B") 

66 

67 def getInputSchema(self) -> KeyedDataSchema: 

68 yield from self.actionA.getInputSchema() # type: ignore 

69 yield from self.actionB.getInputSchema() # type: ignore 

70 

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

72 vecA = self.actionA(data, **kwargs) # type: ignore 

73 vecB = self.actionB(data, **kwargs) # type: ignore 

74 return vecA + vecB 

75 

76 

77class SubtractVector(VectorAction): 

78 """Calculate (A-B).""" 

79 

80 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A") 

81 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B") 

82 

83 def getInputSchema(self) -> KeyedDataSchema: 

84 yield from self.actionA.getInputSchema() # type: ignore 

85 yield from self.actionB.getInputSchema() # type: ignore 

86 

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

88 vecA = self.actionA(data, **kwargs) # type: ignore 

89 vecB = self.actionB(data, **kwargs) # type: ignore 

90 return vecA - vecB 

91 

92 

93class MultiplyVector(VectorAction): 

94 """Calculate (A*B)""" 

95 

96 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A") 

97 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B") 

98 

99 def getInputSchema(self) -> KeyedDataSchema: 

100 yield from self.actionA.getInputSchema() # type: ignore 

101 yield from self.actionB.getInputSchema() # type: ignore 

102 

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

104 vecA = self.actionA(data, **kwargs) # type: ignore 

105 vecB = self.actionB(data, **kwargs) # type: ignore 

106 return vecA * vecB 

107 

108 

109class DivideVector(VectorAction): 

110 """Calculate (A/B)""" 

111 

112 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A") 

113 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B") 

114 

115 def getInputSchema(self) -> KeyedDataSchema: 

116 yield from self.actionA.getInputSchema() # type: ignore 

117 yield from self.actionB.getInputSchema() # type: ignore 

118 

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

120 vecA = self.actionA(data, **kwargs) # type: ignore 

121 vecB = self.actionB(data, **kwargs) # type: ignore 

122 return divide(vecA, vecB) 

123 

124 

125class SqrtVector(VectorAction): 

126 """Calculate sqrt(A)""" 

127 

128 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction) 

129 

130 def getInputSchema(self) -> KeyedDataSchema: 

131 yield from self.actionA.getInputSchema() # type: ignore 

132 

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

134 vecA = self.actionA(data, **kwargs) # type: ignore 

135 return sqrt(vecA) 

136 

137 

138class SquareVector(VectorAction): 

139 """Calculate A**2""" 

140 

141 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction) 

142 

143 def getInputSchema(self) -> KeyedDataSchema: 

144 yield from self.actionA.getInputSchema() # type: ignore 

145 

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

147 vecA = self.actionA(data, **kwargs) # type: ignore 

148 return vecA * vecA 

149 

150 

151class RaiseFromBaseVector(VectorAction): 

152 """Calculate n**A""" 

153 

154 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction) 

155 base = Field[float](doc="The base value to raise to the power of vector values") 

156 

157 def getInputSchema(self) -> KeyedDataSchema: 

158 yield from self.actionA.getInputSchema() # type: ignore 

159 

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

161 vecA = self.actionA(data, **kwargs) # type: ignore 

162 return self.base**vecA 

163 

164 

165class RaiseToPowerVector(VectorAction): 

166 """Calculate A**n""" 

167 

168 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction) 

169 power = Field[float](doc="The power to raise the vector to") 

170 

171 def getInputSchema(self) -> KeyedDataSchema: 

172 yield from self.actionA.getInputSchema() # type: ignore 

173 

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

175 vecA = self.actionA(data, **kwargs) # type: ignore 

176 return vecA**self.power 

177 

178 

179class Log10Vector(VectorAction): 

180 """Calculate log10(A)""" 

181 

182 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction) 

183 

184 def getInputSchema(self) -> KeyedDataSchema: 

185 yield from self.actionA.getInputSchema() # type: ignore 

186 

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

188 vecA = self.actionA(data, **kwargs) # type: ignore 

189 return log10(vecA) 

190 

191 

192class FractionalDifference(VectorAction): 

193 """Calculate (A-B)/B.""" 

194 

195 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A") 

196 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B") 

197 

198 def getInputSchema(self) -> KeyedDataSchema: 

199 yield from self.actionA.getInputSchema() # type: ignore 

200 yield from self.actionB.getInputSchema() # type: ignore 

201 

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

203 vecA = self.actionA(data, **kwargs) # type: ignore 

204 vecB = self.actionB(data, **kwargs) # type: ignore 

205 return divide(vecA - vecB, vecB)