- Home
- Documentation
- API reference
- Spectral
- hyperproc.spectral.resampling
hyperproc.spectral.resampling¶
Source-derived reference
Generated from the current hyperproc 0.1.2 checkout.
Implementation: hyperproc/spectral/resampling.py. Signatures, defaults, docstrings, and expandable source are extracted statically; the module is not imported or executed. Names beginning with _ are implementation details, not a stable public API.
Use the function signature as the authority for individual parameter defaults and return annotations. Original docstrings sometimes group parameter names or wrap return descriptions across lines; these descriptions are preserved rather than inferred or rewritten.
Exported entry points¶
| Importable name | Definition |
|---|---|
hyperproc.spectral.resampling.METHODS |
hyperproc.spectral.resampling.METHODS |
hyperproc.spectral.resampling.build_fwhm |
hyperproc.spectral.resampling.build_fwhm |
hyperproc.spectral.resampling.resampling_matrix |
hyperproc.spectral.resampling.resampling_matrix |
hyperproc.spectral.resampling.resample |
hyperproc.spectral.resampling.resample |
hyperproc.spectral.resampling.target_grid |
hyperproc.spectral.resampling.target_grid |
Spectral resampling: put a cube, or a spectrum, on another band set.
Resampling is a fixed linear map. Once the weights are known, moving a whole cube is one matrix multiply, which is why nothing here loops over pixels::
import hyperproc as hp
hp.resample(ds, step=10) # a 10 nm grid
hp.resample(ds, step=10, fwhm=15) # 10 nm spacing, 15 nm bands
hp.resample(ds, like=other) # match another sensor's bands
hp.resample(ds, sensor="SENTINEL2A") # a real instrument
hp.resample(spectra, source_wl=wl, step=10) # an array of spectra, same maths
Two numbers, not one¶
"Spectral resolution" is two independent things and every sensor in this
package has them different: the spacing between band centres and the
FWHM of each band. EMIT samples every 7.44 nm with 8.4 nm bands, PRISMA
every 9.25 nm with bands from 8.9 to 15.3 nm. So step and fwhm are
separate arguments, and leaving fwhm out makes it equal to step, the
contiguous convention.
Two guards¶
Coverage. A target band whose response falls partly outside the source's
range, or into a water-vapour gap, is reported with the fraction of its
response that the source actually measured, and becomes NaN below
min_coverage. Renormalising over whatever bands happened to be there is
the default behaviour of most implementations and it silently turns a 43 %
sample into a confident-looking number.
Sharpening. Resampling cannot raise spectral resolution. Asking EMIT, with
8.4 nm bands, for a 2 nm grid interpolates and calls it measurement, so it is
refused unless allow_sharpening=True.
Methods¶
"gaussian"
Both source and target bands are Gaussians of their own FWHM, and the
weight is their overlap integral, which has a closed form. The default.
"box"
Source band as a rectangle of its FWHM, target as a Gaussian, weights from
the overlap. This is what Spectral Python's BandResampler does, kept so
earlier results stay reproducible.
"response"
Uses a measured response function per target band. See
:mod:hyperproc.spectral.srf for the instruments that ship one.
"linear", "cubic", "nearest"
Interpolation at the target centres, ignoring band width. Right when the
FWHM is unknown, or when the target bands are no wider than the source.
METHODS = ('gaussian', 'box', 'response', 'linear', 'cubic', 'nearest')
module-attribute
¶
SQRT_8LN2 = 2.3548200450309493
module-attribute
¶
_sigma(fwhm) -> np.ndarray
¶
_normal_cdf(x)
¶
build_fwhm(centres) -> np.ndarray
¶
FWHM assumed equal to the spacing between neighbouring band centres.
This is only a fallback for a band set that does not state its own widths. It is wrong for every sensor in this package, which are all oversampled: EMIT's bands are 8.4 nm wide at 7.44 nm spacing, DESIS's up to 6.6 nm wide at 2.56 nm spacing. Pass the real FWHM whenever the metadata has it.
Source code in hyperproc/spectral/resampling.py
_merged_intervals(lo: np.ndarray, hi: np.ndarray) -> list
¶
Union of [lo, hi] intervals, merged and sorted.
Source code in hyperproc/spectral/resampling.py
coverage_of(target_wl, target_fwhm, source_wl, source_fwhm, usable=None) -> np.ndarray
¶
Fraction of each target band's response that the source measures.
The source is treated as covering the union of its usable bands' intervals; the target's Gaussian response is integrated over that union. 1.0 means the target band sits entirely inside measured wavelengths, 0.0 that none of it does.
Source code in hyperproc/spectral/resampling.py
_weights_gaussian(s_wl, s_fw, t_wl, t_fw) -> np.ndarray
¶
Overlap integral of two Gaussians: a Gaussian in the centre difference.
Source code in hyperproc/spectral/resampling.py
_weights_box(s_wl, s_fw, t_wl, t_fw) -> np.ndarray
¶
Source band as a rectangle, target as a Gaussian, integrated over the overlap.
The formulation used by Spectral Python's BandResampler.
Source code in hyperproc/spectral/resampling.py
_weights_interp(s_wl, t_wl, kind: str) -> np.ndarray
¶
Interpolation expressed as a matrix, by interpolating the identity basis.
Source code in hyperproc/spectral/resampling.py
_weights_response(s_wl, s_fw, fine_wl, response) -> np.ndarray
¶
Measured target response against the source's own Gaussian bands.
Source code in hyperproc/spectral/resampling.py
resampling_matrix(source_wl, target_wl, source_fwhm=None, target_fwhm=None, method: str = 'gaussian', response=None, response_wl=None, usable=None, min_coverage: float = 0.5, allow_sharpening: bool = False) -> tuple
¶
The weights that turn source bands into target bands.
| PARAMETER | DESCRIPTION |
|---|---|
source_wl, target_wl
|
band centres, nm.
|
source_fwhm, target_fwhm
|
band widths, nm. Inferred from the spacing by
:func:
|
method
|
one of :data:
TYPE:
|
response, response_wl
|
for
|
usable
|
boolean mask of source bands to use. Unusable bands get zero weight and are excluded from the coverage.
DEFAULT:
|
min_coverage
|
target bands covered less than this become NaN.
TYPE:
|
allow_sharpening
|
permit a target narrower than the source.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple
|
|
tuple
|
to 1, and the coverage fraction per target band. Rows below |
tuple
|
|
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
an unknown method, or a target finer than the source while
|
Source code in hyperproc/spectral/resampling.py
target_grid(source_wl=None, source_fwhm=None, *, step=None, fwhm=None, wl_range=None, wavelengths=None, like=None, sensor=None) -> dict
¶
Resolve the many ways of naming a target band set into one description.
Exactly one of step, wavelengths, like or sensor is used.
| RETURNS | DESCRIPTION |
|---|---|
dict
|
dict with |
dict
|
with a measured response, |
Source code in hyperproc/spectral/resampling.py
_apply_block(a: np.ndarray, M: np.ndarray, min_coverage: float = 0.5) -> np.ndarray
¶
Apply the resampling matrix, keeping a dead source band local.
A dense product spreads a single NaN across the whole output, because
0.0 * nan is nan: one dead band at the end of the shortwave takes
the visible with it. On the PRISMA test granule four unflagged bands near
2490 nm carry NaN in some pixels, and that silently emptied the resampled
spectrum of 31 % of them.
So the gaps are zeroed and each target band is divided by the weight that
actually landed on finite source bands. That is the renormalisation the
static coverage test already performs, applied per pixel, and it is held
to the same threshold: a target band that kept less than min_coverage
of its weight comes back NaN rather than as a confident-looking number
built from a fraction of its response.
Source code in hyperproc/spectral/resampling.py
resample(data, source_wl=None, source_fwhm=None, *, var=None, step=None, fwhm=None, wl_range=None, wavelengths=None, like=None, sensor=None, method: str | None = None, min_coverage: float = 0.5, allow_sharpening: bool = False, good_only: bool = True, return_coverage: bool = False, verbose: bool = False)
¶
Resample a cube, a table of spectra or a single spectrum.
Dispatches on type, never on shape: an xarray.Dataset goes through
the metadata-aware path, anything array-like is treated as values whose
last axis is wavelength, whatever the other axes mean.
| PARAMETER | DESCRIPTION |
|---|---|
data
|
a Dataset, or an array of any shape with wavelength last.
|
source_wl, source_fwhm
|
required for arrays, read from a Dataset.
|
var
|
which variable to resample; the main cube by default.
DEFAULT:
|
step, fwhm, wl_range, wavelengths, like, sensor
|
how to name the
target; see :func:
|
method
|
see :data:
TYPE:
|
min_coverage
|
target bands covered less than this become NaN.
TYPE:
|
allow_sharpening
|
permit a target narrower than the source.
TYPE:
|
good_only
|
drop bands flagged unusable by
TYPE:
|
return_coverage
|
also return the per-target-band coverage.
TYPE:
|
verbose
|
print what the target is and how well it is covered.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
|
The same kind that went in, with the new band set. For a Dataset the |
|
|
|
|
|
becomes the coverage test, and |
|
|
what was done. Lazy input stays lazy. |