From b08adc43a115f585d911db9ec2fe5517b95c0664 Mon Sep 17 00:00:00 2001 From: Joseph H Kennedy Date: Fri, 14 Jun 2024 12:48:46 -0800 Subject: [PATCH 01/23] No need to provide ESA credentials arguments for s1_correction workflow; just use netrc or env vars --- src/hyp3_autorift/s1_correction.py | 2 -- src/hyp3_autorift/s1_isce2.py | 6 +----- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/hyp3_autorift/s1_correction.py b/src/hyp3_autorift/s1_correction.py index dc5995a1..8b8d4338 100644 --- a/src/hyp3_autorift/s1_correction.py +++ b/src/hyp3_autorift/s1_correction.py @@ -16,8 +16,6 @@ def main(): ) parser.add_argument('--bucket', help='AWS bucket to upload product files to') parser.add_argument('--bucket-prefix', default='', help='AWS prefix (location in bucket) to add to product files') - parser.add_argument('--esa-username', default=None, help="Username for ESA's Copernicus Data Space Ecosystem") - parser.add_argument('--esa-password', default=None, help="Password for ESA's Copernicus Data Space Ecosystem") parser.add_argument('--buffer', type=int, default=0, help='Number of pixels to buffer each edge of the input scene') parser.add_argument('--parameter-file', default=DEFAULT_PARAMETER_FILE, help='Shapefile for determining the correct search parameters by geographic location. ' diff --git a/src/hyp3_autorift/s1_isce2.py b/src/hyp3_autorift/s1_isce2.py index c1b2ee97..5127fb59 100644 --- a/src/hyp3_autorift/s1_isce2.py +++ b/src/hyp3_autorift/s1_isce2.py @@ -5,7 +5,6 @@ import textwrap from datetime import timedelta from pathlib import Path -from typing import Optional import numpy as np from hyp3lib.fetch import download_file @@ -93,8 +92,6 @@ def generate_correction_data( scene: str, buffer: int = 0, parameter_file: str = DEFAULT_PARAMETER_FILE, - esa_username: Optional[str] = None, - esa_password: Optional[str] = None, ): from hyp3_autorift.vend.testGeogrid_ISCE import loadParsedata, runGeogrid scene_path = Path(f'{scene}.zip') @@ -105,8 +102,7 @@ def generate_correction_data( orbits = Path('Orbits').resolve() orbits.mkdir(parents=True, exist_ok=True) - if (esa_username is None) or (esa_password is None): - esa_username, esa_password = get_esa_credentials() + esa_username, esa_password = get_esa_credentials() state_vec, oribit_provider = downloadSentinelOrbitFile( scene, directory=str(orbits), esa_credentials=(esa_username, esa_password) From 9ca9fbf06f94df5c57d3a104877af6beb47c58a0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jun 2024 16:07:07 +0000 Subject: [PATCH 02/23] Bump ASFHyP3/actions from 0.11.0 to 0.11.1 Bumps [ASFHyP3/actions](https://github.com/asfhyp3/actions) from 0.11.0 to 0.11.1. - [Release notes](https://github.com/asfhyp3/actions/releases) - [Changelog](https://github.com/ASFHyP3/actions/blob/develop/CHANGELOG.md) - [Commits](https://github.com/asfhyp3/actions/compare/v0.11.0...v0.11.1) --- updated-dependencies: - dependency-name: ASFHyP3/actions dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/changelog.yml | 2 +- .github/workflows/create-jira-issue.yml | 2 +- .github/workflows/labeled-pr.yml | 2 +- .github/workflows/release-template-comment.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/static-analysis.yml | 4 ++-- .github/workflows/tag-version.yml | 2 +- .github/workflows/test-and-build.yml | 6 +++--- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 3ce6f429..6b6bbdaa 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -13,6 +13,6 @@ on: jobs: call-changelog-check-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-changelog-check.yml@v0.11.0 + uses: ASFHyP3/actions/.github/workflows/reusable-changelog-check.yml@v0.11.1 secrets: USER_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/create-jira-issue.yml b/.github/workflows/create-jira-issue.yml index 0b69efec..129ff5f1 100644 --- a/.github/workflows/create-jira-issue.yml +++ b/.github/workflows/create-jira-issue.yml @@ -6,7 +6,7 @@ on: jobs: call-create-jira-issue-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-create-jira-issue.yml@v0.11.0 + uses: ASFHyP3/actions/.github/workflows/reusable-create-jira-issue.yml@v0.11.1 secrets: JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} diff --git a/.github/workflows/labeled-pr.yml b/.github/workflows/labeled-pr.yml index 66ba502e..3ba21604 100644 --- a/.github/workflows/labeled-pr.yml +++ b/.github/workflows/labeled-pr.yml @@ -12,4 +12,4 @@ on: jobs: call-labeled-pr-check-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-labeled-pr-check.yml@v0.11.0 + uses: ASFHyP3/actions/.github/workflows/reusable-labeled-pr-check.yml@v0.11.1 diff --git a/.github/workflows/release-template-comment.yml b/.github/workflows/release-template-comment.yml index cae89e6f..01d20589 100644 --- a/.github/workflows/release-template-comment.yml +++ b/.github/workflows/release-template-comment.yml @@ -7,6 +7,6 @@ on: jobs: call-release-checklist-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-release-checklist-comment.yml@v0.11.0 + uses: ASFHyP3/actions/.github/workflows/reusable-release-checklist-comment.yml@v0.11.1 secrets: USER_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c8fed248..f04a3669 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,7 +7,7 @@ on: jobs: call-release-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-release.yml@v0.11.0 + uses: ASFHyP3/actions/.github/workflows/reusable-release.yml@v0.11.1 with: release_prefix: HyP3 autoRIFT secrets: diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 3b07f93b..6e006ab8 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -4,10 +4,10 @@ on: push jobs: call-flake8-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-flake8.yml@v0.11.0 + uses: ASFHyP3/actions/.github/workflows/reusable-flake8.yml@v0.11.1 with: local_package_names: hyp3_autorift excludes: src/hyp3_autorift/vend call-secrets-analysis-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-secrets-analysis.yml@v0.11.0 + uses: ASFHyP3/actions/.github/workflows/reusable-secrets-analysis.yml@v0.11.1 diff --git a/.github/workflows/tag-version.yml b/.github/workflows/tag-version.yml index 4714c1f1..7bc79246 100644 --- a/.github/workflows/tag-version.yml +++ b/.github/workflows/tag-version.yml @@ -7,6 +7,6 @@ on: jobs: call-bump-version-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-bump-version.yml@v0.11.0 + uses: ASFHyP3/actions/.github/workflows/reusable-bump-version.yml@v0.11.1 secrets: USER_TOKEN: ${{ secrets.TOOLS_BOT_PAK }} diff --git a/.github/workflows/test-and-build.yml b/.github/workflows/test-and-build.yml index cee1a1e2..cfc16752 100644 --- a/.github/workflows/test-and-build.yml +++ b/.github/workflows/test-and-build.yml @@ -12,18 +12,18 @@ on: jobs: call-pytest-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-pytest.yml@v0.11.0 + uses: ASFHyP3/actions/.github/workflows/reusable-pytest.yml@v0.11.1 with: local_package_name: hyp3_autorift python_versions: >- ["3.9"] call-version-info-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-version-info.yml@v0.11.0 + uses: ASFHyP3/actions/.github/workflows/reusable-version-info.yml@v0.11.1 call-docker-ghcr-workflow: needs: call-version-info-workflow - uses: ASFHyP3/actions/.github/workflows/reusable-docker-ghcr.yml@v0.11.0 + uses: ASFHyP3/actions/.github/workflows/reusable-docker-ghcr.yml@v0.11.1 with: version_tag: ${{ needs.call-version-info-workflow.outputs.version_tag }} secrets: From 3119c017dbdf13588857ebcd87c99773e39a7a6e Mon Sep 17 00:00:00 2001 From: Jake Herrmann Date: Mon, 17 Jun 2024 09:20:10 -0800 Subject: [PATCH 03/23] Update .github/workflows/changelog.yml --- .github/workflows/changelog.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 6b6bbdaa..6047ddb1 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -14,5 +14,3 @@ on: jobs: call-changelog-check-workflow: uses: ASFHyP3/actions/.github/workflows/reusable-changelog-check.yml@v0.11.1 - secrets: - USER_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 9c868f708167c100b69aaf1a85ed391df33cbbe1 Mon Sep 17 00:00:00 2001 From: Joseph H Kennedy Date: Mon, 17 Jun 2024 12:46:31 -0800 Subject: [PATCH 04/23] update utils load geospatial to return srs info --- src/hyp3_autorift/process.py | 2 +- src/hyp3_autorift/utils.py | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/hyp3_autorift/process.py b/src/hyp3_autorift/process.py index 38f5d9f8..0ff7b60d 100644 --- a/src/hyp3_autorift/process.py +++ b/src/hyp3_autorift/process.py @@ -242,7 +242,7 @@ def apply_wallis_nodata_fill_filter(array: np.ndarray, nodata: int) -> Tuple[np. def _apply_filter_function(image_path: str, filter_function: Callable) -> Tuple[str, Optional[str]]: - image_array, image_transform, image_projection, image_nodata = utils.load_geospatial(image_path) + image_array, image_transform, image_projection, _, image_nodata = utils.load_geospatial(image_path) image_array = image_array.astype(np.float32) image_filtered, zero_mask = filter_function(image_array, image_nodata) diff --git a/src/hyp3_autorift/utils.py b/src/hyp3_autorift/utils.py index a36a80a4..f2c58e85 100644 --- a/src/hyp3_autorift/utils.py +++ b/src/hyp3_autorift/utils.py @@ -125,10 +125,13 @@ def load_geospatial(infile: str, band: int = 1): data = ds.GetRasterBand(band).ReadAsArray() nodata = ds.GetRasterBand(band).GetNoDataValue() - projection = ds.GetProjection() + transform = ds.GetGeoTransform() + projection = ds.GetProjection() + srs = ds.GetSpatialRef() + del ds - return data, transform, projection, nodata + return data, transform, projection, srs, nodata def write_geospatial(outfile: str, data, transform, projection, nodata, From f51ad18ab75de2d22877205d2150954e32795a88 Mon Sep 17 00:00:00 2001 From: Joseph H Kennedy Date: Tue, 18 Jun 2024 14:01:02 -0800 Subject: [PATCH 05/23] Create M conversion matricies netCDF as part of S1 correction workflow --- src/hyp3_autorift/s1_correction.py | 3 +- src/hyp3_autorift/s1_isce2.py | 166 ++++++++++++++++++++++++++++- 2 files changed, 166 insertions(+), 3 deletions(-) diff --git a/src/hyp3_autorift/s1_correction.py b/src/hyp3_autorift/s1_correction.py index 8b8d4338..fd785566 100644 --- a/src/hyp3_autorift/s1_correction.py +++ b/src/hyp3_autorift/s1_correction.py @@ -23,8 +23,9 @@ def main(): parser.add_argument('granule', help='Reference granule to process') args = parser.parse_args() - _ = generate_correction_data(args.granule, buffer=args.buffer) + _, conversion_nc = generate_correction_data(args.granule, buffer=args.buffer) if args.bucket: + upload_file_to_s3(conversion_nc, args.bucket, args.bucket_prefix) for geotiff in Path.cwd().glob('*.tif'): upload_file_to_s3(geotiff, args.bucket, args.bucket_prefix) diff --git a/src/hyp3_autorift/s1_isce2.py b/src/hyp3_autorift/s1_isce2.py index 5127fb59..f1e0fd46 100644 --- a/src/hyp3_autorift/s1_isce2.py +++ b/src/hyp3_autorift/s1_isce2.py @@ -1,15 +1,17 @@ import copy +import json import logging import os import sys import textwrap -from datetime import timedelta +from datetime import datetime, timedelta from pathlib import Path import numpy as np from hyp3lib.fetch import download_file from hyp3lib.get_orb import downloadSentinelOrbitFile from hyp3lib.scene import get_download_url +from netCDF4 import Dataset from osgeo import gdal from hyp3_autorift import geometry, utils @@ -88,6 +90,164 @@ def process_sentinel1_with_isce2(reference, secondary, parameter_file): return netcdf_file +def write_conversion_file(*, file_name, srs, epsg, tran, x, y, M11, M12, dr_2_vr_factor, ChunkSize, + NoDataValue=-32767) -> Path: + + # FIXME: what else needs to be added to the nextCDF file + nc_outfile = Dataset(file_name, 'w', clobber=True, format='NETCDF4') + + nc_outfile.setncattr('GDAL_AREA_OR_POINT', 'Area') + nc_outfile.setncattr('Conventions', 'CF-1.8') + nc_outfile.setncattr('date_created', datetime.now().strftime("%d-%b-%Y %H:%M:%S")) + nc_outfile.setncattr('title', 'autoRIFT S1 Corrections') + # nc_outfile.setncattr('autoRIFT_software_version', 'FIXME') + # nc_outfile.setncattr('autoRIFT_parameter_file', 'FIXME') + + nc_outfile.createDimension('x', len(x)) + nc_outfile.createDimension('y', len(y)) + + var = nc_outfile.createVariable('x', np.dtype('float64'), 'x', fill_value=None) + var.setncattr('standard_name', 'projection_x_coordinate') + var.setncattr('description', 'x coordinate of projection') + var.setncattr('units', 'm') + var[:] = x + + var = nc_outfile.createVariable('y', np.dtype('float64'), 'y', fill_value=None) + var.setncattr('standard_name', 'projection_y_coordinate') + var.setncattr('description', 'y coordinate of projection') + var.setncattr('units', 'm') + var[:] = y + + mapping_var_name = 'mapping' + var = nc_outfile.createVariable(mapping_var_name, 'U1', (), fill_value=None) + if srs.GetAttrValue('PROJECTION') == 'Polar_Stereographic': + var.setncattr('grid_mapping_name', 'polar_stereographic') + var.setncattr('straight_vertical_longitude_from_pole', srs.GetProjParm('central_meridian')) + var.setncattr('false_easting', srs.GetProjParm('false_easting')) + var.setncattr('false_northing', srs.GetProjParm('false_northing')) + var.setncattr('latitude_of_projection_origin', np.sign(srs.GetProjParm('latitude_of_origin')) * 90.0) + var.setncattr('latitude_of_origin', srs.GetProjParm('latitude_of_origin')) + var.setncattr('semi_major_axis', float(srs.GetAttrValue('GEOGCS|SPHEROID', 1))) + var.setncattr('scale_factor_at_projection_origin', 1) + var.setncattr('inverse_flattening', float(srs.GetAttrValue('GEOGCS|SPHEROID', 2))) + var.setncattr('spatial_ref', srs.ExportToWkt()) + var.setncattr('crs_wkt', srs.ExportToWkt()) + var.setncattr('proj4text', srs.ExportToProj4()) + var.setncattr('spatial_epsg', epsg) + var.setncattr('GeoTransform', ' '.join(str(x) for x in tran)) + + elif srs.GetAttrValue('PROJECTION') == 'Transverse_Mercator': + var.setncattr('grid_mapping_name', 'universal_transverse_mercator') + zone = epsg - np.floor(epsg / 100) * 100 + var.setncattr('utm_zone_number', zone) + var.setncattr('longitude_of_central_meridian', srs.GetProjParm('central_meridian')) + var.setncattr('false_easting', srs.GetProjParm('false_easting')) + var.setncattr('false_northing', srs.GetProjParm('false_northing')) + var.setncattr('latitude_of_projection_origin', srs.GetProjParm('latitude_of_origin')) + var.setncattr('semi_major_axis', float(srs.GetAttrValue('GEOGCS|SPHEROID', 1))) + var.setncattr('scale_factor_at_central_meridian', srs.GetProjParm('scale_factor')) + var.setncattr('inverse_flattening', float(srs.GetAttrValue('GEOGCS|SPHEROID', 2))) + var.setncattr('spatial_ref', srs.ExportToWkt()) + var.setncattr('crs_wkt', srs.ExportToWkt()) + var.setncattr('proj4text', srs.ExportToProj4()) + var.setncattr('spatial_epsg', epsg) + var.setncattr('GeoTransform', ' '.join(str(x) for x in tran)) + else: + raise Exception('Projection {0} not recognized for this program'.format(srs.GetAttrValue('PROJECTION'))) + + var = nc_outfile.createVariable('M11', np.dtype('float32'), ('y', 'x'), fill_value=NoDataValue, + zlib=True, complevel=2, shuffle=True, chunksizes=ChunkSize) + var.setncattr('standard_name', 'conversion_matrix_element_11') + var.setncattr( + 'description', + 'conversion matrix element (1st row, 1st column) that can be multiplied with vx to give range pixel ' + 'displacement dr (see Eq. A18 in https://www.mdpi.com/2072-4292/13/4/749)' + ) + var.setncattr('units', 'pixel/(meter/year)') + var.setncattr('grid_mapping', mapping_var_name) + var.setncattr('dr_to_vr_factor', dr_2_vr_factor) + var.setncattr('dr_to_vr_factor_description', 'multiplicative factor that converts slant range ' + 'pixel displacement dr to slant range velocity vr') + var[:] = M11 + + var = nc_outfile.createVariable('M12', np.dtype('float32'), ('y', 'x'), fill_value=NoDataValue, + zlib=True, complevel=2, shuffle=True, chunksizes=ChunkSize) + var.setncattr('standard_name', 'conversion_matrix_element_12') + var.setncattr( + 'description', + 'conversion matrix element (1st row, 2nd column) that can be multiplied with vy to give range pixel ' + 'displacement dr (see Eq. A18 in https://www.mdpi.com/2072-4292/13/4/749)' + ) + var.setncattr('units', 'pixel/(meter/year)') + var.setncattr('grid_mapping', mapping_var_name) + var.setncattr('dr_to_vr_factor', dr_2_vr_factor) + var.setncattr('dr_to_vr_factor_description', + 'multiplicative factor that converts slant range pixel displacement dr to slant range velocity vr') + var[:] = M12 + + return Path(nc_outfile.filepath()) + + +def create_conversion_matrices( + *, + scene: str, + grid_location: str = 'window_location.tif', + search_range: str = 'window_search_range.tif', + offset2vx: str = 'window_rdr_off2vel_x_vec.tif', + offset2vy: str = 'window_rdr_off2vel_y_vec.tif', + scale_factor: str = 'window_scale_factor.tif', + epsg: int = 4326, + **kwargs, # noqa: consume kwargs we don't care about for convenience +) -> Path: + xGrid, tran, _, srs, nodata = utils.load_geospatial(grid_location, band=1) + yGrid, _, _, _, _ = utils.load_geospatial(grid_location, band=2) + + offset2vy_1, _, _, _, _ = utils.load_geospatial(offset2vy, band=1) + offset2vy_1[offset2vy_1 == nodata] = np.nan + + offset2vy_2, _, _, _, _ = utils.load_geospatial(offset2vy, band=2) + offset2vy_2[offset2vy_2 == nodata] = np.nan + + offset2vx_1, _, _, _, _ = utils.load_geospatial(offset2vx, band=1) + offset2vx_1[offset2vx_1 == nodata] = np.nan + + offset2vx_2, _, _, _, _ = utils.load_geospatial(offset2vx, band=2) + offset2vx_2[offset2vx_2 == nodata] = np.nan + + offset2vr, _, _, _, _ = utils.load_geospatial(offset2vx, band=3) + offset2vr[offset2vr == nodata] = np.nan + + scale_factor_1, _, _, _, _ = utils.load_geospatial(scale_factor, band=1) + scale_factor_1[scale_factor_1 == nodata] = np.nan + + scale_factor_2, _, _, _, _ = utils.load_geospatial(scale_factor, band=2) + scale_factor_2[scale_factor_2 == nodata] = np.nan + + SRx0, _, _, _, _ = utils.load_geospatial(search_range, band=1) + SRx0 = SRx0.astype('float32') + SRx0[SRx0 == nodata] = np.nan + + dimidY, dimidX = xGrid.shape + + y = np.arange(tran[3], tran[3] + tran[5] * dimidY, tran[5]) + x = np.arange(tran[0], tran[0] + tran[1] * dimidX, tran[1]) + + M11 = offset2vy_2 / (offset2vx_1 * offset2vy_2 - offset2vx_2 * offset2vy_1) / scale_factor_1 + M12 = -offset2vx_2 / (offset2vx_1 * offset2vy_2 - offset2vx_2 * offset2vy_1) / scale_factor_1 + + dr_2_vr_factor = np.median(offset2vr[np.logical_not(np.isnan(offset2vr))]) + + chunk_lines = np.min([np.ceil(8192 / dimidY) * 128, dimidY]) + ChunkSize = [chunk_lines, dimidX] + + conversion_nc = write_conversion_file( + file_name=f'{scene}_conversion_matrices.nc', srs=srs, epsg=epsg, tran=tran, x=x, y=y, M11=M11, M12=M12, + dr_2_vr_factor=dr_2_vr_factor, ChunkSize=ChunkSize + ) + + return conversion_nc + + def generate_correction_data( scene: str, buffer: int = 0, @@ -127,7 +287,9 @@ def generate_correction_data( geogrid_info = runGeogrid(reference_meta, secondary_meta, epsg=parameter_info['epsg'], **parameter_info['geogrid']) - return geogrid_info + conversion_nc = create_conversion_matrices(scene=scene, epsg=parameter_info['epsg'], **parameter_info['autorift']) + + return geogrid_info, conversion_nc class SysArgvManager: From 06e4d8370d973bbc8b4c38f0c6e1689860e6ad0d Mon Sep 17 00:00:00 2001 From: Joseph H Kennedy Date: Tue, 18 Jun 2024 14:04:47 -0800 Subject: [PATCH 06/23] tweaks --- src/hyp3_autorift/s1_isce2.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/hyp3_autorift/s1_isce2.py b/src/hyp3_autorift/s1_isce2.py index f1e0fd46..cc6f3f1f 100644 --- a/src/hyp3_autorift/s1_isce2.py +++ b/src/hyp3_autorift/s1_isce2.py @@ -1,5 +1,4 @@ import copy -import json import logging import os import sys @@ -90,8 +89,8 @@ def process_sentinel1_with_isce2(reference, secondary, parameter_file): return netcdf_file -def write_conversion_file(*, file_name, srs, epsg, tran, x, y, M11, M12, dr_2_vr_factor, ChunkSize, - NoDataValue=-32767) -> Path: +def write_conversion_file(*, file_name: str, srs, epsg, tran, x, y, M11, M12, dr_2_vr_factor, ChunkSize, + NoDataValue=-32767) -> str: # FIXME: what else needs to be added to the nextCDF file nc_outfile = Dataset(file_name, 'w', clobber=True, format='NETCDF4') @@ -185,7 +184,7 @@ def write_conversion_file(*, file_name, srs, epsg, tran, x, y, M11, M12, dr_2_vr 'multiplicative factor that converts slant range pixel displacement dr to slant range velocity vr') var[:] = M12 - return Path(nc_outfile.filepath()) + return file_name def create_conversion_matrices( @@ -198,7 +197,7 @@ def create_conversion_matrices( scale_factor: str = 'window_scale_factor.tif', epsg: int = 4326, **kwargs, # noqa: consume kwargs we don't care about for convenience -) -> Path: +) -> str: xGrid, tran, _, srs, nodata = utils.load_geospatial(grid_location, band=1) yGrid, _, _, _, _ = utils.load_geospatial(grid_location, band=2) @@ -252,7 +251,7 @@ def generate_correction_data( scene: str, buffer: int = 0, parameter_file: str = DEFAULT_PARAMETER_FILE, -): +) -> (dict, str): from hyp3_autorift.vend.testGeogrid_ISCE import loadParsedata, runGeogrid scene_path = Path(f'{scene}.zip') if not scene_path.exists(): From 7d2dcbfd40421404f82988e50a5860cd8de624f0 Mon Sep 17 00:00:00 2001 From: Joseph H Kennedy Date: Tue, 18 Jun 2024 14:07:11 -0800 Subject: [PATCH 07/23] Add changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c60d4c4..07a7fb62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ 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.18.0] +### Added +* The Sentinel-1 correction workflow will now calculate and write the M11/M12 conversion matrices to a netCDF file. + ## [0.17.0] ## Changed * In preparation for a major update, the Sentinel-1 processing workflow has been isolated to a new `hyp3_autorift.s1_isce2` module. From 97ba71edd19069a62656ba8459278fd5f4688cec Mon Sep 17 00:00:00 2001 From: Joseph H Kennedy Date: Tue, 18 Jun 2024 16:06:21 -0800 Subject: [PATCH 08/23] Register all gdal drivers b/c Geogrid :rolling_eyes: --- src/hyp3_autorift/s1_isce2.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hyp3_autorift/s1_isce2.py b/src/hyp3_autorift/s1_isce2.py index cc6f3f1f..5e486a62 100644 --- a/src/hyp3_autorift/s1_isce2.py +++ b/src/hyp3_autorift/s1_isce2.py @@ -286,6 +286,10 @@ def generate_correction_data( geogrid_info = runGeogrid(reference_meta, secondary_meta, epsg=parameter_info['epsg'], **parameter_info['geogrid']) + # NOTE: After Geogrid is run, all drivers are no longer registered. + # I've got no idea why, or if there are other affects... + gdal.AllRegister() + conversion_nc = create_conversion_matrices(scene=scene, epsg=parameter_info['epsg'], **parameter_info['autorift']) return geogrid_info, conversion_nc From c25fb8a20c8637a7403fc5eebeb352c05e0d6e7e Mon Sep 17 00:00:00 2001 From: Joseph H Kennedy Date: Wed, 19 Jun 2024 11:36:05 -0800 Subject: [PATCH 09/23] Apply suggestions from code review Co-authored-by: Jake Herrmann --- CHANGELOG.md | 2 +- src/hyp3_autorift/s1_isce2.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07a7fb62..de56d257 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ 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.18.0] +## [0.18.0] ### Added * The Sentinel-1 correction workflow will now calculate and write the M11/M12 conversion matrices to a netCDF file. diff --git a/src/hyp3_autorift/s1_isce2.py b/src/hyp3_autorift/s1_isce2.py index 5e486a62..343cb3e0 100644 --- a/src/hyp3_autorift/s1_isce2.py +++ b/src/hyp3_autorift/s1_isce2.py @@ -92,7 +92,7 @@ def process_sentinel1_with_isce2(reference, secondary, parameter_file): def write_conversion_file(*, file_name: str, srs, epsg, tran, x, y, M11, M12, dr_2_vr_factor, ChunkSize, NoDataValue=-32767) -> str: - # FIXME: what else needs to be added to the nextCDF file + # FIXME: what else needs to be added to the netCDF file nc_outfile = Dataset(file_name, 'w', clobber=True, format='NETCDF4') nc_outfile.setncattr('GDAL_AREA_OR_POINT', 'Area') From c43310f06eefa05a383684d1b9499bddfece4eeb Mon Sep 17 00:00:00 2001 From: Joseph H Kennedy Date: Wed, 19 Jun 2024 13:59:03 -0800 Subject: [PATCH 10/23] add missing netcdf attributes and use correct nan for floats --- src/hyp3_autorift/s1_isce2.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/hyp3_autorift/s1_isce2.py b/src/hyp3_autorift/s1_isce2.py index 343cb3e0..d673f602 100644 --- a/src/hyp3_autorift/s1_isce2.py +++ b/src/hyp3_autorift/s1_isce2.py @@ -7,6 +7,7 @@ from pathlib import Path import numpy as np +from autoRIFT import __version__ as version from hyp3lib.fetch import download_file from hyp3lib.get_orb import downloadSentinelOrbitFile from hyp3lib.scene import get_download_url @@ -90,7 +91,7 @@ def process_sentinel1_with_isce2(reference, secondary, parameter_file): def write_conversion_file(*, file_name: str, srs, epsg, tran, x, y, M11, M12, dr_2_vr_factor, ChunkSize, - NoDataValue=-32767) -> str: + NoDataValue=np.nan, parameter_file: str) -> str: # FIXME: what else needs to be added to the netCDF file nc_outfile = Dataset(file_name, 'w', clobber=True, format='NETCDF4') @@ -99,8 +100,8 @@ def write_conversion_file(*, file_name: str, srs, epsg, tran, x, y, M11, M12, dr nc_outfile.setncattr('Conventions', 'CF-1.8') nc_outfile.setncattr('date_created', datetime.now().strftime("%d-%b-%Y %H:%M:%S")) nc_outfile.setncattr('title', 'autoRIFT S1 Corrections') - # nc_outfile.setncattr('autoRIFT_software_version', 'FIXME') - # nc_outfile.setncattr('autoRIFT_parameter_file', 'FIXME') + nc_outfile.setncattr('autoRIFT_software_version', version) + nc_outfile.setncattr('autoRIFT_parameter_file', parameter_file) nc_outfile.createDimension('x', len(x)) nc_outfile.createDimension('y', len(y)) @@ -196,6 +197,7 @@ def create_conversion_matrices( offset2vy: str = 'window_rdr_off2vel_y_vec.tif', scale_factor: str = 'window_scale_factor.tif', epsg: int = 4326, + parameter_file: str = DEFAULT_PARAMETER_FILE, **kwargs, # noqa: consume kwargs we don't care about for convenience ) -> str: xGrid, tran, _, srs, nodata = utils.load_geospatial(grid_location, band=1) @@ -241,7 +243,7 @@ def create_conversion_matrices( conversion_nc = write_conversion_file( file_name=f'{scene}_conversion_matrices.nc', srs=srs, epsg=epsg, tran=tran, x=x, y=y, M11=M11, M12=M12, - dr_2_vr_factor=dr_2_vr_factor, ChunkSize=ChunkSize + dr_2_vr_factor=dr_2_vr_factor, ChunkSize=ChunkSize, parameter_file=parameter_file, ) return conversion_nc @@ -290,7 +292,9 @@ def generate_correction_data( # I've got no idea why, or if there are other affects... gdal.AllRegister() - conversion_nc = create_conversion_matrices(scene=scene, epsg=parameter_info['epsg'], **parameter_info['autorift']) + conversion_nc = create_conversion_matrices( + scene=scene, epsg=parameter_info['epsg'], parameter_file=parameter_file, **parameter_info['autorift'] + ) return geogrid_info, conversion_nc From 4aaa993b372030c5fe5106783d82a147af70c0bd Mon Sep 17 00:00:00 2001 From: Joseph H Kennedy Date: Wed, 19 Jun 2024 14:00:29 -0800 Subject: [PATCH 11/23] drop fixme --- src/hyp3_autorift/s1_isce2.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hyp3_autorift/s1_isce2.py b/src/hyp3_autorift/s1_isce2.py index d673f602..c6416b3c 100644 --- a/src/hyp3_autorift/s1_isce2.py +++ b/src/hyp3_autorift/s1_isce2.py @@ -93,7 +93,6 @@ def process_sentinel1_with_isce2(reference, secondary, parameter_file): def write_conversion_file(*, file_name: str, srs, epsg, tran, x, y, M11, M12, dr_2_vr_factor, ChunkSize, NoDataValue=np.nan, parameter_file: str) -> str: - # FIXME: what else needs to be added to the netCDF file nc_outfile = Dataset(file_name, 'w', clobber=True, format='NETCDF4') nc_outfile.setncattr('GDAL_AREA_OR_POINT', 'Area') From 407efc9584983375d9c15c0557cb5f0987c6a3b8 Mon Sep 17 00:00:00 2001 From: Joseph H Kennedy Date: Wed, 19 Jun 2024 14:19:17 -0800 Subject: [PATCH 12/23] just use float64 everywhere; add type hints --- src/hyp3_autorift/s1_isce2.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/hyp3_autorift/s1_isce2.py b/src/hyp3_autorift/s1_isce2.py index c6416b3c..d4fc0f50 100644 --- a/src/hyp3_autorift/s1_isce2.py +++ b/src/hyp3_autorift/s1_isce2.py @@ -3,6 +3,7 @@ import os import sys import textwrap +from typing import List from datetime import datetime, timedelta from pathlib import Path @@ -12,7 +13,7 @@ from hyp3lib.get_orb import downloadSentinelOrbitFile from hyp3lib.scene import get_download_url from netCDF4 import Dataset -from osgeo import gdal +from osgeo import gdal, osr from hyp3_autorift import geometry, utils from hyp3_autorift.process import DEFAULT_PARAMETER_FILE @@ -90,8 +91,21 @@ def process_sentinel1_with_isce2(reference, secondary, parameter_file): return netcdf_file -def write_conversion_file(*, file_name: str, srs, epsg, tran, x, y, M11, M12, dr_2_vr_factor, ChunkSize, - NoDataValue=np.nan, parameter_file: str) -> str: +def write_conversion_file( + *, + file_name: str, + srs: osr.SpatialReference, + epsg: int, + tran: List[float], + x: np.ndarray, + y: np.ndarray, + M11: np.ndarray, + M12: np.ndarray, + dr_2_vr_factor: float, + ChunkSize: List[int], + NoDataValue=np.nan, + parameter_file: str +) -> str: nc_outfile = Dataset(file_name, 'w', clobber=True, format='NETCDF4') @@ -154,7 +168,7 @@ def write_conversion_file(*, file_name: str, srs, epsg, tran, x, y, M11, M12, dr else: raise Exception('Projection {0} not recognized for this program'.format(srs.GetAttrValue('PROJECTION'))) - var = nc_outfile.createVariable('M11', np.dtype('float32'), ('y', 'x'), fill_value=NoDataValue, + var = nc_outfile.createVariable('M11', np.dtype('float64'), ('y', 'x'), fill_value=NoDataValue, zlib=True, complevel=2, shuffle=True, chunksizes=ChunkSize) var.setncattr('standard_name', 'conversion_matrix_element_11') var.setncattr( @@ -169,7 +183,7 @@ def write_conversion_file(*, file_name: str, srs, epsg, tran, x, y, M11, M12, dr 'pixel displacement dr to slant range velocity vr') var[:] = M11 - var = nc_outfile.createVariable('M12', np.dtype('float32'), ('y', 'x'), fill_value=NoDataValue, + var = nc_outfile.createVariable('M12', np.dtype('float64'), ('y', 'x'), fill_value=NoDataValue, zlib=True, complevel=2, shuffle=True, chunksizes=ChunkSize) var.setncattr('standard_name', 'conversion_matrix_element_12') var.setncattr( @@ -224,7 +238,7 @@ def create_conversion_matrices( scale_factor_2[scale_factor_2 == nodata] = np.nan SRx0, _, _, _, _ = utils.load_geospatial(search_range, band=1) - SRx0 = SRx0.astype('float32') + SRx0 = SRx0.astype('float64') SRx0[SRx0 == nodata] = np.nan dimidY, dimidX = xGrid.shape From 2aa993d22746ee8d48764452423b8844e6c9808b Mon Sep 17 00:00:00 2001 From: Joseph H Kennedy Date: Wed, 19 Jun 2024 14:22:08 -0800 Subject: [PATCH 13/23] Apply suggestions from code review Co-authored-by: Jake Herrmann --- src/hyp3_autorift/s1_isce2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hyp3_autorift/s1_isce2.py b/src/hyp3_autorift/s1_isce2.py index d4fc0f50..20252846 100644 --- a/src/hyp3_autorift/s1_isce2.py +++ b/src/hyp3_autorift/s1_isce2.py @@ -166,7 +166,7 @@ def write_conversion_file( var.setncattr('spatial_epsg', epsg) var.setncattr('GeoTransform', ' '.join(str(x) for x in tran)) else: - raise Exception('Projection {0} not recognized for this program'.format(srs.GetAttrValue('PROJECTION'))) + raise Exception(f'Projection {srs.GetAttrValue('PROJECTION')} not recognized for this program') var = nc_outfile.createVariable('M11', np.dtype('float64'), ('y', 'x'), fill_value=NoDataValue, zlib=True, complevel=2, shuffle=True, chunksizes=ChunkSize) @@ -211,7 +211,7 @@ def create_conversion_matrices( scale_factor: str = 'window_scale_factor.tif', epsg: int = 4326, parameter_file: str = DEFAULT_PARAMETER_FILE, - **kwargs, # noqa: consume kwargs we don't care about for convenience + **kwargs, ) -> str: xGrid, tran, _, srs, nodata = utils.load_geospatial(grid_location, band=1) yGrid, _, _, _, _ = utils.load_geospatial(grid_location, band=2) @@ -302,7 +302,7 @@ def generate_correction_data( geogrid_info = runGeogrid(reference_meta, secondary_meta, epsg=parameter_info['epsg'], **parameter_info['geogrid']) # NOTE: After Geogrid is run, all drivers are no longer registered. - # I've got no idea why, or if there are other affects... + # I've got no idea why, or if there are other effects... gdal.AllRegister() conversion_nc = create_conversion_matrices( From df02c09a6234e68613453149d519cf7ebbb3e95e Mon Sep 17 00:00:00 2001 From: Joseph H Kennedy Date: Wed, 19 Jun 2024 14:24:32 -0800 Subject: [PATCH 14/23] lint --- src/hyp3_autorift/s1_isce2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hyp3_autorift/s1_isce2.py b/src/hyp3_autorift/s1_isce2.py index 20252846..23176878 100644 --- a/src/hyp3_autorift/s1_isce2.py +++ b/src/hyp3_autorift/s1_isce2.py @@ -3,8 +3,8 @@ import os import sys import textwrap -from typing import List from datetime import datetime, timedelta +from typing import List from pathlib import Path import numpy as np From 066cea7000e48b62193d8b6f3036814704937e7a Mon Sep 17 00:00:00 2001 From: Joseph H Kennedy Date: Wed, 19 Jun 2024 14:25:35 -0800 Subject: [PATCH 15/23] fix f string --- src/hyp3_autorift/s1_isce2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hyp3_autorift/s1_isce2.py b/src/hyp3_autorift/s1_isce2.py index 23176878..999b63b1 100644 --- a/src/hyp3_autorift/s1_isce2.py +++ b/src/hyp3_autorift/s1_isce2.py @@ -166,7 +166,7 @@ def write_conversion_file( var.setncattr('spatial_epsg', epsg) var.setncattr('GeoTransform', ' '.join(str(x) for x in tran)) else: - raise Exception(f'Projection {srs.GetAttrValue('PROJECTION')} not recognized for this program') + raise Exception(f'Projection {srs.GetAttrValue("PROJECTION")} not recognized for this program') var = nc_outfile.createVariable('M11', np.dtype('float64'), ('y', 'x'), fill_value=NoDataValue, zlib=True, complevel=2, shuffle=True, chunksizes=ChunkSize) From 2162174fe99781c2da7c6f547fea4d22ffefb384 Mon Sep 17 00:00:00 2001 From: Joseph H Kennedy Date: Wed, 19 Jun 2024 14:26:43 -0800 Subject: [PATCH 16/23] import order --- src/hyp3_autorift/s1_isce2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hyp3_autorift/s1_isce2.py b/src/hyp3_autorift/s1_isce2.py index 999b63b1..7895abba 100644 --- a/src/hyp3_autorift/s1_isce2.py +++ b/src/hyp3_autorift/s1_isce2.py @@ -4,8 +4,8 @@ import sys import textwrap from datetime import datetime, timedelta -from typing import List from pathlib import Path +from typing import List import numpy as np from autoRIFT import __version__ as version From 6fa18e4fb9d992974876b8a3e8e46fca1a4f031b Mon Sep 17 00:00:00 2001 From: Andrew Player Date: Wed, 26 Jun 2024 14:56:35 -0500 Subject: [PATCH 17/23] dropped support for python 3.8 --- CHANGELOG.md | 3 +++ environment.yml | 2 +- pyproject.toml | 4 +--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de56d257..9b165e26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ 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.19.0] +### Removed +* Support for Python 3.8 has been dropped. ## [0.18.0] ### Added diff --git a/environment.yml b/environment.yml index 0afab498..3fb87871 100644 --- a/environment.yml +++ b/environment.yml @@ -6,7 +6,7 @@ channels: dependencies: - boto3 - botocore - - python>=3.8,<3.10 # Top pin to fix ISCE2 incompatibility: https://github.com/isce-framework/isce2/issues/458 + - python>=3.9,<3.10 # Top pin to fix ISCE2 incompatibility: https://github.com/isce-framework/isce2/issues/458 - pip # For packaging, and testing - build diff --git a/pyproject.toml b/pyproject.toml index 2032aa16..878d283b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "hyp3_autorift" -requires-python = ">=3.8" +requires-python = ">=3.9" authors = [ {name="ASF APD/Tools Team", email="uaf-asf-apd@alaska.edu"}, ] @@ -17,9 +17,7 @@ classifiers=[ "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", ] dependencies = [ 'boto3', From 98abf66e29248968d97392b5c72d8a45a6c4dbee Mon Sep 17 00:00:00 2001 From: Jake Herrmann Date: Thu, 27 Jun 2024 10:03:52 -0800 Subject: [PATCH 18/23] Update CHANGELOG.md --- CHANGELOG.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b165e26..23a65519 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,13 +6,11 @@ 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.19.0] -### Removed -* Support for Python 3.8 has been dropped. - ## [0.18.0] ### Added * The Sentinel-1 correction workflow will now calculate and write the M11/M12 conversion matrices to a netCDF file. +### Removed +* Support for Python 3.8 has been dropped. ## [0.17.0] ## Changed From 0dec0d79ecfc28ed2683f5446ff764efde3ec459 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 16:49:05 +0000 Subject: [PATCH 19/23] Bump ASFHyP3/actions from 0.11.1 to 0.11.2 Bumps [ASFHyP3/actions](https://github.com/asfhyp3/actions) from 0.11.1 to 0.11.2. - [Release notes](https://github.com/asfhyp3/actions/releases) - [Changelog](https://github.com/ASFHyP3/actions/blob/develop/CHANGELOG.md) - [Commits](https://github.com/asfhyp3/actions/compare/v0.11.1...v0.11.2) --- updated-dependencies: - dependency-name: ASFHyP3/actions dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/changelog.yml | 2 +- .github/workflows/create-jira-issue.yml | 2 +- .github/workflows/labeled-pr.yml | 2 +- .github/workflows/release-template-comment.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/static-analysis.yml | 4 ++-- .github/workflows/tag-version.yml | 2 +- .github/workflows/test-and-build.yml | 6 +++--- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 6047ddb1..7740de9e 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -13,4 +13,4 @@ on: jobs: call-changelog-check-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-changelog-check.yml@v0.11.1 + uses: ASFHyP3/actions/.github/workflows/reusable-changelog-check.yml@v0.11.2 diff --git a/.github/workflows/create-jira-issue.yml b/.github/workflows/create-jira-issue.yml index 129ff5f1..99489d50 100644 --- a/.github/workflows/create-jira-issue.yml +++ b/.github/workflows/create-jira-issue.yml @@ -6,7 +6,7 @@ on: jobs: call-create-jira-issue-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-create-jira-issue.yml@v0.11.1 + uses: ASFHyP3/actions/.github/workflows/reusable-create-jira-issue.yml@v0.11.2 secrets: JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} diff --git a/.github/workflows/labeled-pr.yml b/.github/workflows/labeled-pr.yml index 3ba21604..f89f3e3b 100644 --- a/.github/workflows/labeled-pr.yml +++ b/.github/workflows/labeled-pr.yml @@ -12,4 +12,4 @@ on: jobs: call-labeled-pr-check-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-labeled-pr-check.yml@v0.11.1 + uses: ASFHyP3/actions/.github/workflows/reusable-labeled-pr-check.yml@v0.11.2 diff --git a/.github/workflows/release-template-comment.yml b/.github/workflows/release-template-comment.yml index 01d20589..dd3650ce 100644 --- a/.github/workflows/release-template-comment.yml +++ b/.github/workflows/release-template-comment.yml @@ -7,6 +7,6 @@ on: jobs: call-release-checklist-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-release-checklist-comment.yml@v0.11.1 + uses: ASFHyP3/actions/.github/workflows/reusable-release-checklist-comment.yml@v0.11.2 secrets: USER_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f04a3669..784648ef 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,7 +7,7 @@ on: jobs: call-release-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-release.yml@v0.11.1 + uses: ASFHyP3/actions/.github/workflows/reusable-release.yml@v0.11.2 with: release_prefix: HyP3 autoRIFT secrets: diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 6e006ab8..c7f96d1e 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -4,10 +4,10 @@ on: push jobs: call-flake8-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-flake8.yml@v0.11.1 + uses: ASFHyP3/actions/.github/workflows/reusable-flake8.yml@v0.11.2 with: local_package_names: hyp3_autorift excludes: src/hyp3_autorift/vend call-secrets-analysis-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-secrets-analysis.yml@v0.11.1 + uses: ASFHyP3/actions/.github/workflows/reusable-secrets-analysis.yml@v0.11.2 diff --git a/.github/workflows/tag-version.yml b/.github/workflows/tag-version.yml index 7bc79246..3b94479b 100644 --- a/.github/workflows/tag-version.yml +++ b/.github/workflows/tag-version.yml @@ -7,6 +7,6 @@ on: jobs: call-bump-version-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-bump-version.yml@v0.11.1 + uses: ASFHyP3/actions/.github/workflows/reusable-bump-version.yml@v0.11.2 secrets: USER_TOKEN: ${{ secrets.TOOLS_BOT_PAK }} diff --git a/.github/workflows/test-and-build.yml b/.github/workflows/test-and-build.yml index cfc16752..984878d6 100644 --- a/.github/workflows/test-and-build.yml +++ b/.github/workflows/test-and-build.yml @@ -12,18 +12,18 @@ on: jobs: call-pytest-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-pytest.yml@v0.11.1 + uses: ASFHyP3/actions/.github/workflows/reusable-pytest.yml@v0.11.2 with: local_package_name: hyp3_autorift python_versions: >- ["3.9"] call-version-info-workflow: - uses: ASFHyP3/actions/.github/workflows/reusable-version-info.yml@v0.11.1 + uses: ASFHyP3/actions/.github/workflows/reusable-version-info.yml@v0.11.2 call-docker-ghcr-workflow: needs: call-version-info-workflow - uses: ASFHyP3/actions/.github/workflows/reusable-docker-ghcr.yml@v0.11.1 + uses: ASFHyP3/actions/.github/workflows/reusable-docker-ghcr.yml@v0.11.2 with: version_tag: ${{ needs.call-version-info-workflow.outputs.version_tag }} secrets: From 52c2b84a4918315e8087e8e122da2d6256d58c4f Mon Sep 17 00:00:00 2001 From: Jake Herrmann Date: Mon, 1 Jul 2024 10:39:05 -0800 Subject: [PATCH 20/23] Update .github/workflows/test-and-build.yml --- .github/workflows/test-and-build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test-and-build.yml b/.github/workflows/test-and-build.yml index 984878d6..f23e4baf 100644 --- a/.github/workflows/test-and-build.yml +++ b/.github/workflows/test-and-build.yml @@ -20,6 +20,8 @@ jobs: call-version-info-workflow: uses: ASFHyP3/actions/.github/workflows/reusable-version-info.yml@v0.11.2 + with: + python_version: '3.9' call-docker-ghcr-workflow: needs: call-version-info-workflow From abea71933aacad91f5270fa0130a1476f75fd31d Mon Sep 17 00:00:00 2001 From: Joseph H Kennedy Date: Tue, 2 Jul 2024 20:18:04 -0800 Subject: [PATCH 21/23] switch to writing ints; drop unused --- src/hyp3_autorift/s1_isce2.py | 47 +++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/src/hyp3_autorift/s1_isce2.py b/src/hyp3_autorift/s1_isce2.py index 7895abba..58c873ac 100644 --- a/src/hyp3_autorift/s1_isce2.py +++ b/src/hyp3_autorift/s1_isce2.py @@ -103,7 +103,8 @@ def write_conversion_file( M12: np.ndarray, dr_2_vr_factor: float, ChunkSize: List[int], - NoDataValue=np.nan, + NoDataValue: int = -32767, + noDataMask: np.ndarray, parameter_file: str ) -> str: @@ -168,7 +169,7 @@ def write_conversion_file( else: raise Exception(f'Projection {srs.GetAttrValue("PROJECTION")} not recognized for this program') - var = nc_outfile.createVariable('M11', np.dtype('float64'), ('y', 'x'), fill_value=NoDataValue, + var = nc_outfile.createVariable('M11', np.dtype('int16'), ('y', 'x'), fill_value=NoDataValue, zlib=True, complevel=2, shuffle=True, chunksizes=ChunkSize) var.setncattr('standard_name', 'conversion_matrix_element_11') var.setncattr( @@ -181,9 +182,20 @@ def write_conversion_file( var.setncattr('dr_to_vr_factor', dr_2_vr_factor) var.setncattr('dr_to_vr_factor_description', 'multiplicative factor that converts slant range ' 'pixel displacement dr to slant range velocity vr') + + x1 = np.nanmin(M11[:]) + x2 = np.nanmax(M11[:]) + y1 = -50 + y2 = 50 + + C = [(y2 - y1) / (x2 - x1), y1 - x1 * (y2 - y1) / (x2 - x1)] + var.setncattr('scale_factor', np.float32(1 / C[0])) + var.setncattr('add_offset', np.float32(-C[1] / C[0])) + + M11[noDataMask] = NoDataValue * np.float32(1 / C[0]) + np.float32(-C[1] / C[0]) var[:] = M11 - var = nc_outfile.createVariable('M12', np.dtype('float64'), ('y', 'x'), fill_value=NoDataValue, + var = nc_outfile.createVariable('M12', np.dtype('int16'), ('y', 'x'), fill_value=NoDataValue, zlib=True, complevel=2, shuffle=True, chunksizes=ChunkSize) var.setncattr('standard_name', 'conversion_matrix_element_12') var.setncattr( @@ -196,6 +208,17 @@ def write_conversion_file( var.setncattr('dr_to_vr_factor', dr_2_vr_factor) var.setncattr('dr_to_vr_factor_description', 'multiplicative factor that converts slant range pixel displacement dr to slant range velocity vr') + + x1 = np.nanmin(M12[:]) + x2 = np.nanmax(M12[:]) + y1 = -50 + y2 = 50 + + C = [(y2 - y1) / (x2 - x1), y1 - x1 * (y2 - y1) / (x2 - x1)] + var.setncattr('scale_factor', np.float32(1 / C[0])) + var.setncattr('add_offset', np.float32(-C[1] / C[0])) + + M12[noDataMask] = NoDataValue * np.float32(1 / C[0]) + np.float32(-C[1] / C[0]) var[:] = M12 return file_name @@ -205,7 +228,6 @@ def create_conversion_matrices( *, scene: str, grid_location: str = 'window_location.tif', - search_range: str = 'window_search_range.tif', offset2vx: str = 'window_rdr_off2vel_x_vec.tif', offset2vy: str = 'window_rdr_off2vel_y_vec.tif', scale_factor: str = 'window_scale_factor.tif', @@ -214,7 +236,6 @@ def create_conversion_matrices( **kwargs, ) -> str: xGrid, tran, _, srs, nodata = utils.load_geospatial(grid_location, band=1) - yGrid, _, _, _, _ = utils.load_geospatial(grid_location, band=2) offset2vy_1, _, _, _, _ = utils.load_geospatial(offset2vy, band=1) offset2vy_1[offset2vy_1 == nodata] = np.nan @@ -234,29 +255,23 @@ def create_conversion_matrices( scale_factor_1, _, _, _, _ = utils.load_geospatial(scale_factor, band=1) scale_factor_1[scale_factor_1 == nodata] = np.nan - scale_factor_2, _, _, _, _ = utils.load_geospatial(scale_factor, band=2) - scale_factor_2[scale_factor_2 == nodata] = np.nan - - SRx0, _, _, _, _ = utils.load_geospatial(search_range, band=1) - SRx0 = SRx0.astype('float64') - SRx0[SRx0 == nodata] = np.nan - dimidY, dimidX = xGrid.shape + noDataMask = xGrid == nodata y = np.arange(tran[3], tran[3] + tran[5] * dimidY, tran[5]) x = np.arange(tran[0], tran[0] + tran[1] * dimidX, tran[1]) + chunk_lines = np.min([np.ceil(8192 / dimidY) * 128, dimidY]) + ChunkSize = [chunk_lines, dimidX] + M11 = offset2vy_2 / (offset2vx_1 * offset2vy_2 - offset2vx_2 * offset2vy_1) / scale_factor_1 M12 = -offset2vx_2 / (offset2vx_1 * offset2vy_2 - offset2vx_2 * offset2vy_1) / scale_factor_1 dr_2_vr_factor = np.median(offset2vr[np.logical_not(np.isnan(offset2vr))]) - chunk_lines = np.min([np.ceil(8192 / dimidY) * 128, dimidY]) - ChunkSize = [chunk_lines, dimidX] - conversion_nc = write_conversion_file( file_name=f'{scene}_conversion_matrices.nc', srs=srs, epsg=epsg, tran=tran, x=x, y=y, M11=M11, M12=M12, - dr_2_vr_factor=dr_2_vr_factor, ChunkSize=ChunkSize, parameter_file=parameter_file, + dr_2_vr_factor=dr_2_vr_factor, ChunkSize=ChunkSize, noDataMask=noDataMask, parameter_file=parameter_file, ) return conversion_nc From 0670524bccf82e515392d3b317a02e0510243b31 Mon Sep 17 00:00:00 2001 From: Joseph H Kennedy Date: Tue, 2 Jul 2024 22:12:57 -0800 Subject: [PATCH 22/23] Ensure are encoding attributes are carried over when cropping --- src/hyp3_autorift/crop.py | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/src/hyp3_autorift/crop.py b/src/hyp3_autorift/crop.py index 4e14ab6a..58a725dc 100644 --- a/src/hyp3_autorift/crop.py +++ b/src/hyp3_autorift/crop.py @@ -36,22 +36,7 @@ import pyproj import xarray as xr - -ENCODING_TEMPLATE = { - 'interp_mask': {'_FillValue': 0.0, 'dtype': 'ubyte', "zlib": True, "complevel": 2, "shuffle": True}, - 'chip_size_height': {'_FillValue': 0.0, 'dtype': 'ushort', "zlib": True, "complevel": 2, "shuffle": True}, - 'chip_size_width': {'_FillValue': 0.0, 'dtype': 'ushort', "zlib": True, "complevel": 2, "shuffle": True}, - 'M11': {'_FillValue': -32767, 'dtype': 'short', "zlib": True, "complevel": 2, "shuffle": True}, - 'M12': {'_FillValue': -32767, 'dtype': 'short', "zlib": True, "complevel": 2, "shuffle": True}, - 'v': {'_FillValue': -32767.0, 'dtype': 'short', "zlib": True, "complevel": 2, "shuffle": True}, - 'vx': {'_FillValue': -32767.0, 'dtype': 'short', "zlib": True, "complevel": 2, "shuffle": True}, - 'vy': {'_FillValue': -32767.0, 'dtype': 'short', "zlib": True, "complevel": 2, "shuffle": True}, - 'v_error': {'_FillValue': -32767.0, 'dtype': 'short', "zlib": True, "complevel": 2, "shuffle": True}, - 'va': {'_FillValue': -32767.0, 'dtype': 'short', "zlib": True, "complevel": 2, "shuffle": True}, - 'vr': {'_FillValue': -32767.0, 'dtype': 'short', "zlib": True, "complevel": 2, "shuffle": True}, - 'x': {'_FillValue': None}, - 'y': {'_FillValue': None} - } +ENCODING_ATTRS = ['_FillValue', 'dtype', "zlib", "complevel", "shuffle", 'add_offset', 'scale_factor'] def crop_netcdf_product(netcdf_file: Path) -> Path: @@ -114,10 +99,12 @@ def crop_netcdf_product(netcdf_file: Path) -> Path: chunk_lines = np.min([np.ceil(8192 / dims['y']) * 128, dims['y']]) two_dim_chunks_settings = (chunk_lines, dims['x']) - encoding = ENCODING_TEMPLATE.copy() - if not netcdf_file.name.startswith('S1'): - for radar_variable in ['M11', 'M12', 'va', 'vr']: - del encoding[radar_variable] + encoding = {} + for variable in ds.data_vars.keys(): + if variable in ['img_pair_info', 'mapping']: + continue + attributes = {attr: ds[variable].encoding[attr] for attr in ENCODING_ATTRS if attr in ds[variable].encoding} + encoding[variable] = attributes for _, attributes in encoding.items(): if attributes['_FillValue'] is not None: From e050c21088ba405ded817044cf321eb00f0e010d Mon Sep 17 00:00:00 2001 From: Joseph H Kennedy Date: Tue, 2 Jul 2024 22:16:12 -0800 Subject: [PATCH 23/23] add changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23a65519..1ad1b937 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ and uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [0.18.0] ### Added * The Sentinel-1 correction workflow will now calculate and write the M11/M12 conversion matrices to a netCDF file. + +### Fixed +* `hyp3_autorift.crop` will now preserve the `add_offset` and `scale_factor` encoding attributes for all variables, and in particular, for the M11/M12 conversion matrices. + ### Removed * Support for Python 3.8 has been dropped.