Skip to content

Commit

Permalink
merge branch develop into compress-mask
Browse files Browse the repository at this point in the history
  • Loading branch information
asjohnston-asf committed Jul 13, 2023
2 parents ca91bd7 + 0a7d06c commit 288243f
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 19 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [PEP 440](https://www.python.org/dev/peps/pep-0440/)
and uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.6.1]
### Added
* `apply_water_mask` optional argument to apply water mask in the output geotiff files

## [0.6.0]
### Changed
* Pixel sizes of output GeoTIFFs now better reflect their resolution: 80m for 20x4 looks, 40m for 10x2 looks, and 20m for 5x1 looks.


## [0.5.0]
### Changed
Expand Down
4 changes: 2 additions & 2 deletions images/coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 0 additions & 4 deletions src/hyp3_isce2/dem.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
from lxml import etree
from shapely.geometry import box

DEM_RESOLUTION = 0.0002777777777777777775


def tag_dem_xml_as_ellipsoidal(dem_path: Path) -> str:
xml_path = str(dem_path) + '.xml'
Expand Down Expand Up @@ -85,8 +83,6 @@ def download_dem_for_isce2(
dst_ellipsoidal_height=True,
dst_area_or_point='Point',
n_threads_downloading=5,
# ensures square resolution
dst_resolution=DEM_RESOLUTION,
)
dem_array[np.isnan(dem_array)] = 0.

Expand Down
35 changes: 24 additions & 11 deletions src/hyp3_isce2/insar_tops_burst.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ def make_readme(
reference_scene: str,
secondary_scene: str,
range_looks: int,
azimuth_looks: int) -> None:
azimuth_looks: int,
apply_water_mask: bool) -> None:

wrapped_phase_path = product_dir / f'{product_name}_wrapped_phase.tif'
info = gdal.Info(str(wrapped_phase_path), format='json')
Expand All @@ -140,6 +141,7 @@ def make_readme(
'secondary_granule_date': datetime.strptime(secondary_granule_datetime_str, '%Y%m%dT%H%M%S'),
'dem_name': 'GLO-30',
'dem_pixel_spacing': '30 m',
'apply_water_mask': apply_water_mask
}
content = hyp3_isce2.metadata.util.render_template('insar_burst/readme.md.txt.j2', payload)

Expand All @@ -156,7 +158,7 @@ def make_parameter_file(
azimuth_looks: int,
range_looks: int,
dem_name: str = 'GLO_30',
dem_resolution: int = 30
dem_resolution: int = 30,
) -> None:
"""Create a parameter file for the output product
Expand Down Expand Up @@ -254,7 +256,7 @@ def make_parameter_file(
outfile.write(output_string)


def translate_outputs(isce_output_dir: Path, product_name: str):
def translate_outputs(isce_output_dir: Path, product_name: str, pixel_size: float = 30.):
"""Translate ISCE outputs to a standard GTiff format with a UTM projection
Args:
Expand Down Expand Up @@ -349,9 +351,15 @@ def translate_outputs(isce_output_dir: Path, product_name: str):
file,
dstSRS=f'epsg:{epsg}',
creationOptions=['TILED=YES', 'COMPRESS=LZW', 'NUM_THREADS=ALL_CPUS'],
xRes=pixel_size,
yRes=pixel_size,
targetAlignedPixels=True
)

make_browse_image(f'{product_name}/{product_name}_unw_phase.tif', f'{product_name}/{product_name}_unw_phase.png')

def get_pixel_size(choice):
choices = {'20x4': 80.0, '10x2': 40.0, '5x1': 20.0}
return choices[choice]


def main():
Expand Down Expand Up @@ -406,13 +414,15 @@ def main():
product_dir = Path(product_name)
product_dir.mkdir(parents=True, exist_ok=True)

translate_outputs(isce_output_dir, product_name)
pixel_size = get_pixel_size(args.looks)
translate_outputs(isce_output_dir, product_name, pixel_size=pixel_size)

unwrapped_phase = f'{product_name}/{product_name}_unw_phase.tif'
wrapped_phase = f'{product_name}/{product_name}_wrapped_phase.tif'
water_mask = f'{product_name}/{product_name}_water_mask.tif'
create_water_mask(wrapped_phase, water_mask)

if args.apply_water_mask:
unwrapped_phase = f'{product_name}/{product_name}_unw_phase.tif'
wrapped_phase = f'{product_name}/{product_name}_wrapped_phase.tif'
water_mask = f'{product_name}/{product_name}_water_mask.tif'
create_water_mask(wrapped_phase, water_mask)
for geotiff in [wrapped_phase, unwrapped_phase]:
cmd = (
'gdal_calc.py '
Expand All @@ -425,21 +435,24 @@ def main():
)
subprocess.check_call(cmd.split(' '))

make_browse_image(unwrapped_phase, f'{product_name}/{product_name}_unw_phase.png')

make_readme(
product_dir=product_dir,
product_name=product_name,
reference_scene=reference_scene,
secondary_scene=secondary_scene,
range_looks=range_looks,
azimuth_looks=azimuth_looks
azimuth_looks=azimuth_looks,
apply_water_mask=args.apply_water_mask
)
make_parameter_file(
Path(f'{product_name}/{product_name}.txt'),
reference_scene=reference_scene,
secondary_scene=secondary_scene,
azimuth_looks=azimuth_looks,
range_looks=range_looks,
swath_number=swath_number
swath_number=swath_number,
)
output_zip = make_archive(base_name=product_name, format='zip', base_dir=product_name)

Expand Down
32 changes: 31 additions & 1 deletion src/hyp3_isce2/metadata/templates/insar_burst/readme.md.txt.j2
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ The files generated in this process include:
5. Parameter Documentation (Text File)
6. Look Vector Maps (GeoTIFFs)
7. DEM used to process the data (GeoTIFF)
8. README.md.txt (Text File)
8. Water Mask (GeoTIFF)
9. README.md.txt (Text File)

*See below for detailed descriptions of each of the product files.*

Expand Down Expand Up @@ -196,6 +197,10 @@ unexpected/invalid phase unwrapping results over land. Masking areas of water be
used to mitigate this issue, but ISCE2 does not currently support this functionality. Thus, use caution when
interpreting unwrapped phase results close to surface water.

There is the option to apply a water mask *after* phase unwrapping. While it doesn't correct for phase unwrapping
errors over water, it can make the interferograms less visually distracting. This product
{{ "has" if apply_water_mask else "has not" }} had a water mask applied.

No atmospheric correction has been applied to this interferogram. While SAR signals can penetrate clouds,
atmospheric conditions can delay the transmission of the signal, resulting in phase differences between acquisition
that can look like surface deformation signals. Use caution when interpreting single interferograms. In some cases,
Expand Down Expand Up @@ -258,6 +263,31 @@ Defence and Space, and edited to flatten water bodies, provide consistent flow o
shore/coastlines and special features. For an overview of the dataset, visit
https://spacedata.copernicus.eu/collections/copernicus-digital-elevation-model.

----------------
## 8. Water Mask

The water mask identifies coastal waters and major inland waterbodies. These areas are assigned a pixel value of 0.
All remaining pixels (land, islands in large lakes, small inland waterbodies, and landfast Antarctic ice) have
a value of 1. The water mask is stored as an 8-bit unsigned integer GeoTIFF file and is always included in the product
package.

Users can choose to apply the water mask to output products, which affects the wrapped interferogram,
the unwrapped interferogram, and the browse images. It returns NoData values over the areas covered by the water mask
in these output images. This product {{ "has" if apply_water_mask else "has not" }} had the water mask applied.

The water mask is generated using the Global Self-consistent, Hierarchical, High-resolution Geography Database (GSHHG)
dataset (https://www.ngdc.noaa.gov/mgg/shorelines). To generate the global mask, we combined the full-resolution
L1 and L5 datasets, and removed the L2 dataset minus the L3 dataset. The L1 dataset is the boundary between land
and ocean, excluding Antarctica, and the L5 dataset is the boundary between Antarctic ice and ocean. The L2
dataset is the boundary between lakes and land, and the L3 dataset is the boundary between islands and the
lakes they are within. The GSHHG dataset was last updated in 2017, so there may be discrepancies where
shorelines have changed.

ISCE2 currently only supports applying a water mask to an interferogram *after* phase unwrapping. Note that
applying the mask after phase unwrapping does not prevent unwrapping errors caused by the inclusion of water pixels
as valid data during the phase unwrapping process. When phase unwrapping occurs over large expanses of water, it can
lead to unexpected deformation signals or phase jumps in the unwrapped outputs, and the current masking approach
does not correct for these impacts.

*************
# Burst InSAR Processing #
Expand Down
1 change: 0 additions & 1 deletion tests/test_dem.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ def test_download_dem_for_isce2(tmp_path):
dst_ellipsoidal_height=True,
dst_area_or_point='Point',
n_threads_downloading=5,
dst_resolution=dem.DEM_RESOLUTION,
)

root = etree.parse(str(dem_path) + '.xml').getroot()
Expand Down

0 comments on commit 288243f

Please sign in to comment.