Skip to content

Commit

Permalink
Merge pull request #29 from ASFHyP3/develop
Browse files Browse the repository at this point in the history
Release v0.3.0
  • Loading branch information
forrestfwilliams authored Oct 24, 2024
2 parents b457f30 + c9b902a commit c726efa
Show file tree
Hide file tree
Showing 21 changed files with 401 additions and 90 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ on:
jobs:
call-changelog-check-workflow:
# Docs: https://github.com/ASFHyP3/actions
uses: ASFHyP3/actions/.github/workflows/reusable-changelog-check.yml@v0.11.2
uses: ASFHyP3/actions/.github/workflows/reusable-changelog-check.yml@v0.12.0
2 changes: 1 addition & 1 deletion .github/workflows/labeled-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ on:
jobs:
call-labeled-pr-check-workflow:
# Docs: https://github.com/ASFHyP3/actions
uses: ASFHyP3/actions/.github/workflows/reusable-labeled-pr-check.yml@v0.11.2
uses: ASFHyP3/actions/.github/workflows/reusable-labeled-pr-check.yml@v0.12.0
2 changes: 1 addition & 1 deletion .github/workflows/release-checklist-comment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
jobs:
call-release-workflow:
# Docs: https://github.com/ASFHyP3/actions
uses: ASFHyP3/actions/.github/workflows/reusable-release-checklist-comment.yml@v0.11.2
uses: ASFHyP3/actions/.github/workflows/reusable-release-checklist-comment.yml@v0.12.0
permissions:
pull-requests: write
secrets:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
jobs:
call-release-workflow:
# Docs: https://github.com/ASFHyP3/actions
uses: ASFHyP3/actions/.github/workflows/reusable-release.yml@v0.11.2
uses: ASFHyP3/actions/.github/workflows/reusable-release.yml@v0.12.0
with:
release_prefix: OPERA-DISP-TMS
release_branch: main
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ on: push
jobs:
call-secrets-analysis-workflow:
# Docs: https://github.com/ASFHyP3/actions
uses: ASFHyP3/actions/.github/workflows/reusable-secrets-analysis.yml@v0.11.2
uses: ASFHyP3/actions/.github/workflows/reusable-secrets-analysis.yml@v0.12.0

call-flake8-workflow:
# Docs: https://github.com/ASFHyP3/actions
uses: ASFHyP3/actions/.github/workflows/reusable-flake8.yml@v0.11.2
uses: ASFHyP3/actions/.github/workflows/reusable-flake8.yml@v0.12.0
with:
local_package_names: opera_disp_tms
2 changes: 1 addition & 1 deletion .github/workflows/tag-version.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
jobs:
call-bump-version-workflow:
# Docs: https://github.com/ASFHyP3/actions
uses: ASFHyP3/actions/.github/workflows/reusable-bump-version.yml@v0.11.2
uses: ASFHyP3/actions/.github/workflows/reusable-bump-version.yml@v0.12.0
with:
user: tools-bot
email: [email protected]
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ on:
jobs:
call-pytest-workflow:
# Docs: https://github.com/ASFHyP3/actions
uses: ASFHyP3/actions/.github/workflows/reusable-pytest.yml@v0.11.2
uses: ASFHyP3/actions/.github/workflows/reusable-pytest.yml@v0.12.0
with:
local_package_name: opera_disp_tms
python_versions: >-
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ 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.3.0]
### Added
* Ability to generate SW velocity tiles in `generated_sw_vel_tile.py`

### Changed
* California dataset scripts to allow for generation of SW velocity tiles
* Rename `generate_frame_tile.py` to `generate_metadata_tile.py`
* Simplified CLI and filenames of metadata tiles so that location is specified by the upper-left corner of the tile, not the full bounding box
* Expanded/modified some functions in `generate_sw_disp_tile.py` so that they could be reused by `generate_sw_vel_tile.py`

### Fixed
* `extent.json` will be written during `create_tile_map.py` even if the directory `tiles/` does not exist prior to running

## [0.2.0]
### Added
Expand Down
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Package for [OPERA DISP](https://www.jpl.nasa.gov/go/opera/products/disp-product

To run all commands in sequence use:
```bash
git clone https://github.com/ASFHyP3/opera-disp-tms.git
git clone https://github.com/ASFHyP3/opera-disp-tms.git
cd OPERA-DISP-TMS
mamba env create -f environment.yml
mamba activate opera-disp-tms
Expand Down Expand Up @@ -66,6 +66,20 @@ The resulting products have the name format:
For example:
`SW_CUMUL_DISP_20170901_20171231_ASCENDING_W125N42.tif`

### Create a Short Wavelength Velocity tile
The `generate_sw_vel_tile` CLI command can be used to generate a short wavelength velocity geotiff:
```bash
generate_sw_vel_tile METADATA_ASCENDING_W125N42.tif 20170901 20171231
```
Where `METADATA_ASCENDING_W125N42.tif` is the path to the frame metadata tile you want to generate a Short Wavelength Velocity tile for, and `20170901`/`20171231` specify the start/end of the secondary date search range to generate a tile for in format `%Y%m%d`.

By default, the velocity will be calculated with **only** two data points (the first and last dates in the search range), but you can pass the optional `--full` flag to calculate the velocity using all available data in the search range. Using this option will significantly increase processing times.

The resulting products have the name format:
`SW_VELOCITY_DISP_{start date search range}_{stop data search range}_{orbit direction}_{upper left corner in lon/lat}.tif`
For example:
`SW_VELOCITY_DISP_20170901_20171231_ASCENDING_W125N42.tif`

### Create a Tile Map
The `create_tile_map` CLI command generates a directory with small .png tiles from a list of rasters in a common projection, following the OSGeo Tile Map Service Specification, using gdal2tiles: https://gdal.org/en/latest/programs/gdal2tiles.html

Expand Down
1 change: 1 addition & 0 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ dependencies:
- h5netcdf
- xarray
- rioxarray
- numba
- s3fs
- cachetools
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ dependencies = [
"h5netcdf",
"rioxarray",
"xarray",
"numba",
"cachetools",
]
dynamic = ["version", "readme"]
Expand All @@ -53,6 +54,7 @@ Documentation = "https://github.com/ASFHyP3/opera-disp-tms/tree/develop?tab=read
[project.scripts]
generate_metadata_tile = "opera_disp_tms.generate_metadata_tile:main"
generate_sw_disp_tile = "opera_disp_tms.generate_sw_disp_tile:main"
generate_sw_vel_tile = "opera_disp_tms.generate_sw_vel_tile:main"
get_tmp_s3_creds = "opera_disp_tms.tmp_s3_access:main"
create_tile_map = "opera_disp_tms.create_tile_map:main"

Expand Down
2 changes: 1 addition & 1 deletion scripts/make_cal_meta_tiles.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import argparse
from pathlib import Path

from opera_disp_tms.generate_frame_tile import create_product_name, create_tile_for_bbox
from opera_disp_tms.generate_metadata_tile import create_product_name, create_tile_for_bbox


def make_cal_meta_tiles(orbit_direction):
Expand Down
31 changes: 21 additions & 10 deletions scripts/make_cal_sw_disp_tiles.py → scripts/make_cal_tiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,56 @@
from pathlib import Path

from opera_disp_tms.create_tile_map import create_tile_map
from opera_disp_tms.generate_sw_disp_tile import create_product_name, create_sw_disp_tile
from opera_disp_tms.generate_sw_disp_tile import create_sw_disp_tile
from opera_disp_tms.generate_sw_vel_tile import create_sw_vel_tile
from opera_disp_tms.utils import create_tile_name


def make_cal_sw_disp_tiles(meta_tile_dir: Path, begin_date: datetime, end_date: datetime):
def make_cal_tiles(meta_tile_dir: Path, workflow: str, begin_date: datetime, end_date: datetime):
workflow_opts = {
'displacement': ['SW_CUMUL_DISP', create_sw_disp_tile, None],
'velocity': ['SW_VELOCITY', create_sw_vel_tile, [-0.05, 0.05]],
}
prod_type, create_tile_func, scale_range = workflow_opts[workflow]
tiles = list(meta_tile_dir.glob('*.tif'))
for tile in tiles:
product_name = Path(create_product_name(tile.name, begin_date, end_date))
product_name = Path(create_tile_name(tile.name, begin_date, end_date, prod_type))
if product_name.exists():
print(f'{product_name} already exists. Skipping.')
continue
create_sw_disp_tile(tile, begin_date, end_date)
create_tile_func(tile, begin_date, end_date)

sw_disp_tiles = [str(x) for x in Path.cwd().glob('*.tif')]
tiles = [str(x) for x in Path.cwd().glob('*.tif')]
tileset_dir = Path.cwd() / 'tiles'
tileset_dir.mkdir(exist_ok=True)
create_tile_map(str(tileset_dir), sw_disp_tiles)

create_tile_map(str(tileset_dir), tiles, scale_range)


def main():
parser = argparse.ArgumentParser(description='Create a short wavelength cumulative displacement tile')
parser.add_argument('meta_tile_dir', type=str, help='Path to the metadata tile')
parser.add_argument(
'--begin_date',
'workflow', type=str, choices=['displacement', 'velocity'], help='Workflow to run (displacement or velocity)'
)
parser.add_argument(
'--begin-date',
type=str,
default='20170101',
help='Start of secondary date search range to generate tile for (e.g., 20240101)',
)
parser.add_argument(
'--end_date',
'--end-date',
type=str,
default='20171231',
help='End of secondary date search range to generate tile for (e.g., 20240101',
help='End of secondary date search range to generate tile for (e.g., 20240101)',
)

args = parser.parse_args()
args.meta_tile_dir = Path(args.meta_tile_dir)
args.begin_date = datetime.strptime(args.begin_date, '%Y%m%d')
args.end_date = datetime.strptime(args.end_date, '%Y%m%d')
make_cal_sw_disp_tiles(args.meta_tile_dir, args.begin_date, args.end_date)
make_cal_tiles(args.meta_tile_dir, args.workflow, args.begin_date, args.end_date)


if __name__ == '__main__':
Expand Down
23 changes: 13 additions & 10 deletions src/opera_disp_tms/create_tile_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import subprocess
import tempfile
from pathlib import Path
from typing import List

from osgeo import gdal, gdalconst, osr


gdal.UseExceptions()


Expand All @@ -21,22 +23,20 @@ def get_tile_extent(info: dict, output_folder: Path) -> None:
minx, miny = info['cornerCoordinates']['lowerLeft']
maxx, maxy = info['cornerCoordinates']['upperRight']
proj = osr.SpatialReference(info['coordinateSystem']['wkt'])
extent = {
"extent": [minx, miny, maxx, maxy],
"EPSG": int(proj.GetAttrValue('AUTHORITY', 1))
}
extent = {'extent': [minx, miny, maxx, maxy], 'EPSG': int(proj.GetAttrValue('AUTHORITY', 1))}

with open(output_folder / 'extent.json', 'w') as outfile:
json.dump(extent, outfile)


def create_tile_map(output_folder: str, input_rasters: list[str]):
def create_tile_map(output_folder: str, input_rasters: list[str], scale_range: List[float] = None) -> None:
"""Generate a directory with small .png tiles from a list of rasters in a common projection, following the OSGeo
Tile Map Service Specification, using gdal2tiles: https://gdal.org/en/latest/programs/gdal2tiles.html
Args:
output_folder: Path of the output directory to create
input_rasters: List of gdal-compatible raster paths to mosaic
scale_range: Optional list of two integers to scale the mosaic by
"""
with tempfile.NamedTemporaryFile() as mosaic_vrt, tempfile.NamedTemporaryFile() as byte_vrt:
# mosaic the input rasters
Expand All @@ -46,15 +46,15 @@ def create_tile_map(output_folder: str, input_rasters: list[str]):
vrt_info = gdal.Info(mosaic_vrt.name, stats=True, format='json')
stats = vrt_info['bands'][0]['metadata']['']

# get bounds of VRT and write to file
get_tile_extent(vrt_info, Path(output_folder))
if scale_range is None:
scale_range = [stats['STATISTICS_MINIMUM'], stats['STATISTICS_MAXIMUM']]

gdal.Translate(
destName=byte_vrt.name,
srcDS=mosaic_vrt.name,
format='VRT',
outputType=gdalconst.GDT_Byte,
scaleParams=[[stats['STATISTICS_MINIMUM'], stats['STATISTICS_MAXIMUM']]],
scaleParams=[scale_range],
resampleAlg='nearest',
)

Expand All @@ -71,12 +71,15 @@ def create_tile_map(output_folder: str, input_rasters: list[str]):
]
subprocess.run(command)

# get bounds of VRT and write to file
get_tile_extent(vrt_info, Path(output_folder))


def main():
parser = argparse.ArgumentParser(
description='Generate a directory with small .png tiles from a list of rasters in a common projection, '
'following the OSGeo Tile Map Service Specification, using gdal2tiles: '
'https://gdal.org/en/latest/programs/gdal2tiles.html'
'following the OSGeo Tile Map Service Specification, using gdal2tiles: '
'https://gdal.org/en/latest/programs/gdal2tiles.html'
)
parser.add_argument('output_folder', type=str, help='Path of the output directory to create')
parser.add_argument('input_rasters', type=str, nargs='+', help='List of gdal-compatible raster paths to mosaic')
Expand Down
Loading

0 comments on commit c726efa

Please sign in to comment.