Coverage for python/lsst/analysis/tools/actions/scalar/scalarActions.py: 54%
69 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-16 01:27 -0800
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-16 01:27 -0800
1from __future__ import annotations
3import operator
4from typing import cast
6import numpy as np
7from lsst.pex.config import ChoiceField, Field
9from ...interfaces import KeyedData, KeyedDataSchema, Scalar, ScalarAction, Vector
10from ...statistics import nansigmaMad
13class MedianAction(ScalarAction):
14 vectorKey = Field[str]("Key of Vector to median")
16 def getInputSchema(self) -> KeyedDataSchema:
17 return ((self.vectorKey, Vector),)
19 def __call__(self, data: KeyedData, **kwargs) -> Scalar:
20 mask = self.getMask(**kwargs)
21 return cast(Scalar, float(np.nanmedian(cast(Vector, data[self.vectorKey.format(**kwargs)])[mask])))
24class MeanAction(ScalarAction):
25 vectorKey = Field[str]("Key of Vector from which to calculate mean")
27 def getInputSchema(self) -> KeyedDataSchema:
28 return ((self.vectorKey, Vector),)
30 def __call__(self, data: KeyedData, **kwargs) -> Scalar:
31 mask = self.getMask(**kwargs)
32 return cast(Scalar, float(np.nanmean(cast(Vector, data[self.vectorKey.format(**kwargs)])[mask])))
35class StdevAction(ScalarAction):
36 vectorKey = Field[str]("Key of Vector from which to calculate std deviation")
38 def getInputSchema(self) -> KeyedDataSchema:
39 return ((self.vectorKey, Vector),)
41 def __call__(self, data: KeyedData, **kwargs) -> Scalar:
42 mask = self.getMask(**kwargs)
43 return cast(Scalar, float(np.nanstd(cast(Vector, data[self.vectorKey.format(**kwargs)])[mask])))
46class SigmaMadAction(ScalarAction):
47 vectorKey = Field[str]("Key of Vector to median")
49 def getInputSchema(self) -> KeyedDataSchema:
50 return ((self.vectorKey, Vector),)
52 def __call__(self, data: KeyedData, **kwargs) -> Scalar:
53 mask = self.getMask(**kwargs)
54 return cast(
55 Scalar,
56 float(
57 nansigmaMad(
58 data[self.vectorKey.format(**kwargs)][mask], # type: ignore
59 )
60 ),
61 )
64class CountAction(ScalarAction):
65 vectorKey = Field[str]("Key of Vector to median")
67 def getInputSchema(self) -> KeyedDataSchema:
68 return ((self.vectorKey, Vector),)
70 def __call__(self, data: KeyedData, **kwargs) -> Scalar:
71 mask = self.getMask(**kwargs)
72 arr = cast(Vector, data[self.vectorKey.format(**kwargs)])[mask]
73 arr = arr[~np.isnan(arr)]
74 return cast(Scalar, len(arr))
77class ApproxFloor(ScalarAction):
78 vectorKey = Field[str](doc="Key for the vector to perform action on", optional=False)
80 def getInputSchema(self) -> KeyedDataSchema:
81 return ((self.vectorKey, Vector),)
83 def __call__(self, data: KeyedData, **kwargs) -> Scalar:
84 mask = self.getMask(**kwargs)
85 value = np.sort(data[self.vectorKey.format(**kwargs)][mask]) # type: ignore
86 x = len(value) // 10
87 return cast(Scalar, float(np.nanmedian(value[-x:])))
90class FracThreshold(ScalarAction):
91 """Compute the fraction of a distribution that is above or below a
92 specified threshold. The operator is specified as a string, for example,
93 "lt", "le", "ge", "gt" for the mathematical operations <, <=, >=, >. To
94 compute the fraction of elements with values less than a given threshold,
95 use op="le".
96 """
98 op = ChoiceField[str](
99 doc="Operator name string.",
100 allowed={
101 "lt": "less than threshold",
102 "le": "less than or equal to threshold",
103 "ge": "greater than or equal to threshold",
104 "gt": "greater than threshold",
105 },
106 )
107 threshold = Field[float](doc="Threshold to apply.")
108 vectorKey = Field[str](doc="Name of column")
109 percent = Field[bool](doc="Express result as percentage", default=False)
111 def getInputSchema(self, **kwargs) -> KeyedDataSchema:
112 return ((self.vectorKey.format(**kwargs), Vector),)
114 def __call__(self, data: KeyedData, **kwargs) -> Scalar:
115 mask = self.getMask(**kwargs)
116 values = data[self.vectorKey.format(**kwargs)]
117 values = values[mask] # type: ignore
118 values = values[np.logical_not(np.isnan(values))]
119 result = cast(
120 Scalar,
121 float(np.sum(getattr(operator, self.op)(values, self.threshold)) / len(values)), # type: ignore
122 )
123 if self.percent:
124 return 100.0 * result
125 else:
126 return result