Coverage for python/lsst/analysis/tools/actions/vector/mathActions.py: 59%
102 statements
« prev ^ index » next coverage.py v7.5.1, created at 2024-05-09 04:18 -0700
« prev ^ index » next coverage.py v7.5.1, created at 2024-05-09 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
44from ...math import divide, log10, sqrt
46_LOG = logging.getLogger(__name__)
49class ConstantValue(VectorAction):
50 """Return a constant scalar value."""
52 value = Field[float](doc="A single constant value", optional=False)
54 def getInputSchema(self) -> KeyedDataSchema:
55 return ()
57 def __call__(self, data: KeyedData, **kwargs) -> Vector:
58 return np.array([self.value])
61class AddVector(VectorAction):
62 """Calculate (A+B)."""
64 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
65 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")
67 def getInputSchema(self) -> KeyedDataSchema:
68 yield from self.actionA.getInputSchema() # type: ignore
69 yield from self.actionB.getInputSchema() # type: ignore
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
77class SubtractVector(VectorAction):
78 """Calculate (A-B)."""
80 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
81 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")
83 def getInputSchema(self) -> KeyedDataSchema:
84 yield from self.actionA.getInputSchema() # type: ignore
85 yield from self.actionB.getInputSchema() # type: ignore
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
93class MultiplyVector(VectorAction):
94 """Calculate (A*B)"""
96 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
97 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")
99 def getInputSchema(self) -> KeyedDataSchema:
100 yield from self.actionA.getInputSchema() # type: ignore
101 yield from self.actionB.getInputSchema() # type: ignore
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
109class DivideVector(VectorAction):
110 """Calculate (A/B)"""
112 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
113 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")
115 def getInputSchema(self) -> KeyedDataSchema:
116 yield from self.actionA.getInputSchema() # type: ignore
117 yield from self.actionB.getInputSchema() # type: ignore
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)
125class SqrtVector(VectorAction):
126 """Calculate sqrt(A)"""
128 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction)
130 def getInputSchema(self) -> KeyedDataSchema:
131 yield from self.actionA.getInputSchema() # type: ignore
133 def __call__(self, data: KeyedData, **kwargs) -> Vector:
134 vecA = self.actionA(data, **kwargs) # type: ignore
135 return sqrt(vecA)
138class SquareVector(VectorAction):
139 """Calculate A**2"""
141 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction)
143 def getInputSchema(self) -> KeyedDataSchema:
144 yield from self.actionA.getInputSchema() # type: ignore
146 def __call__(self, data: KeyedData, **kwargs) -> Vector:
147 vecA = self.actionA(data, **kwargs) # type: ignore
148 return vecA * vecA
151class RaiseFromBaseVector(VectorAction):
152 """Calculate n**A"""
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")
157 def getInputSchema(self) -> KeyedDataSchema:
158 yield from self.actionA.getInputSchema() # type: ignore
160 def __call__(self, data: KeyedData, **kwargs) -> Vector:
161 vecA = self.actionA(data, **kwargs) # type: ignore
162 return self.base**vecA
165class RaiseToPowerVector(VectorAction):
166 """Calculate A**n"""
168 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction)
169 power = Field[float](doc="The power to raise the vector to")
171 def getInputSchema(self) -> KeyedDataSchema:
172 yield from self.actionA.getInputSchema() # type: ignore
174 def __call__(self, data: KeyedData, **kwargs) -> Vector:
175 vecA = self.actionA(data, **kwargs) # type: ignore
176 return vecA**self.power
179class Log10Vector(VectorAction):
180 """Calculate log10(A)"""
182 actionA = ConfigurableActionField(doc="Action which supplies vector A", dtype=VectorAction)
184 def getInputSchema(self) -> KeyedDataSchema:
185 yield from self.actionA.getInputSchema() # type: ignore
187 def __call__(self, data: KeyedData, **kwargs) -> Vector:
188 vecA = self.actionA(data, **kwargs) # type: ignore
189 return log10(vecA)
192class FractionalDifference(VectorAction):
193 """Calculate (A-B)/B."""
195 actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
196 actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")
198 def getInputSchema(self) -> KeyedDataSchema:
199 yield from self.actionA.getInputSchema() # type: ignore
200 yield from self.actionB.getInputSchema() # type: ignore
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)