Skip to content

Commit a52256d

Browse files
authored
mask: replace --threshold with --vmin/vmax (#1009)
* mask: replace --threshold with --vmin/vmax + mask.py: replace the -t / --threshold option with the --vmin / --mask-vmin option, to be less ambiguous, as vmin includes the direction for thresholding. + mask.py: add --vmax / --mask-vmax option + utils.isce_utils.unwrap_snaphu: support 2-band corr file, by checking the number of bands for the input correlation files, and set the file format accordingly, to support both the phase sigma and complex correlation files. + utils.readfile.read_binary_file(): add file/dset size checking + view: bugfix for --mask-vmin/vmax options - utils.plot.read_mask(): when --mask-vmin/vmax options are specified, create mask via thresholding the 2D matrix of the mask file, instead of updating mask on top of the 2D matrix of the mask file.
1 parent f641b90 commit a52256d

File tree

7 files changed

+61
-45
lines changed

7 files changed

+61
-45
lines changed

src/mintpy/cli/mask.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313

1414
############################################################
1515
EXAMPLE = """example:
16-
mask.py velocity.h5 -m Mask.h5
17-
mask.py timeseries.h5 -m temporalCoherence.h5 -t 0.7
18-
mask.py ifgramStack.h5 -m 100102_101120.cor -t 0.9 -y 200 300 -x 300 400
16+
mask.py velocity.h5 -m maskTempCoh.h5
17+
mask.py timeseries.h5 -m temporalCoherence.h5 --vmin 0.7
18+
mask.py ifgramStack.h5 -m 100102_101120.cor --vmin 0.9 -y 200 300 -x 300 400
1919
2020
mask.py filt_20060924_20090214.int -m waterMask.h5 -o filt_20060924_20090214_msk.int
2121
mask.py filt_20060924_20090214.cor -m waterMask.h5 -o filt_20060924_20090214_msk.cor
@@ -30,21 +30,23 @@ def create_parser(subparsers=None):
3030

3131
parser.add_argument('file', help='File to be masked')
3232
parser.add_argument('-m', '--mask', dest='mask_file', required=True,
33-
help='mask for pixels used in ramp estimation')
33+
help='mask out pixels with mask value == 0.')
3434
parser.add_argument('-o', '--outfile', help='Output file name.')
3535

3636
# modify input mask
37-
parser.add_argument('-t', dest='threshold', type=float,
38-
help='threshold value used for masking.\n' +
39-
'if not specified, only pixels with mask value equal to zero is masked out.')
40-
parser.add_argument('--fill', dest='fill_value', type=float, default=math.nan,
41-
help="fill masked out area with input value. i.e. \n"
42-
"np.nan (default), 0, 1000, ... \n"
43-
"If np.nan and input data matrix is not float/complex, convert matrix data type to np.float32.")
37+
parser.add_argument('--vmin','--mask-vmin', dest='mask_vmin', type=float,
38+
help='mask out pixels with mask value < vmin.')
39+
parser.add_argument('--vmax','--mask-vmax', dest='mask_vmax', type=float,
40+
help='mask out pixels with mask value > vmax.')
4441
parser.add_argument('-x', dest='subset_x', type=int, nargs=2,
4542
help='subset range in x/cross-track/column direction')
4643
parser.add_argument('-y', dest='subset_y', type=int, nargs=2,
4744
help='subset range in y/along-track/row direction')
45+
parser.add_argument('--fill', dest='fill_value', type=float, default=math.nan,
46+
help='fill masked out area with input value. i.e. \n'
47+
'np.nan (default), 0, 1000, ... \n'
48+
'If np.nan and input data matrix is not float/complex, '
49+
'convert matrix data type to np.float32.')
4850
return parser
4951

5052

src/mintpy/cli/view.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
view.py velocity.h5 velocity --wrap --wrap-range -2 2 -c cmy --lalo-label
2020
view.py velocity.h5 --ref-yx 210 566 #change reference pixel for display
2121
view.py velocity.h5 --sub-lat 31.05 31.10 --sub-lon 130.05 130.10 #subset in lalo / yx
22+
view.py velocity.h5 velocity --mask waterBody.h5 --mask-vmax 1
2223
2324
view.py timeseries.h5
24-
view.py timeseries.h5 -m no #do not use auto mask
2525
view.py timeseries.h5 --ref-date 20101120 #change reference date
2626
view.py timeseries.h5 --ex drop_date.txt #exclude dates to plot
2727
view.py timeseries.h5 '*2017*' '*2018*' #all acquisitions in 2017 and 2018
@@ -32,8 +32,6 @@
3232
view.py ifgramStack.h5 -n 6 #the 6th slice
3333
view.py ifgramStack.h5 20171010_20171115 #all data related with 20171010_20171115
3434
view.py ifgramStack.h5 'coherence*20171010*' #all coherence related with 20171010
35-
view.py ifgramStack.h5 unwrapPhase-20070927_20100217 --zero-mask --wrap #wrapped phase
36-
view.py ifgramStack.h5 unwrapPhase-20070927_20100217 --mask ifgramStack.h5 #mask using connected components
3735
3836
# GPS (for one subplot in geo-coordinates only)
3937
view.py geo_velocity_msk.h5 velocity --show-gps --gps-label #show locations of available GPS

src/mintpy/mask.py

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,27 @@ def mask_matrix(data, mask, fill_value=np.nan):
3636

3737

3838
def update_mask_with_inps(mask, inps, print_msg=True):
39-
"""Update mask matrix from input options: subset_x/y and threshold"""
39+
"""Update mask matrix from input options: subset_x/y and mask_vmin/vmax."""
40+
vprint = print if print_msg else lambda *args, **kwargs: None
41+
4042
if inps.subset_x:
4143
mask[:, 0:inps.subset_x[0]] = 0
4244
mask[:, inps.subset_x[1]:] = 0
43-
if print_msg:
44-
print(f'mask out area not in x: {inps.subset_x}')
45+
vprint(f'mask out area not in x: {inps.subset_x}')
4546

4647
if inps.subset_y:
4748
mask[0:inps.subset_y[0], :] = 0
4849
mask[inps.subset_y[1]:, :] = 0
49-
if print_msg:
50-
print(f'mask out area not in y: {inps.subset_y}')
50+
vprint(f'mask out area not in y: {inps.subset_y}')
51+
52+
if inps.mask_vmin:
53+
mask = mask >= inps.mask_vmin
54+
vprint(f'mask out pixels with value < {inps.mask_vmin} in mask file')
55+
56+
if inps.mask_vmax:
57+
mask = mask <= inps.mask_vmax
58+
vprint(f'mask out pixels with value > {inps.mask_vmax} in mask file')
5159

52-
if inps.threshold:
53-
mask[mask < inps.threshold] = 0
54-
if print_msg:
55-
print(f'mask out pixels with value < {inps.threshold} in mask file')
5660
return mask
5761

5862

@@ -62,9 +66,8 @@ def mask_file(fname, mask_file, out_file=None, fill_value=np.nan, inps=None):
6266
mask_file - str, mask file
6367
out_file - str, output file name
6468
inps - namespace object, including:
65-
subset_x
66-
subset_y
67-
threshold
69+
subset_x/y
70+
mask_vmin/vmax
6871
Returns: out_file - str, output file name
6972
"""
7073

@@ -121,18 +124,21 @@ def mask_isce_file(in_file, mask_file, out_file=None):
121124
print('setting the (phase) value on the masked out pixels to zero')
122125
fbase, ext = os.path.splitext(in_file)
123126
if ext == '.unw':
124-
amp = readfile.read_binary(in_file, (length, width), data_type=data_type,
125-
num_band=num_band, interleave=interleave, band=1)
126-
pha = readfile.read_binary(in_file, (length, width), data_type=data_type,
127-
num_band=num_band, interleave=interleave, band=2)
127+
kwargs = dict(
128+
shape=(length, width),
129+
data_type=data_type,
130+
num_band=num_band,
131+
interleave=interleave,
132+
)
133+
amp = readfile.read_binary(in_file, band=1, **kwargs)
134+
pha = readfile.read_binary(in_file, band=2, **kwargs)
128135
pha[mask == 0] = 0
129136
data = np.hstack((amp, pha)).flatten()
130137
elif ext == '.int':
131138
data = np.fromfile(in_file, dtype=data_type, count=length*width).reshape(-1, width)
132-
#data[mask == 0] = np.abs(data[mask == 0]) #set the angle of complex data to zero
133139
data[mask == 0] = 0
134140
elif ext in ['.cor','.conncomp']:
135-
data = readfile.read(in_file)[0] #, data_type=data_type, num_band=num_band, band_interleave=interleave, band=1)[0]
141+
data = readfile.read(in_file)[0]
136142
data[mask == 0] = 0
137143
else:
138144
raise ValueError(f'unsupported ISCE file: {in_file}')

src/mintpy/objects/coord.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,22 @@ class coordinate:
2828
(bounding) box of points indicate the lat/lon of the pixel UL corner.
2929
3030
Example:
31+
from mintpy.utils import readfile, utils as ut
3132
atr = readfile.read('velocity.h5')
32-
coord = ut.coordinate(atr, lookup_file='inputs/geometryRadar.h5') # for radar coord file
33-
coord = ut.coordinate(atr) # for geo coord file
33+
coord = ut.coordinate(atr) # geo coord
34+
coord = ut.coordinate(atr, lookup_file='inputs/geometryRadar.h5') # radar coord
35+
coord = ut.coordinate(atr, lookup_file=['lat.rdr', 'lon.rdr']) # radar coord in isce2 format
3436
y, x = coord.geo2radar(lat, lon)[0:2]
3537
lat, lon = coord.radar2geo(y, x)[0:2]
3638
"""
3739

3840
def __init__(self, metadata, lookup_file=None):
3941
"""Define a coordinate object
4042
Parameters: metadata - dict, source metadata
41-
lookup_file - list of 2 strings, or string, lookup table file(s)
42-
Example: from mintpy.utils import readfile, utils as ut
43-
atr = readfile.read_attribute('./velocity.h5')
44-
coord = ut.coordinate(atr, './inputs/geometryRadar.h5')
45-
coord.geo2radar(33.450, -90.22)
46-
coord.radar2geo(50, 200)
43+
lookup_file - str / list of 2 str, lookup table file(s)
44+
'geometryRadar.h5'
45+
['lat.rdr', 'lon.rdr']
46+
Returns: mintpy.utils.utils.coordinate object
4747
"""
4848
self.src_metadata = metadata
4949
if lookup_file is None:

src/mintpy/utils/isce_utils.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,7 @@ def unwrap_snaphu(int_file, cor_file, unw_file, defo_max=2.0, max_comp=32,
10061006
cost_mode = 'DEFO'
10071007
10081008
Parameters: int_file - str, path to the wrapped interferogram file
1009-
cor_file - str, path to the correlation file
1009+
cor_file - str, path to the correlation file: phase sigma or complex correlation
10101010
unw_file - str, path to the output unwrapped interferogram file
10111011
defo_max - float, maximum number of cycles for the deformation phase
10121012
max_comp - int, maximum number of connected components
@@ -1046,9 +1046,12 @@ def unwrap_snaphu(int_file, cor_file, unw_file, defo_max=2.0, max_comp=32,
10461046
snp.setInput(int_file)
10471047
snp.setOutput(unw_file)
10481048
snp.setCorrfile(cor_file)
1049-
snp.setCorFileFormat('FLOAT_DATA')
10501049
snp.setWidth(width)
10511050

1051+
atr_cor = readfile.read_attribute(cor_file)
1052+
if int(atr_cor.get('BANDS', 1)) == 1:
1053+
snp.setCorFileFormat('FLOAT_DATA')
1054+
10521055
# runtime options
10531056
snp.setCostMode(cost_mode)
10541057
snp.setInitOnly(init_only)

src/mintpy/utils/plot.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1785,14 +1785,15 @@ def read_mask(fname, mask_file=None, datasetName=None, box=None, xstep=1, ystep=
17851785
if mask is not None:
17861786
mask[np.isnan(mask)] = 0
17871787

1788-
# vmin/max
1788+
# vmin/vmax: create mask based on the input thresholds
17891789
if vmin is not None:
1790-
mask[mask < vmin] = 0
1790+
mask = mask >= vmin
17911791
vprint(f'hide pixels with mask value < {vmin}')
17921792
if vmax is not None:
1793-
mask[mask > vmax] = 0
1793+
mask = mask <= vmax
17941794
vprint(f'hide pixels with mask value > {vmax}')
17951795

1796+
# set to bool type
17961797
mask = mask != 0
17971798

17981799
return mask, mask_file

src/mintpy/utils/readfile.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,12 @@ def read_binary_file(fname, datasetName=None, box=None, xstep=1, ystep=1):
581581

582582
band = min(band, num_band)
583583

584+
# check file size
585+
fsize = os.path.getsize(fname)
586+
dsize = np.dtype(data_type).itemsize * length * width * num_band
587+
if dsize != fsize:
588+
warnings.warn(f'file size ({fsize}) does NOT match with metadata ({dsize})!')
589+
584590
# ROI_PAC
585591
elif processor in ['roipac']:
586592
# data structure - auto

0 commit comments

Comments
 (0)