diff --git a/environment.yml b/environment.yml index d713bda9..01f5c66e 100644 --- a/environment.yml +++ b/environment.yml @@ -23,7 +23,6 @@ dependencies: - wheel # For running - gdal>=3 - - h5netcdf - hyp3lib=1.7.0 - isce2=2.6.1.dev7 - autorift=1.5.0 @@ -35,4 +34,3 @@ dependencies: - pyproj - requests - scipy - - xarray diff --git a/hyp3_autorift/crop.py b/hyp3_autorift/crop.py deleted file mode 100644 index fa94e45f..00000000 --- a/hyp3_autorift/crop.py +++ /dev/null @@ -1,129 +0,0 @@ -# MIT License -# -# Copyright (c) 2020 NASA Jet Propulsion Laboratory -# Modifications (c) Copyright 2023 Alaska Satellite Facility -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -"""Crop HyP3 AutoRIFT products to their valid data range, inplace - -This module is based on the ITS_LIVE production script for cropping V2 products -after they have been generated and has been heavily refactored for use in this HyP3 plugin: - -The original script: -https://github.com/nasa-jpl/its_live_production/blob/957e9aba627be2abafcc9601712a7f9c4dd87849/src/tools/crop_v2_granules.py -""" - -from pathlib import Path - -import numpy as np -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} - } - - -def crop_netcdf_product(netcdf_file: Path) -> Path: - """ - - Args: - netcdf_file: - """ - with xr.open_dataset(netcdf_file) as ds: - # this will drop X/Y coordinates, so drop non-None values just to get X/Y extends - xy_ds = ds.where(ds.v.notnull(), drop=True) - - x_values = xy_ds.x.values - grid_x_min, grid_x_max = x_values.min(), x_values.max() - - y_values = xy_ds.y.values - grid_y_min, grid_y_max = y_values.min(), y_values.max() - - # Based on X/Y extends, mask original dataset - mask_lon = (ds.x >= grid_x_min) & (ds.x <= grid_x_max) - mask_lat = (ds.y >= grid_y_min) & (ds.y <= grid_y_max) - mask = (mask_lon & mask_lat) - - cropped_ds = ds.where(mask, drop=True) - cropped_ds = cropped_ds.load() - - # Reset data for mapping and img_pair_info data variables as ds.where() extends data of all data variables - # to the dimensions of the "mask" - cropped_ds['mapping'] = ds['mapping'] - cropped_ds['img_pair_info'] = ds['img_pair_info'] - - # Compute centroid longitude/latitude - center_x = (grid_x_min + grid_x_max) / 2 - center_y = (grid_y_min + grid_y_max) / 2 - - # Convert to lon/lat coordinates - projection = ds['mapping'].attrs['spatial_epsg'] - to_lon_lat_transformer = pyproj.Transformer.from_crs( - f"EPSG:{projection}", - 'EPSG:4326', - always_xy=True - ) - - # Update centroid information for the granule - center_lon_lat = to_lon_lat_transformer.transform(center_x, center_y) - - cropped_ds['mapping'].attrs['latitude'] = round(center_lon_lat[1], 2) - cropped_ds['img_pair_info'].attrs['longitude'] = round(center_lon_lat[0], 2) - - # Update mapping.GeoTransform - x_cell = x_values[1] - x_values[0] - y_cell = y_values[1] - y_values[0] - - # It was decided to keep all values in GeoTransform center-based - cropped_ds['mapping'].attrs['GeoTransform'] = f"{x_values[0]} {x_cell} 0 {y_values[0]} 0 {y_cell}" - - # Compute chunking like AutoRIFT does: - # https://github.com/ASFHyP3/hyp3-autorift/blob/develop/hyp3_autorift/vend/netcdf_output.py#L410-L411 - dims = cropped_ds.dims - 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] - - for _, attributes in encoding.items(): - if attributes['_FillValue'] is not None: - attributes['chunksizes'] = two_dim_chunks_settings - - cropped_file = netcdf_file.with_stem(f'{netcdf_file.stem}_cropped') - cropped_ds.to_netcdf(cropped_file, engine='h5netcdf', encoding=encoding) - - return cropped_file diff --git a/hyp3_autorift/process.py b/hyp3_autorift/process.py index 86371b67..0138d688 100644 --- a/hyp3_autorift/process.py +++ b/hyp3_autorift/process.py @@ -26,7 +26,6 @@ from osgeo import gdal from hyp3_autorift import geometry, image, io -from hyp3_autorift.crop import crop_netcdf_product log = logging.getLogger(__name__) @@ -472,22 +471,18 @@ def process(reference: str, secondary: str, parameter_file: str = DEFAULT_PARAME if netcdf_file is None: raise Exception('Processing failed! Output netCDF file not found') - netcdf_file = Path(netcdf_file) - cropped_file = crop_netcdf_product(netcdf_file) - netcdf_file.unlink() - if naming_scheme == 'ITS_LIVE_PROD': - product_file = netcdf_file + product_file = Path(netcdf_file) elif naming_scheme == 'ASF': product_name = get_product_name( reference, secondary, orbit_files=(reference_state_vec, secondary_state_vec), pixel_spacing=parameter_info['xsize'], ) product_file = Path(f'{product_name}.nc') + shutil.move(netcdf_file, str(product_file)) else: - product_file = netcdf_file.with_stem(f'{netcdf_file.stem}_IL_ASF_OD') - - shutil.move(cropped_file, str(product_file)) + product_file = Path(netcdf_file.replace('.nc', '_IL_ASF_OD.nc')) + shutil.move(netcdf_file, str(product_file)) with Dataset(product_file) as nc: velocity = nc.variables['v'] diff --git a/setup.py b/setup.py index ddd5742f..433f5ae3 100644 --- a/setup.py +++ b/setup.py @@ -37,7 +37,6 @@ 'boto3', 'botocore', 'gdal', - 'h5netcdf', 'hyp3lib==1.7.0', 'matplotlib', 'netCDF4', @@ -45,7 +44,6 @@ 'pyproj', 'requests', 'scipy', - 'xarray', ], extras_require={