Coverage for python / lsst / analysis / tools / actions / plot / calculateRange.py: 62%
32 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-15 00:23 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-15 00:23 +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/>.
22from __future__ import annotations
24__all__ = (
25 "MinMax",
26 "Med2Mad",
27 "Asinh",
28 "Perc",
29 "Linear",
30)
32from typing import cast
34import numpy as np
35from astropy.visualization import (
36 AsinhStretch,
37 LinearStretch,
38 PercentileInterval,
39)
40from lsst.pex.config import Field
42from ...interfaces import Tensor, TensorAction, Vector, VectorAction
43from ...math import nanMax, nanMedian, nanMin, nanSigmaMad
46class MinMax(VectorAction):
47 """Return the maximum and minimum values of an input vector to use as the
48 minimum and maximum values of a colorbar range.
50 Parameters
51 ----------
52 data : `Vector`
53 A vector containing the data whose minimum and maximum are to be
54 returned.
56 Returns
57 -------
58 A two-element vector containing the minimum and maximum values of `data`.
59 """
61 def __call__(self, data: Vector, **kwargs) -> Vector:
62 if len(data) == 0:
63 return cast(Vector, [np.nan, np.nan])
64 else:
65 return cast(Vector, [nanMin(data), nanMax(data)])
68class Med2Mad(VectorAction):
69 """Return the median +/- 2*nansigmamad values of an input vector to use
70 as the minimum and maximum values of a colorbar range.
72 Parameters
73 ----------
74 data : `Vector`
75 A vector containing the data whose median +/- 2*nansigmamad are to
76 be returned.
78 Returns
79 -------
80 A two-element vector containing the median +/- 2*nansigmamad values of
81 `data`.
82 """
84 def __call__(self, data: Vector, **kwargs) -> Vector:
85 med = nanMedian(data)
86 mad = nanSigmaMad(data)
87 cmin = med - 2 * mad
88 cmax = med + 2 * mad
89 return cast(Vector, [cmin, cmax])
92class Perc(VectorAction):
93 """Return the minimum and maximum values of an input vector after
94 excluding a fraction of values from either end of the distribution.
96 Parameters
97 ----------
98 data : `Vector`
99 A vector containing the data whose minimum and maximum are to be
100 calculated following the exclusion of a fraction of extreme upper
101 and lower values.
103 Returns
104 -------
105 A two-element vector containing the minimum and maximum values of
106 the input vector, following the exclusion of a fraction of extreme
107 upper and lower values.
108 """
110 percentile = Field[float](
111 doc="The fraction of values to keep. The same fraction of values is "
112 "eliminated from both ends of the distribution. Default: 97.",
113 default=97.0,
114 )
116 def __call__(self, data, **kwargs):
117 return PercentileInterval(self.percentile).get_limits(data)
120class Asinh(VectorAction, TensorAction):
121 """Transform the input vector/tensor using the asinh stretch.
123 Parameters
124 ----------
125 data : `Vector` | `Tensor`
126 A vector or a tensor containing the data to be transformed
127 using the asinh stretch.
129 Returns
130 -------
131 A vector or tensor of the same size as the input, transformed
132 using the asinh stretch.
133 """
135 def __call__(self, data: Vector | Tensor, **kwargs) -> Vector | Tensor:
136 return AsinhStretch()(data)
139class Linear(VectorAction, TensorAction):
140 """Transform the input vector/tensor using the linear stretch.
142 Parameters
143 ----------
144 data : `Vector`
145 A vector or a tensor containing the data to be transformed
146 using the linear stretch.
148 Returns
149 -------
150 A vector or tensor of the same size as the input, transformed
151 using the linear stretch.
152 """
154 intercept = Field[float](doc="The offset of the linear stretch. Default: 0.", default=0.0)
156 slope = Field[float](doc="The slope of the linear stretch. Default: 1.", default=1.0)
158 def __call__(self, data: Vector | Tensor, **kwargs) -> Vector | Tensor:
159 return LinearStretch(self.slope, self.intercept)(data)