Skip to content

Commit d4c8328

Browse files
replace real/imag stats with power/phase stats (#150)
* replace stats real/imag with power/phase * add pytest-order to force test CSLC HDF5 to be generated 1st * update specifile.txt with pytest-order Co-authored-by: Seongsu Jeong <[email protected]>
1 parent 7ffab31 commit d4c8328

File tree

6 files changed

+55
-24
lines changed

6 files changed

+55
-24
lines changed

docker/specfile.txt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# platform: linux-64
44
@EXPLICIT
55
https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2
6-
https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2022.12.7-ha878542_0.conda
6+
https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2023.5.7-hbcca054_0.conda
77
https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2
88
https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2
99
https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2
@@ -61,7 +61,7 @@ https://conda.anaconda.org/conda-forge/linux-64/libzopfli-1.0.3-h9c3ff4c_0.tar.b
6161
https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda
6262
https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.3-h27087fc_1.tar.bz2
6363
https://conda.anaconda.org/conda-forge/linux-64/nspr-4.35-h27087fc_0.conda
64-
https://conda.anaconda.org/conda-forge/linux-64/openssl-3.1.0-h0b41bf4_0.conda
64+
https://conda.anaconda.org/conda-forge/linux-64/openssl-3.1.0-hd590300_3.conda
6565
https://conda.anaconda.org/conda-forge/linux-64/pixman-0.40.0-h36c2ea0_0.tar.bz2
6666
https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-h36c2ea0_1001.tar.bz2
6767
https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.10-h9fff704_0.conda
@@ -122,7 +122,7 @@ https://conda.anaconda.org/conda-forge/noarch/backoff-2.2.1-pyhd8ed1ab_0.tar.bz2
122122
https://conda.anaconda.org/conda-forge/linux-64/brotli-1.0.9-h166bdaf_8.tar.bz2
123123
https://conda.anaconda.org/conda-forge/linux-64/c-compiler-1.5.2-h0b41bf4_0.conda
124124
https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2
125-
https://conda.anaconda.org/conda-forge/noarch/certifi-2022.12.7-pyhd8ed1ab_0.conda
125+
https://conda.anaconda.org/conda-forge/noarch/certifi-2023.5.7-pyhd8ed1ab_0.conda
126126
https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-2.1.1-pyhd8ed1ab_0.tar.bz2
127127
https://conda.anaconda.org/conda-forge/noarch/click-8.1.3-unix_pyhd8ed1ab_2.tar.bz2
128128
https://conda.anaconda.org/conda-forge/noarch/cloudpickle-2.2.1-pyhd8ed1ab_0.conda
@@ -219,6 +219,7 @@ https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.1.1-pyhd8ed1ab_0.co
219219
https://conda.anaconda.org/conda-forge/linux-64/poppler-23.03.0-hf052cbe_1.conda
220220
https://conda.anaconda.org/conda-forge/linux-64/pyproj-3.4.1-py311h945b3ca_1.conda
221221
https://conda.anaconda.org/conda-forge/linux-64/pyre-1.11.2-py311hbbb8f27_3.tar.bz2
222+
https://conda.anaconda.org/conda-forge/noarch/pytest-order-1.0.1-pyhd8ed1ab_0.tar.bz2
222223
https://conda.anaconda.org/conda-forge/linux-64/tiledb-2.13.2-hd532e3d_0.conda
223224
https://conda.anaconda.org/conda-forge/noarch/geopandas-base-0.12.2-pyha770c72_0.conda
224225
https://conda.anaconda.org/conda-forge/linux-64/libgdal-3.6.3-h93ed92d_1.conda
@@ -242,4 +243,4 @@ https://conda.anaconda.org/conda-forge/linux-64/scikit-learn-1.2.2-py311h67c5ca5
242243
https://conda.anaconda.org/conda-forge/noarch/mapclassify-2.5.0-pyhd8ed1ab_1.conda
243244
https://conda.anaconda.org/conda-forge/linux-64/pysolid-0.2.3-py311ha29c927_1.tar.bz2
244245
https://conda.anaconda.org/conda-forge/noarch/geopandas-0.12.2-pyhd8ed1ab_0.conda
245-
https://conda.anaconda.org/conda-forge/noarch/dem_stitcher-2.4.0-pyhd8ed1ab_0.conda
246+
https://conda.anaconda.org/conda-forge/noarch/dem_stitcher-2.4.0-pyhd8ed1ab_0.conda

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pandas
88
pyproj
99
pysolid
1010
pytest
11+
pytest-order
1112
ruamel.yaml
1213
scipy
1314
yamale

src/compass/s1_cslc_qa.py

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,19 @@
1111
QA_PATH, add_dataset_and_attrs, Meta)
1212

1313

14+
def _compute_slc_array_stats(arr: np.ndarray, pwr_phase: str):
15+
# internal to function to compute min, max, mean, and std dev of power or
16+
# phase of SLC array. Default to phase stat computation.
17+
if pwr_phase == 'power':
18+
post_op_arr = np.abs(arr)**2
19+
else:
20+
post_op_arr = np.angle(arr)
21+
22+
return [np_op(post_op_arr)
23+
for np_op in [np.nanmean, np.nanmin, np.nanmax,
24+
np.nanstd]]
25+
26+
1427
def value_description_dict(val, desc):
1528
'''
1629
Convenience function that returns dict with description and value
@@ -64,40 +77,32 @@ def compute_CSLC_raster_stats(self, cslc_h5py_root, bursts):
6477

6578
# get dataset and compute stats according to dtype
6679
pol_path = f'{DATA_PATH}/{pol}'
67-
pol_ds = cslc_h5py_root[pol_path]
68-
69-
# compute stats for real and complex
70-
stat_obj = isce3.math.StatsRealImagFloat32(pol_ds[()])
80+
pol_arr = cslc_h5py_root[pol_path][()]
7181

7282
# create dict for current polarization
7383
self.stats_dict[pol] = {}
7484
pol_dict = self.stats_dict[pol]
7585

76-
# write stats to HDF5
77-
for real_imag, cstat_member in zip(['real', 'imaginary'],
78-
[stat_obj.real, stat_obj.imag]):
86+
# compute power or phase then write stats to HDF5 for CSLC
87+
for pwr_phase in ['power', 'phase']:
7988
# create dict to store real/imaginary stat items
80-
pol_dict[real_imag] = {}
89+
pol_dict[pwr_phase] = {}
8190

82-
# create HDF5 group for real/imaginary stats of current
91+
# create HDF5 group for power or phase stats of current
8392
# polarization
84-
h5_stats_path = f'{QA_PATH}/statistics/data/{pol}/{real_imag}'
93+
h5_stats_path = f'{QA_PATH}/statistics/data/{pol}/{pwr_phase}'
8594
stats_group = cslc_h5py_root.require_group(h5_stats_path)
8695

87-
# add description for stat items
88-
suffix_qa_item_desc = f'{real_imag} part of geoocoded SLC'
89-
90-
# build list of QA stat items for real_imag
96+
# build list of QA stat items for pwr_phase
9197
qa_items = []
92-
vals = [cstat_member.mean, cstat_member.min,
93-
cstat_member.max, cstat_member.sample_stddev]
98+
vals = _compute_slc_array_stats(pol_arr, pwr_phase)
9499
for val_name, val in zip(self.stat_names, vals):
95-
desc = f'{val_name} of {suffix_qa_item_desc}'
100+
desc = f'{val_name} of {pwr_phase} of {pol} geocoded SLC'
96101
qa_items.append(Meta(val_name, val, desc))
97102

98103
# save stats to dict and write to HDF5
99-
_qa_items_to_h5_and_dict(stats_group, pol_dict[real_imag],
100-
qa_items)
104+
_qa_items_to_h5_and_dict(stats_group, pol_dict[pwr_phase],
105+
qa_items)
101106

102107

103108
def compute_static_layer_stats(self, cslc_h5py_root, rdr2geo_params):

src/compass/utils/browse_image.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def _normalize_apply_gamma(image, vmin, vmax, gamma=1.0):
9494
Normalized and gamma corrected image
9595
'''
9696
if vmax <= vmin:
97-
raise ValueError('maximum value not > minimum value')
97+
raise ValueError(f'maximum value {vmax} not > minimum value {vmin}')
9898

9999
# scale to 0-1 for gray scale and then apply gamma correction
100100
image = (image - vmin) / (vmax - vmin)

tests/test_qa.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import h5py
2+
import numpy as np
3+
4+
from compass.utils.h5_helpers import QA_PATH
5+
6+
def test_qa_power_stats(geocode_slc_params):
7+
def _power_test(arr):
8+
return arr > 0.0
9+
10+
def _phase_test(arr):
11+
return abs(arr) <= np.pi
12+
13+
# basic sanity checks of mean, min, and max
14+
with h5py.File(geocode_slc_params.output_hdf5_path, 'r') as h5_obj:
15+
for pwr_phase, test in {'power':_power_test,
16+
'phase':_phase_test}.items():
17+
h5_stats_path = f'{QA_PATH}/statistics/data/VV/{pwr_phase}'
18+
stat_names = ['mean', 'min', 'max']
19+
for stat_name in stat_names:
20+
print(f'Testing: {stat_name} of {pwr_phase}')
21+
stat_val = h5_obj[f'{h5_stats_path}/{stat_name}'][()]
22+
assert test(stat_val)

tests/test_s1_geocode_slc.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
import h5py
44
import isce3
55
import numpy as np
6+
import pytest
67

78
from compass import s1_geocode_slc
89
from compass.utils.geo_runconfig import GeoRunConfig
910

1011

12+
@pytest.mark.order(1)
1113
def test_geocode_slc_run(geocode_slc_params):
1214
'''
1315
Run s1_geocode_slc to ensure it does not crash

0 commit comments

Comments
 (0)