Skip to content

pu: phase unwrapping

Commands of moraine.cli.pu (source); the same functions are called in Python as mc.<name>(...) with import moraine.cli as mc. The help below is generated from the docstrings, like moraine COMMAND --help.

command summary
gamma-mcf-pt A wrapper for mcf_pt in GAMMA software.
mcf-pc Minimum cost flow phase unwrapping of point cloud interferograms
emcf-pc Extended minimum cost flow (EMCF) phase unwrapping of point cloud interferograms
unwrap-correct-closure-pc Correction of unwrapping errors of point cloud interferograms by phase closure, to the unwrapped phase of every image

gamma-mcf-pt

A wrapper for mcf_pt in GAMMA software.

moraine gamma-mcf-pt --pc_x STR --pc_y STR --ph STR --unw_ph STR --image_pairs FILE [--ref_point VALUE] [--out_chunks VALUE] [--n_workers VALUE] [--threads_per_worker VALUE]
argument type default description
--pc_x str required input x coordinate of the points, shape (n_points,)
--pc_y str required input y coordinate of the points, shape (n_points,)
--ph str required input wrapped phase history (complex), shape (n_points, nimages)
--unw_ph str required output unwrapped phase of the interferograms, shape (n_points, n_image_pairs)
--image_pairs np.ndarray required image pairs (reference, secondary) of the interferograms to unwrap, shape (n_image_pairs, 2)
--ref_point int 0 index of the reference point (from 0), the first point by default
--out_chunks int None point chunk size of unw_ph, same as ph by default
--n_workers 1 number of worker processes: interferograms unwrapped at the same time
--threads_per_worker 2 tasks a worker runs at the same time

Global options: --json, --traceback, --log FILE, -q / --quiet (conventions).

In a pipeline (not used by the example pipelines; required arguments only):

[[step]]
name = "gamma_mcf_pt"
run = "gamma-mcf-pt"
pc_x = "..."
pc_y = "..."
ph = "..."
unw_ph = "..."
image_pairs = "..."

In Python:

import moraine.cli as mc
mc.gamma_mcf_pt(pc_x, pc_y, ph, unw_ph, image_pairs, ref_point=0, out_chunks=None, n_workers=1, threads_per_worker=2)

The array function mr.gamma_mcf_pt does the same on numpy / cupy arrays in memory.

mcf-pc

Minimum cost flow phase unwrapping of point cloud interferograms. Every interferogram is unwrapped alone on the Delaunay network of the points. The network stays in memory, about 50 bytes per point (100 with spatial_cost 'length'), and every interferogram unwrapped at the same time needs about 160 bytes per point more.

moraine mcf-pc --gix STR --ph STR --unw_ph STR --image_pairs FILE --range_pixel_spacing VALUE --azimuth_pixel_spacing VALUE [--earth_cost VALUE] [--spatial_cost STR] [--n_workers VALUE] [--out_chunks VALUE]
argument type default description
--gix str required input grid index (azimuth, range) of the points, shape (n_points, 2), int; the points must be unique
--ph str required input wrapped phase history (complex), shape (n_points, nimages), chunked one image per chunk (points_block, 1)
--unw_ph str required output unwrapped phase of the interferograms in radians, shape (n_points, n_pairs), float32, chunks (out_chunks, 1); the first point keeps its wrapped phase
--image_pairs np.ndarray required image pairs (reference, secondary) of the interferograms to unwrap, shape (n_pairs, 2); the interferogram is reference * conj(secondary)
--range_pixel_spacing float required range pixel spacing in meters
--azimuth_pixel_spacing float required azimuth pixel spacing in meters
--earth_cost int 1 cost of a phase jump across the convex hull of the points, relative to 1 inside; a larger value discourages discharging residues through the border
--spatial_cost str 'constant' where phase jumps are placed first: 'constant' (anywhere alike) or 'length' (long connections between points)
--n_workers int None number of interferograms unwrapped at the same time; by default as many as the available cores and half of the available memory allow
--out_chunks int None point chunk size of unw_ph, same as ph by default

Global options: --json, --traceback, --log FILE, -q / --quiet (conventions).

In a pipeline (examples/05_unwrap.toml, step unwrap):

[[step]]
name = "unwrap"
run = "mcf-pc"
gix = "unw/pc_gix.zarr"
ph = "pc/pc_ph.zarr"
unw_ph = "unw/pc_unw.zarr"
image_pairs = "unw/pairs_seq.txt"
range_pixel_spacing = "${range_pixel_spacing}"
azimuth_pixel_spacing = "${azimuth_pixel_spacing}"

In Python:

import moraine.cli as mc
mc.mcf_pc(gix, ph, unw_ph, image_pairs, range_pixel_spacing, azimuth_pixel_spacing, earth_cost=1, spatial_cost='constant', n_workers=None, out_chunks=None)

The array function mr.mcf_pc does the same on numpy / cupy arrays in memory.

emcf-pc

Extended minimum cost flow (EMCF) phase unwrapping of point cloud interferograms. The interferograms of a network of image pairs are unwrapped together: the redundancy of the network (image pairs that close loops, e.g. (a, b), (b, c) and (a, c)) is used against unwrapping errors. The coordinates and the network of the points stay in memory, about 120 bytes per point, and every interferogram unwrapped at the same time needs about 200 bytes per point more. Intermediate results are written to unw_ph.tmp (kept if the command fails, removed at the end).

moraine emcf-pc --gix STR --ph STR --image_pairs FILE --unw_ph STR --range_pixel_spacing VALUE --azimuth_pixel_spacing VALUE [--dates PATH [PATH ...]] [--weight STR] [--earth_cost VALUE] [--temporal_cost STR] [--spatial_cost STR] [--n_workers VALUE] [--out_chunks VALUE]
argument type default description
--gix str required input grid index (azimuth, range) of the points, shape (n_points, 2), int; the points must be unique
--ph str required input wrapped phase history (complex), shape (n_points, nimages), chunked one image per chunk (points_block, 1)
--image_pairs np.ndarray required the interferograms: (reference, secondary) image indices, shape (n_pairs, 2), e.g. a file made by image-pairs (--bandwidth 3: every image with the next three); the interferogram is reference * conj(secondary); without any loop in the network every interferogram is unwrapped alone
--unw_ph str required output unwrapped phase of the interferograms in radians, shape (n_points, n_pairs), float32, chunks (out_chunks, 1); at the first point the difference of the wrapped phases of the two images. Loops of image pairs may still not add up to zero at some points: see unwrap-correct-closure-pc
--range_pixel_spacing float required range pixel spacing in meters
--azimuth_pixel_spacing float required azimuth pixel spacing in meters
--dates str or list None acquisition date of every image (YYYYMMDD), nimages values; needed by temporal_cost 'length'
--weight str None input quality of the points from 0 (unreliable) to 1, e.g. the temporal coherence, shape (n_points,); needed by spatial_cost 'weight'
--earth_cost int 1 cost of a phase jump across the border of the network of points, relative to 1 inside; a larger value discourages discharging residues through the border
--temporal_cost str 'constant' which interferograms are corrected first where the interferograms of a loop of image pairs disagree: 'constant' (all alike) or 'length' (the longest in time)
--spatial_cost str 'constant' where phase jumps are placed first in every interferogram: 'constant' (anywhere alike), 'length' (long connections between points), 'weight' (points of low weight) or 'length+weight'
--n_workers int None number of interferograms unwrapped at the same time; by default as many as the available cores and half of the available memory allow
--out_chunks int None point chunk size of unw_ph, same as ph by default

Global options: --json, --traceback, --log FILE, -q / --quiet (conventions).

In a pipeline (not used by the example pipelines; required arguments only):

[[step]]
name = "emcf_pc"
run = "emcf-pc"
gix = "..."
ph = "..."
image_pairs = "..."
unw_ph = "..."
range_pixel_spacing = "..."
azimuth_pixel_spacing = "..."

In Python:

import moraine.cli as mc
mc.emcf_pc(gix, ph, image_pairs, unw_ph, range_pixel_spacing, azimuth_pixel_spacing, dates=None, weight=None, earth_cost=1, temporal_cost='constant', spatial_cost='constant', n_workers=None, out_chunks=None)

The array function mr.emcf_pc does the same on numpy / cupy arrays in memory.

unwrap-correct-closure-pc

Correction of unwrapping errors of point cloud interferograms by phase closure, to the unwrapped phase of every image. The unwrapped phases of every loop of image pairs should add up to zero, e.g. unw(a, b) + unw(b, c) = unw(a, c). Where they do not, the interferograms are corrected by whole cycles, changing as few interferograms as possible, by the same amount for all points of a region: the points connected by edges of the point network no longer than max_edge_factor times the median edge length. Points of smaller regions than min_region_points are corrected one by one. The correction assumes that most interferograms of a region are right: where most are wrong, it makes them worse. Where a point still does not fit the loops after the correction of its region, the interferograms fitting most of its loops are kept. The result is the unwrapped phase of every image, whose differences close every loop. Errors that close every loop (e.g. the same whole cycles in every interferogram of one image) are neither corrected nor reported. The region of every point stays in memory (4 bytes per point; about 100 bytes per point while the regions are made). Intermediate results are written to ts.tmp (kept if the command fails, removed at the end).

moraine unwrap-correct-closure-pc --gix STR --ph STR --unw_ph STR --image_pairs FILE --ts STR --range_pixel_spacing VALUE --azimuth_pixel_spacing VALUE [--ref VALUE] [--misclosure_fraction STR] [--change_fraction STR] [--region STR] [--max_edge_factor VALUE] [--min_region_points VALUE] [--n_workers VALUE] [--out_chunks VALUE]
argument type default description
--gix str required input grid index (azimuth, range) of the points, shape (n_points, 2), int; the points must be unique
--ph str required input wrapped phase history (complex), shape (n_points, nimages), chunked one image per chunk (points_block, 1)
--unw_ph str required input unwrapped phase of the interferograms in radians, shape (n_points, n_pairs), chunked one interferogram per chunk (points_block, 1), e.g. from mcf-pc or emcf-pc; rewrapped, it must be the phase of ph[:, reference] * conj(ph[:, secondary])
--image_pairs np.ndarray required the interferograms: (reference, secondary) image indices of the columns of unw_ph, shape (n_pairs, 2); the pairs must connect all images; the network needs loops (e.g. every image paired with the next three) to correct anything, otherwise only the image phases are computed (a warning is given)
--ts str required output unwrapped phase of every image relative to image ref in radians, shape (n_points, nimages), float32, chunks (out_chunks, 1); ts[:, ref] is 0; rewrapped, ts[:, j] is the phase of ph[:, j] * conj(ph[:, ref]); the corrected interferogram (a, b) is ts[:, a] - ts[:, b]
--range_pixel_spacing float required range pixel spacing in meters
--azimuth_pixel_spacing float required azimuth pixel spacing in meters
--ref int 0 index of the reference image, 0 .. nimages - 1: the image phases are relative to it
--misclosure_fraction str None output fraction of the interferograms of every point that do not fit the loops before the correction, shape (n_points,), float32, 0..1; 0 where every loop closes
--change_fraction str None output fraction of the interferograms of every point whose whole cycles in ts differ from unw_ph, shape (n_points,), float32, 0..1; 0 where unw_ph was kept; large values mark points whose input unwrapping was poor (e.g. to be masked)
--region str None output region of every point, shape (n_points,), int32: 0 .. n_regions - 1, or -1 for the points of regions smaller than min_region_points, corrected one by one (e.g. to be masked)
--max_edge_factor float 4.0 edges of the point network longer than this times the median edge length do not connect a region, e.g. edges across water or decorrelated areas; larger than 1
--min_region_points int 30 in regions of fewer points every point is corrected by its own loops alone, which is less reliable
--n_workers int None number of interferograms corrected at the same time; by default as many as the available cores and half of the available memory allow
--out_chunks int None point chunk size of the outputs, same as unw_ph by default

Global options: --json, --traceback, --log FILE, -q / --quiet (conventions).

In a pipeline (not used by the example pipelines; required arguments only):

[[step]]
name = "unwrap_correct_closure_pc"
run = "unwrap-correct-closure-pc"
gix = "..."
ph = "..."
unw_ph = "..."
image_pairs = "..."
ts = "..."
range_pixel_spacing = "..."
azimuth_pixel_spacing = "..."

In Python:

import moraine.cli as mc
mc.unwrap_correct_closure_pc(gix, ph, unw_ph, image_pairs, ts, range_pixel_spacing, azimuth_pixel_spacing, ref=0, misclosure_fraction=None, change_fraction=None, region=None, max_edge_factor=4.0, min_region_points=30, n_workers=None, out_chunks=None)

The array function mr.unwrap_correct_closure_pc does the same on numpy / cupy arrays in memory.