Skip to content

pl: Phase linking

moraine.api.pl (source). Every name is also moraine.<name> (import moraine as mr).

emi

emi(coh: ndarray, ref: int = 0, regularize: bool = True) -> ndarray

Phase linking with the EMI estimator.

Parameters:

Name Type Description Default
coh ndarray

complex coherence of the points (upper triangle of the coherence matrix, all image pairs), dtype complex64, shape (n_points, n_image_pairs), numpy or cupy

required
ref int

index of the reference image, its phase is set to 0

0
regularize bool

regularize the coherence matrix of the points whose coherence magnitude matrix is not positive definite or numerically singular (e.g. when the number of images approaches the number of independent looks of the SHPs; without it their phase history is not reliable); points with a well conditioned positive definite matrix are not changed

True

Returns:

Type Description
ndarray

phase history ph, dtype complex64, shape (n_points, nimages), unit amplitude, the phase of image ref is 0

ds_temp_coh

ds_temp_coh(coh: ndarray, ph: ndarray, image_pairs: ndarray = None, block_size: int = 128, n_looks=None, alpha: float = 0.001)

DS temporal coherence, optionally also weighted by the coherence of the image pairs.

Parameters:

Name Type Description Default
coh ndarray

complex coherence of the points as estimated (upper triangle of the coherence matrix), dtype complex64, shape (n_points, n_image_pairs), numpy or cupy

required
ph ndarray

phase history of the points, dtype complex64, shape (n_points, nimages), unit amplitude; with n_looks on a GPU block_size x nimages is at most 393216 (3072 images at the default block size)

required
image_pairs ndarray

image pairs of coh, dtype int32, shape (n_image_pairs, 2), all image pairs by default

None
block_size int

the CUDA block size, a multiple of 32, only applied for cuda

128
n_looks float or ndarray

effective number of independent looks of the coherence of each point, float or shape (n_points,), e.g. from emperical_co_pc(..., return_n_looks=True); with it also the weighted temporal coherence, the effective number of image pairs and the number of connected components are returned; points with n_looks <= 1 get NaN, 0 and nimages

None
alpha float

only with n_looks; probability that a point without any coherent image pair (pure noise) has all images connected (n_components 1); it sets the squared coherence above which an image pair counts as coherent, depending on n_looks and the number of images; 1e-6 <= alpha <= 0.5

1e-3

Returns:

Type Description
ndarray or tuple[ndarray, ndarray, ndarray, ndarray]

temporal coherence t_coh, dtype float32, shape (n_points,), 0..1, every image pair weighted the same; with n_looks also the weighted temporal coherence t_coh_w, dtype float32, shape (n_points,), 0..1: the image pairs weighted by their squared coherence without the noise bias of n_looks looks, so that incoherent pairs (e.g. long time spans in vegetation) do not lower it, NaN where no image pair is above the noise level; the effective number of image pairs it rests on eff_n_pairs ((sum of the weights)^2 / sum of the squared weights), dtype float32, shape (n_points,), 0..n_image_pairs, 0 where t_coh_w is NaN; and n_components, dtype int16, shape (n_points,), 1..nimages: the number of connected components of the graph whose nodes are the images and whose edges are the image pairs that are coherent (see alpha); 1 means every image is linked to every other by coherent pairs, with more the phase between the groups of images is not constrained by any coherent pair, whatever t_coh_w is

emperical_co_emi_temp_coh_pc

emperical_co_emi_temp_coh_pc(rslc: ndarray, idx: ndarray, pc_is_shp: ndarray, batch_size: int = None, regularize: bool = True, weighted: bool = False, alpha: float = 0.001)

Coherence matrix estimation, EMI phase linking and DS temporal coherence of points in one pass, without keeping the coherence matrices.

Parameters:

Name Type Description Default
rslc ndarray

rslc stack, dtype complex64, shape (nlines, width, nimages), numpy or cupy

required
idx ndarray

grid index of the points (azimuth, range) in rslc, dtype int32, shape (n_points, 2)

required
pc_is_shp ndarray

SHP masks of the points, dtype bool, shape (n_points, az_win, r_win)

required
batch_size int

number of points processed at once; the coherence matrices of a batch take 8 bytes per image pair and point, their estimation on the GPU up to 1 GiB more. Default: as many points as 1 GiB of coherence matrices hold

None
regularize bool

regularize the coherence matrix in the phase linking as in emi; the temporal coherence is computed with the coherence matrix as estimated

True
weighted bool

also return the weighted temporal coherence, the effective number of image pairs and the number of connected components of ds_temp_coh, with the effective number of looks of the SHPs of each point (as emperical_co_pc(..., return_n_looks=True))

False
alpha float

alpha of ds_temp_coh, only with weighted

1e-3

Returns:

Type Description
tuple

phase history ph, dtype complex64, shape (n_points, nimages), and temporal coherence t_coh, dtype float32, shape (n_points,); with weighted also t_coh_w and eff_n_pairs of ds_temp_coh, dtype float32, shape (n_points,) each, and n_components, dtype int16, shape (n_points,)

Examples

Run when this manual is built; the output follows each snippet.

import numpy as np
import moraine as mr

rng = np.random.default_rng(0)
nimages, n_points = 8, 3
phi = rng.uniform(-np.pi, np.pi, (n_points, nimages))            # a true phase history per point
phi[:, 0] = 0
ph_true = np.exp(1j * phi)
lag = np.abs(np.arange(nimages)[:, None] - np.arange(nimages)[None, :])
gamma = 0.7 ** lag                                               # coherence magnitude decaying with the time lag
C = gamma * ph_true[:, :, None] * np.conj(ph_true[:, None, :])   # (n_points, nimages, nimages)
i, j = np.triu_indices(nimages, 1)
coh = C[:, i, j].astype(np.complex64)                            # compressed, (n_points, n_pairs)

ph = mr.emi(coh)                                                 # phase linking, (n_points, nimages), unit amplitude
print(ph.shape, ph.dtype)
print('max phase error [rad]', np.abs(np.angle(ph * np.conj(ph_true))).max().round(4))
t_coh = mr.ds_temp_coh(coh, ph)                                  # how well the linked phases explain the coherence
print('temporal coherence', t_coh.round(3))
(3, 8) complex64
max phase error [rad] 0.0
temporal coherence [1. 1. 1.]

Coherence estimated from few looks is often not positive definite; emi regularizes such matrices by default (regularize=True). With n_looks (from emperical_co_pc) ds_temp_coh also returns the weighted temporal coherence, the effective number of image pairs and the number of connected components of the coherent pairs, the quantities the DS selection uses.