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-06 04:18 -0700
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-06 04:18 -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/>.
21from __future__ import annotations
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)
37import logging
39import numpy as np
40from lsst.pex.config import Field
41from lsst.pex.config.configurableActions import ConfigurableActionField
43from ...interfaces import KeyedData, KeyedDataSchema, Vector, VectorAction
45_LOG = logging.getLogger(__name__)
48class ConstantValue(VectorAction):
49 """Return a constant scalar value."""
51 value = Field[float](doc="A single constant value", optional=False)
53 def getInputSchema(self) -> KeyedDataSchema:
54 return ()
56 def __call__(self, data: KeyedData, **kwargs) -> Vector:
57 return np.array([self.value])
60class AddVector(VectorAction):
61 """Calculate (A+B)."""
63 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
64 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")
66 def getInputSchema(self) -> KeyedDataSchema:
67 yield from self.actionA.getInputSchema() # type: ignore
68 yield from self.actionB.getInputSchema() # type: ignore
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
76class SubtractVector(VectorAction):
77 """Calculate (A-B)."""
79 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
80 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")
82 def getInputSchema(self) -> KeyedDataSchema:
83 yield from self.actionA.getInputSchema() # type: ignore
84 yield from self.actionB.getInputSchema() # type: ignore
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
92class MultiplyVector(VectorAction):
93 """Calculate (A*B)"""
95 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
96 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")
98 def getInputSchema(self) -> KeyedDataSchema:
99 yield from self.actionA.getInputSchema() # type: ignore
100 yield from self.actionB.getInputSchema() # type: ignore
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
108class DivideVector(VectorAction):
109 """Calculate (A/B)"""
111 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
112 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")
114 def getInputSchema(self) -> KeyedDataSchema:
115 yield from self.actionA.getInputSchema() # type: ignore
116 yield from self.actionB.getInputSchema() # type: ignore
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
124class SqrtVector(VectorAction):
125 """Calculate sqrt(A)"""
127 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction)
129 def getInputSchema(self) -> KeyedDataSchema:
130 yield from self.actionA.getInputSchema() # type: ignore
132 def __call__(self, data: KeyedData, **kwargs) -> Vector:
133 vecA = self.actionA(data, **kwargs) # type: ignore
134 return np.sqrt(vecA)
137class SquareVector(VectorAction):
138 """Calculate A**2"""
140 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction)
142 def getInputSchema(self) -> KeyedDataSchema:
143 yield from self.actionA.getInputSchema() # type: ignore
145 def __call__(self, data: KeyedData, **kwargs) -> Vector:
146 vecA = self.actionA(data, **kwargs) # type: ignore
147 return vecA * vecA
150class RaiseFromBaseVector(VectorAction):
151 """Calculate n**A"""
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")
156 def getInputSchema(self) -> KeyedDataSchema:
157 yield from self.actionA.getInputSchema() # type: ignore
159 def __call__(self, data: KeyedData, **kwargs) -> Vector:
160 vecA = self.actionA(data, **kwargs) # type: ignore
161 return self.base**vecA
164class RaiseToPowerVector(VectorAction):
165 """Calculate A**n"""
167 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction)
168 power = Field[float](doc="The power to raise the vector to")
170 def getInputSchema(self) -> KeyedDataSchema:
171 yield from self.actionA.getInputSchema() # type: ignore
173 def __call__(self, data: KeyedData, **kwargs) -> Vector:
174 vecA = self.actionA(data, **kwargs) # type: ignore
175 return vecA**self.power
178class Log10Vector(VectorAction):
179 """Calculate log10(A)"""
181 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction)
183 def getInputSchema(self) -> KeyedDataSchema:
184 yield from self.actionA.getInputSchema() # type: ignore
186 def __call__(self, data: KeyedData, **kwargs) -> Vector:
187 vecA = self.actionA(data, **kwargs) # type: ignore
188 return np.log10(vecA)
191class FractionalDifference(VectorAction):
192 """Calculate (A-B)/B."""
194 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
195 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")
197 def getInputSchema(self) -> KeyedDataSchema:
198 yield from self.actionA.getInputSchema() # type: ignore
199 yield from self.actionB.getInputSchema() # type: ignore
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