Source code for scarlet.measure
import numpy as np
from . import initialization
from .bbox import Box
[docs]def max_pixel(component):
"""Determine pixel with maximum value
Parameters
----------
component: `scarlet.Component` or array
Component to analyze or its hyperspectral model
"""
if hasattr(component, "get_model"):
model = component.get_model()
origin = component.bbox.origin
else:
model = component
origin = 0
return tuple(np.array(np.unravel_index(np.argmax(model), model.shape)) + origin)
[docs]def flux(component):
"""Determine flux in every channel
Parameters
----------
component: `scarlet.Component` or array
Component to analyze or its hyperspectral model
"""
if hasattr(component, "get_model"):
model = component.get_model()
else:
model = component
return model.sum(axis=(1, 2))
[docs]def centroid(component):
"""Determine centroid of model
Parameters
----------
component: `scarlet.Component` or array
Component to analyze or its hyperspectral model
"""
if hasattr(component, "get_model"):
model = component.get_model()
origin = component.bbox.origin
else:
model = component
origin = 0
indices = np.indices(model.shape)
centroid = np.array([np.sum(ind * model) for ind in indices]) / model.sum()
return centroid + origin
[docs]def snr(component, observations):
"""Determine SNR with morphology as weight function
Parameters
----------
component: `scarlet.Component` or array
Component to analyze or its hyperspectral model
observations: `scarlet.Observation` or list thereof
"""
if not hasattr(observations, "__iter__"):
observations = (observations,)
if hasattr(component, "get_model"):
frame = None
if not prerender:
frame = observations[0].model_frame
model = component.get_model(frame=frame)
bbox = component.bbox
else:
model = component
bbox = Box(model.shape)
M = []
W = []
var = []
# convolve model for every observation;
# flatten in channel direction because it may not have all C channels; concatenate
# do same thing for noise variance
for obs in observations:
model_ = obs.render(model)
M.append(model_.reshape(-1))
W.append((model_ / (model_.sum(axis=(-2, -1))[:, None, None])).reshape(-1))
noise_var = obs.noise_rms ** 2
var.append(noise_var.reshape(-1))
M = np.concatenate(M)
W = np.concatenate(W)
var = np.concatenate(var)
# SNR from Erben (2001), eq. 16, extended to multiple bands
# SNR = (I @ W) / sqrt(W @ Sigma^2 @ W)
# with W = morph, Sigma^2 = diagonal variance matrix
snr = (M * W).sum() / np.sqrt(((var * W) * W).sum())
return snr
# adapted from https://github.com/pmelchior/shapelens/blob/master/src/Moments.cc
[docs]def moments(component, N=2, centroid=None, weight=None):
"""Determine SNR with morphology as weight function
Parameters
----------
component: `scarlet.Component` or array
Component to analyze or its hyperspectral model
N: int >=0
Moment order
centroid: array
2D coordinate in frame of `component`
weight: array
weight function with same shape as `component`
"""
if hasattr(component, "get_model"):
model = component.get_model()
else:
model = component
if weight is None:
weight = 1
else:
assert model.shape == weight.shape
if centroid is None:
centroid = np.array(model.shape) // 2
grid_x, grid_y = np.indices(model.shape[-2:], dtype=np.float64)
if len(model.shape) == 3:
grid_y = grid_y[None, :, :]
grid_x = grid_x[None, :, :]
grid_y -= centroid[0]
grid_x -= centroid[1]
M = dict()
for n in range(N + 1):
for m in range(n + 1):
# moments ordered by power in y, then x
M[m, n - m] = (grid_y ** m * grid_x ** (n - m) * model * weight).sum(
axis=(-2, -1)
)
return M