Normalize¶
geotoolz.normalize
¶
Normalization operators for remote-sensing GeoTensors.
AsinhScale
¶
Bases: Operator
Inverse-hyperbolic-sine scaling.
.. math::
y \;=\; \mathrm{asinh}(x / a)
Linear near zero, logarithmic for |x| >> a. Symmetric and
well-defined for negative values (unlike log) — a common pick
for astronomy and signed radar quantities.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
float
|
Scale parameter. Must be strictly positive. Default
|
1.0
|
Examples:
Source code in src/geotoolz/normalize/_src/operators.py
HistogramMatch
¶
Bases: Operator
Match a GeoTensor histogram to a reference GeoTensor.
Reshapes the per-band empirical CDF of the input to match the reference. Useful for visual harmonisation across scenes acquired under different illumination.
The reference is a live GeoTensor — not JSON / YAML serialisable —
so forbid_in_yaml = True.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reference
|
GeoTensor
|
Reference GeoTensor whose per-band CDF the input will be matched against. |
required |
Examples:
>>> from geotoolz.normalize import HistogramMatch
>>> op = HistogramMatch(reference=reference_scene)
>>> matched = op(source_scene)
Source code in src/geotoolz/normalize/_src/operators.py
HistogramStretch
¶
Bases: Operator
Per-band percentile stretch into out_range for visualisation.
Lighter-weight cousin of :class:geotoolz.radiometry.PercentileClip:
clips to [P_lower, P_upper] using NaN-aware percentiles, then
maps the result into out_range instead of fixed [0, 1].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
out_range
|
tuple[float, float]
|
Two-element increasing tuple. Default
|
(0.0, 1.0)
|
lower
|
float
|
Lower percentile. Default |
2.0
|
upper
|
float
|
Upper percentile. Default |
98.0
|
Examples:
>>> from geotoolz.normalize import HistogramStretch
>>> # Standard "satellite RGB to display byte range" stretch.
>>> op = HistogramStretch(out_range=(0.0, 255.0))
>>> display = op(reflectance_scene)
Source code in src/geotoolz/normalize/_src/operators.py
LogScale
¶
Bases: Operator
Logarithmic scaling with an epsilon offset for zeros.
.. math::
y \;=\; \log_{\text{base}}(\max(x, 0) + \epsilon)
Compresses heavy-tailed distributions (radar backscatter, fire
radiative power, etc.) before downstream training. eps keeps
the log finite at zero.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base
|
float
|
Logarithm base. Must be |
10.0
|
eps
|
float
|
Small positive offset added before the log. Default
|
1e-06
|
Examples:
>>> from geotoolz.normalize import LogScale
>>> log_sar = LogScale(base=10.0, eps=1e-6)(sar_backscatter)
Source code in src/geotoolz/normalize/_src/operators.py
MinMaxScaler
¶
Bases: Operator
Per-band min-max scaling into an arbitrary output range.
.. math::
y \;=\; \frac{x - v_{\min}}{v_{\max} - v_{\min}}
\cdot (o_{\max} - o_{\min}) + o_{\min}
Per-band variant of :class:geotoolz.radiometry.MinMax. The
radiometry version takes scalar bounds and is the display-prep
pick when you already know fixed reflectance limits; this version
fits per-band bounds (one vmin / vmax per channel) or
accepts cached training-time bounds for inference. When
vmax == vmin for a band the divisor falls back to 1.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vmin
|
ndarray | list[float] | float | None
|
Per-band lower bound, scalar / list / ndarray, or
|
None
|
vmax
|
ndarray | list[float] | float | None
|
Per-band upper bound. |
None
|
out_range
|
tuple[float, float]
|
|
(0.0, 1.0)
|
fit_on_call
|
bool
|
If |
False
|
Examples:
>>> from geotoolz.normalize import MinMaxScaler
>>> # Map per-band [vmin, vmax] into [0, 1]:
>>> op = MinMaxScaler(vmin=[0.0, 0.0], vmax=[0.3, 0.4])
>>> scaled = op(scene)
>>>
>>> # Or fit on the scene and emit a uint8-style range:
>>> op = MinMaxScaler(fit_on_call=True, out_range=(0.0, 255.0))
>>> _ = op(scene)
Source code in src/geotoolz/normalize/_src/operators.py
Normalize
¶
Bases: StandardScaler
Fixed-stats per-band z-score normaliser.
Convenience alias for :class:StandardScaler with mandatory
mean / std (no fit_on_call knob exposed). The canonical
inference-time normaliser: cache stats once at training time,
instantiate at inference.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mean
|
ndarray | list[float] | float
|
Per-band mean (scalar, list, or ndarray). |
required |
std
|
ndarray | list[float] | float
|
Per-band std (scalar, list, or ndarray). |
required |
Examples:
>>> from geotoolz.normalize import Normalize
>>> import numpy as np
>>> op = Normalize(
... mean=np.array([0.1, 0.2, 0.15]),
... std=np.array([0.05, 0.07, 0.06]),
... )
>>> normed = op(scene)
Source code in src/geotoolz/normalize/_src/operators.py
PerBandStats
¶
Bases: Operator
Compute NaN-aware per-band statistics and cache them.
Side-effect-only operator: returns the input unchanged after caching
a stats dict containing per-band mean, std, min,
max, and percentiles over the spatial (H, W) axes. Use
this in a Tap-style stage to inspect a scene before applying a
downstream normaliser.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
percentiles
|
list[float] | None
|
Percentiles (in |
None
|
Examples:
>>> from geotoolz.normalize import PerBandStats
>>> op = PerBandStats(percentiles=[2.0, 98.0])
>>> _ = op(scene)
>>> op.stats["mean"] # one entry per band
[...]
Source code in src/geotoolz/normalize/_src/operators.py
PowerScale
¶
Bases: Operator
Non-negative power scaling.
.. math::
y \;=\; \max(x, 0)^{\gamma}
A simple gamma-style brightness curve. gamma < 1 brightens
midtones; gamma > 1 darkens. Differs from
:class:geotoolz.radiometry.Gamma only in convention
(Gamma raises to 1/g).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
gamma
|
float
|
Power exponent. Must be strictly positive. Default
|
0.5
|
Examples:
Source code in src/geotoolz/normalize/_src/operators.py
RobustScaler
¶
Bases: Operator
Per-band median / IQR scaling (robust to outliers).
.. math::
y \;=\; \frac{x - \mathrm{median}}{Q_{3} - Q_{1}}
Identical role to :class:StandardScaler but uses the median and
interquartile range instead of mean and std — robust against
bright-pixel outliers (cumulus, glint, saturation). When
iqr == 0 the divisor falls back to 1.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
median
|
ndarray | list[float] | float | None
|
Per-band median (scalar, list, or ndarray) or |
None
|
iqr
|
ndarray | list[float] | float | None
|
Per-band IQR ( |
None
|
fit_on_call
|
bool
|
If |
False
|
Examples:
>>> from geotoolz.normalize import RobustScaler
>>> op = RobustScaler(fit_on_call=True)
>>> _ = op(scene)
>>> op.median, op.iqr
Source code in src/geotoolz/normalize/_src/operators.py
StandardScaler
¶
Bases: Operator
Per-band z-score normalisation.
.. math::
y \;=\; \frac{x - \mu}{\sigma}
Statistics reduce over the spatial axes (-2, -1) so a
(C, H, W) carrier yields per-band mu / sigma of shape
(C,). Pass cached training-set statistics via mean / std
for inference, or set fit_on_call=True to fit on the first
scene seen. When sigma == 0 (a constant band) the divisor falls
back to 1 so the band collapses to zero instead of producing
inf / nan.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mean
|
ndarray | list[float] | float | None
|
Per-band mean (scalar, list, or ndarray) or |
None
|
std
|
ndarray | list[float] | float | None
|
Per-band std (scalar, list, or ndarray) or |
None
|
fit_on_call
|
bool
|
If |
False
|
Examples:
>>> from geotoolz.normalize import StandardScaler
>>> # Inference: cached per-band statistics from training.
>>> scaler = StandardScaler(mean=[0.1, 0.2], std=[0.05, 0.07])
>>> normed = scaler(scene)
>>>
>>> # Training-time fit-and-apply on a single scene:
>>> fit = StandardScaler(fit_on_call=True)
>>> _ = fit(train_scene)
>>> fit.mean # cached per-band ndarray
Source code in src/geotoolz/normalize/_src/operators.py
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | |
inverse(gt)
¶
Invert a previously applied standard scaling.
Source code in src/geotoolz/normalize/_src/operators.py
ZeroOne
¶
Bases: Operator
Scale the current scene extent into [0, 1].
.. math::
y \;=\; \frac{x - \min(x)}{\max(x) - \min(x)}
Stateless per-scene min-max stretch. per_band=True (default)
stretches each band independently; per_band=False uses a
single global min / max.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
per_band
|
bool
|
Compute min / max per band rather than globally. |
True
|
Examples:
Source code in src/geotoolz/normalize/_src/operators.py
asinh_scale(arr, *, a=1.0)
¶
Apply inverse-hyperbolic-sine scaling.
histogram_match(source, reference)
¶
Match source values to the empirical CDF of reference.
Source code in src/geotoolz/normalize/_src/array.py
log_scale(arr, *, base=10.0, eps=1e-06)
¶
Apply log scaling with a small offset for zero-valued pixels.
Source code in src/geotoolz/normalize/_src/array.py
minmax_scale(arr, vmin, vmax, *, out_range=(0.0, 1.0), axis=(-2, -1))
¶
Linearly map [vmin, vmax] into out_range.
Source code in src/geotoolz/normalize/_src/array.py
per_band_stats(arr, *, percentiles=(1.0, 99.0), axis=(-2, -1))
¶
Compute NaN-aware statistics over spatial axes.
Source code in src/geotoolz/normalize/_src/array.py
percentile_clip(arr, *, lower=1.0, upper=99.0, axis=(-2, -1))
¶
Clip to percentile bounds and stretch the result into [0, 1].
Source code in src/geotoolz/normalize/_src/array.py
power_scale(arr, *, gamma=0.5)
¶
Apply non-negative power scaling.
robust_scale(arr, median, iqr, *, axis=(-2, -1))
¶
Apply median/IQR scaling while preserving NaN pixels.
Source code in src/geotoolz/normalize/_src/array.py
standard_scale(arr, mean, std, *, axis=(-2, -1))
¶
Apply z-score scaling while preserving NaN pixels.