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-25 08:54 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-25 08:54 +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)
41from lsst.pex.config import Field
43from ...interfaces import Tensor, TensorAction, Vector, VectorAction
44from ...math import nanMax, nanMedian, nanMin, nanSigmaMad
47class MinMax(VectorAction):
48 """Return the maximum and minimum values of an input vector to use as the
49 minimum and maximum values of a colorbar range.
51 Parameters
52 ----------
53 data : `Vector`
54 A vector containing the data whose minimum and maximum are to be
55 returned.
57 Returns
58 -------
59 A two-element vector containing the minimum and maximum values of `data`.
60 """
62 def __call__(self, data: Vector, **kwargs) -> Vector:
63 if len(data) == 0:
64 return cast(Vector, [np.nan, np.nan])
65 else:
66 return cast(Vector, [nanMin(data), nanMax(data)])
69class Med2Mad(VectorAction):
70 """Return the median +/- 2*nansigmamad values of an input vector to use
71 as the minimum and maximum values of a colorbar range.
73 Parameters
74 ----------
75 data : `Vector`
76 A vector containing the data whose median +/- 2*nansigmamad are to
77 be returned.
79 Returns
80 -------
81 A two-element vector containing the median +/- 2*nansigmamad values of
82 `data`.
83 """
85 def __call__(self, data: Vector, **kwargs) -> Vector:
86 med = nanMedian(data)
87 mad = nanSigmaMad(data)
88 cmin = med - 2 * mad
89 cmax = med + 2 * mad
90 return cast(Vector, [cmin, cmax])
93class Perc(VectorAction):
94 """Return the minimum and maximum values of an input vector after
95 excluding a fraction of values from either end of the distribution.
97 Parameters
98 ----------
99 data : `Vector`
100 A vector containing the data whose minimum and maximum are to be
101 calculated following the exclusion of a fraction of extreme upper
102 and lower values.
104 Returns
105 -------
106 A two-element vector containing the minimum and maximum values of
107 the input vector, following the exclusion of a fraction of extreme
108 upper and lower values.
109 """
111 percentile = Field[float](
112 doc="The fraction of values to keep. The same fraction of values is "
113 "eliminated from both ends of the distribution. Default: 97.",
114 default=97.0,
115 )
117 def __call__(self, data, **kwargs):
118 return PercentileInterval(self.percentile).get_limits(data)
121class Asinh(VectorAction, TensorAction):
122 """Transform the input vector/tensor using the asinh stretch.
124 Parameters
125 ----------
126 data : `Vector` | `Tensor`
127 A vector or a tensor containing the data to be transformed
128 using the asinh stretch.
130 Returns
131 -------
132 A vector or tensor of the same size as the input, transformed
133 using the asinh stretch.
134 """
136 def __call__(self, data: Vector | Tensor, **kwargs) -> Vector | Tensor:
137 return AsinhStretch()(data)
140class Linear(VectorAction, TensorAction):
141 """Transform the input vector/tensor using the linear stretch.
143 Parameters
144 ----------
145 data : `Vector`
146 A vector or a tensor containing the data to be transformed
147 using the linear stretch.
149 Returns
150 -------
151 A vector or tensor of the same size as the input, transformed
152 using the linear stretch.
153 """
155 intercept = Field[float](doc="The offset of the linear stretch. Default: 0.", default=0.0)
157 slope = Field[float](doc="The slope of the linear stretch. Default: 1.", default=1.0)
159 def __call__(self, data: Vector | Tensor, **kwargs) -> Vector | Tensor:
160 return LinearStretch(self.slope, self.intercept)(data)