Coverage for python / lsst / analysis / tools / actions / vector / mathActions.py: 59%
116 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-04 17:42 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-04 17:42 +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
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 "CosVector",
36 "SinVector",
37)
39import logging
41import numpy as np
43from lsst.pex.config import Field
44from lsst.pex.config.configurableActions import ConfigurableActionField
46from ...interfaces import KeyedData, KeyedDataSchema, Vector, VectorAction
47from ...math import cos, divide, log10, sin, sqrt
49_LOG = logging.getLogger(__name__)
52class ConstantValue(VectorAction):
53 """Return a constant scalar value."""
55 value = Field[float](doc="A single constant value", optional=False)
57 def getInputSchema(self) -> KeyedDataSchema:
58 return ()
60 def __call__(self, data: KeyedData, **kwargs) -> Vector:
61 return np.array([self.value])
64class AddVector(VectorAction):
65 """Calculate (A+B)."""
67 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
68 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")
70 def getInputSchema(self) -> KeyedDataSchema:
71 yield from self.actionA.getInputSchema() # type: ignore
72 yield from self.actionB.getInputSchema() # type: ignore
74 def __call__(self, data: KeyedData, **kwargs) -> Vector:
75 vecA = self.actionA(data, **kwargs) # type: ignore
76 vecB = self.actionB(data, **kwargs) # type: ignore
77 return vecA + vecB
80class SubtractVector(VectorAction):
81 """Calculate (A-B)."""
83 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
84 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")
86 def getInputSchema(self) -> KeyedDataSchema:
87 yield from self.actionA.getInputSchema() # type: ignore
88 yield from self.actionB.getInputSchema() # type: ignore
90 def __call__(self, data: KeyedData, **kwargs) -> Vector:
91 vecA = self.actionA(data, **kwargs) # type: ignore
92 vecB = self.actionB(data, **kwargs) # type: ignore
93 return vecA - vecB
96class MultiplyVector(VectorAction):
97 """Calculate (A*B)"""
99 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
100 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")
102 def getInputSchema(self) -> KeyedDataSchema:
103 yield from self.actionA.getInputSchema() # type: ignore
104 yield from self.actionB.getInputSchema() # type: ignore
106 def __call__(self, data: KeyedData, **kwargs) -> Vector:
107 vecA = self.actionA(data, **kwargs) # type: ignore
108 vecB = self.actionB(data, **kwargs) # type: ignore
109 return vecA * vecB
112class DivideVector(VectorAction):
113 """Calculate (A/B)"""
115 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
116 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")
118 def getInputSchema(self) -> KeyedDataSchema:
119 yield from self.actionA.getInputSchema() # type: ignore
120 yield from self.actionB.getInputSchema() # type: ignore
122 def __call__(self, data: KeyedData, **kwargs) -> Vector:
123 vecA = self.actionA(data, **kwargs) # type: ignore
124 vecB = self.actionB(data, **kwargs) # type: ignore
125 return divide(vecA, vecB)
128class SqrtVector(VectorAction):
129 """Calculate sqrt(A)"""
131 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction)
133 def getInputSchema(self) -> KeyedDataSchema:
134 yield from self.actionA.getInputSchema() # type: ignore
136 def __call__(self, data: KeyedData, **kwargs) -> Vector:
137 vecA = self.actionA(data, **kwargs) # type: ignore
138 return sqrt(vecA)
141class SquareVector(VectorAction):
142 """Calculate A**2"""
144 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction)
146 def getInputSchema(self) -> KeyedDataSchema:
147 yield from self.actionA.getInputSchema() # type: ignore
149 def __call__(self, data: KeyedData, **kwargs) -> Vector:
150 vecA = self.actionA(data, **kwargs) # type: ignore
151 return vecA * vecA
154class RaiseFromBaseVector(VectorAction):
155 """Calculate n**A"""
157 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction)
158 base = Field[float](doc="The base value to raise to the power of vector values")
160 def getInputSchema(self) -> KeyedDataSchema:
161 yield from self.actionA.getInputSchema() # type: ignore
163 def __call__(self, data: KeyedData, **kwargs) -> Vector:
164 vecA = self.actionA(data, **kwargs) # type: ignore
165 return self.base**vecA
168class RaiseToPowerVector(VectorAction):
169 """Calculate A**n"""
171 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction)
172 power = Field[float](doc="The power to raise the vector to")
174 def getInputSchema(self) -> KeyedDataSchema:
175 yield from self.actionA.getInputSchema() # type: ignore
177 def __call__(self, data: KeyedData, **kwargs) -> Vector:
178 vecA = self.actionA(data, **kwargs) # type: ignore
179 return vecA**self.power
182class Log10Vector(VectorAction):
183 """Calculate log10(A)"""
185 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction)
187 def getInputSchema(self) -> KeyedDataSchema:
188 yield from self.actionA.getInputSchema() # type: ignore
190 def __call__(self, data: KeyedData, **kwargs) -> Vector:
191 vecA = self.actionA(data, **kwargs) # type: ignore
192 return log10(vecA)
195class FractionalDifference(VectorAction):
196 """Calculate (A-B)/B."""
198 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
199 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")
201 def getInputSchema(self) -> KeyedDataSchema:
202 yield from self.actionA.getInputSchema() # type: ignore
203 yield from self.actionB.getInputSchema() # type: ignore
205 def __call__(self, data: KeyedData, **kwargs) -> Vector:
206 vecA = self.actionA(data, **kwargs) # type: ignore
207 vecB = self.actionB(data, **kwargs) # type: ignore
208 return divide(vecA - vecB, vecB)
211class CosVector(VectorAction):
212 """Calculate cos(A)"""
214 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction)
216 def getInputSchema(self) -> KeyedDataSchema:
217 yield from self.actionA.getInputSchema() # type: ignore
219 def __call__(self, data: KeyedData, **kwargs) -> Vector:
220 vecA = self.actionA(data, **kwargs) # type: ignore
221 return cos(vecA)
224class SinVector(VectorAction):
225 """Calculate sin(A)"""
227 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction)
229 def getInputSchema(self) -> KeyedDataSchema:
230 yield from self.actionA.getInputSchema() # type: ignore
232 def __call__(self, data: KeyedData, **kwargs) -> Vector:
233 vecA = self.actionA(data, **kwargs) # type: ignore
234 return sin(vecA)