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

101 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-07-23 09:43 +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 

44 

45_LOG = logging.getLogger(__name__) 

46 

47 

48class ConstantValue(VectorAction): 

49 """Return a constant scalar value.""" 

50 

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

52 

53 def getInputSchema(self) -> KeyedDataSchema: 

54 return () 

55 

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

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

58 

59 

60class AddVector(VectorAction): 

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

62 

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

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

65 

66 def getInputSchema(self) -> KeyedDataSchema: 

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

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

69 

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

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

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

73 return vecA + vecB 

74 

75 

76class SubtractVector(VectorAction): 

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

78 

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

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

81 

82 def getInputSchema(self) -> KeyedDataSchema: 

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

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

85 

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

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

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

89 return vecA - vecB 

90 

91 

92class MultiplyVector(VectorAction): 

93 """Calculate (A*B)""" 

94 

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

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

97 

98 def getInputSchema(self) -> KeyedDataSchema: 

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

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

101 

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

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

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

105 return vecA * vecB 

106 

107 

108class DivideVector(VectorAction): 

109 """Calculate (A/B)""" 

110 

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

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

113 

114 def getInputSchema(self) -> KeyedDataSchema: 

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

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

117 

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

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

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

121 return vecA / vecB 

122 

123 

124class SqrtVector(VectorAction): 

125 """Calculate sqrt(A)""" 

126 

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

128 

129 def getInputSchema(self) -> KeyedDataSchema: 

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

131 

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

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

134 return np.sqrt(vecA) 

135 

136 

137class SquareVector(VectorAction): 

138 """Calculate A**2""" 

139 

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

141 

142 def getInputSchema(self) -> KeyedDataSchema: 

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

144 

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

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

147 return vecA * vecA 

148 

149 

150class RaiseFromBaseVector(VectorAction): 

151 """Calculate n**A""" 

152 

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

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

155 

156 def getInputSchema(self) -> KeyedDataSchema: 

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

158 

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

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

161 return self.base**vecA 

162 

163 

164class RaiseToPowerVector(VectorAction): 

165 """Calculate A**n""" 

166 

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

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

169 

170 def getInputSchema(self) -> KeyedDataSchema: 

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

172 

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

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

175 return vecA**self.power 

176 

177 

178class Log10Vector(VectorAction): 

179 """Calculate log10(A)""" 

180 

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

182 

183 def getInputSchema(self) -> KeyedDataSchema: 

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

185 

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

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

188 return np.log10(vecA) 

189 

190 

191class FractionalDifference(VectorAction): 

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

193 

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

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

196 

197 def getInputSchema(self) -> KeyedDataSchema: 

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

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

200 

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

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

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

204 return (vecA - vecB) / vecB