Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding command line interfaces and entry points #15

Merged
merged 13 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 47 additions & 2 deletions docs/workflows/README.MD
Original file line number Diff line number Diff line change
@@ -1,4 +1,49 @@
## Workflows
# Workflows
The repository will handle multiple workflows and backends, some of which have specific requirements.

- [pyroSAR + GAMMA](pyrosar_gamma.md)
## Workflows
- pyroSAR + GAMMA
- [Requirements](pyrosar_gamma.md)

## Command line interface
> **_NOTE:_** At this time, pyroSAR + GAMMA is the only workflow, and the command line interfaces have not yet been generalised to other workflows.

The package has a number of useful command line interfaces:

### Finding the location of a scene on the NCI
The `find-scene` command will display the location of a given scene on the NCI.
The full path to the scene is required as the input to other commands.

Example usage:
```
$ find-scene S1A_EW_GRDM_1SDH_20240129T091735_20240129T091828_052319_065379_0F1E

/path/to/scene/S1A_EW_GRDM_1SDH_20240129T091735_20240129T091828_052319_065379_0F1E.zip
```

### Submit a workflow
This will submit a job request to the NCI based on the job parameters and file paths in the supplied config.
The [default config](../../sar_antarctica/nci/configs/default.toml) will be used if no other config is provided.

Example usage
```
$ submit-pyrosar-gamma-workflow /path/to/scene/S1A_EW_GRDM_1SDH_20240129T091735_20240129T091828_052319_065379_0F1E.zip
```
This will submit a job to the NCI with the default config.
To use a different config, run the command and supply the `--config` option
```
--config /path/to/config.toml
```

### Run a workflow interactively
If you are still testing a workflow, it is best to run it in an interactive session.
While in an interactive session, you can run the workflow directly.

Example usage
```
$ run-pyrosar-gamma-workflow /path/to/scene/S1A_EW_GRDM_1SDH_20240129T091735_20240129T091828_052319_065379_0F1E.zip
```
To use a different config, run the command and supply the `--config` option
```
--config /path/to/config.toml
```
6 changes: 6 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ version = "0.1" # TODO base this on files in proje t
Homepage = "https://github.com/GeoscienceAustralia/sar-antarctica.git"
# Documentation = "XXX"

[project.scripts]
find-scene = "sar_antarctica.nci.cli:find_scene_file"
find-orbits = "sar_antarctica.nci.cli:find_orbits_for_scene"
run-pyrosar-gamma-workflow = "sar_antarctica.nci.cli:run_pyrosar_gamma_workflow"
submit-pyrosar-gamma-workflow = "sar_antarctica.nci.cli:submit_pyrosar_gamma_workflow"

[tool.pytest.ini_options]
testpaths = ["tests/*"]

Expand Down
174 changes: 174 additions & 0 deletions sar_antarctica/nci/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import click
from pathlib import Path
import tomli

from sar_antarctica.nci.filesystem import get_orbits_nci
from sar_antarctica.nci.submission.pyrosar_gamma.prepare_input import (
get_orbit_and_dem,
)
from sar_antarctica.nci.preparation.orbits import (
filter_orbits_to_cover_time_window,
)
from sar_antarctica.nci.preparation.scenes import (
parse_scene_file_sensor,
parse_scene_file_dates,
find_scene_file_from_id,
)
from sar_antarctica.nci.processing.pyroSAR.pyrosar_geocode import (
run_pyrosar_gamma_geocode,
)
from sar_antarctica.nci.submission.pyrosar_gamma.submit_job import submit_job


@click.command()
@click.argument("scene_name", type=str)
def find_scene_file(scene_name):
scene_file = find_scene_file_from_id(scene_name)

click.echo(scene_file)


DEFAULT_CONFIGURATION = Path(__file__).resolve().parent / "configs/default.toml"


def configure(ctx, param, filename):
with open(filename, "rb") as f:
configuration_dictionary = tomli.load(f)
ctx.default_map = configuration_dictionary


@click.command()
@click.argument(
"scene",
type=click.Path(exists=True, dir_okay=False, path_type=Path),
)
@click.option(
"-c",
"--config",
type=click.Path(dir_okay=False),
default=DEFAULT_CONFIGURATION,
callback=configure,
is_eager=True,
expose_value=False,
help="Read option defaults from the specified .toml file",
show_default=True,
)
@click.option("--spacing", type=int)
@click.option("--scaling", type=click.Choice(["linear", "db"]))
@click.option("--ncpu", type=str, default="4")
@click.option("--mem", type=str, default="32")
@click.option("--queue", type=str, default="normal")
@click.option("--project", type=str, default="u46")
@click.option("--walltime", type=str, default="02:00:00")
@click.option(
"--output-dir",
type=click.Path(exists=True, file_okay=False, path_type=Path),
default="/g/data/yp75/projects/sar-antractica-processing/pyrosar_gamma/",
)
def submit_pyrosar_gamma_workflow(
scene, spacing, scaling, ncpu, mem, queue, project, walltime, output_dir
):

pbs_parameters = {
"ncpu": ncpu,
"mem": mem,
"queue": queue,
"project": project,
"walltime": walltime,
}

log_dir = output_dir / "submission/logs"
log_dir.mkdir(parents=True, exist_ok=True)

submit_job(scene, spacing, scaling, pbs_parameters, log_dir)


@click.command()
@click.argument(
"scene",
type=click.Path(exists=True, dir_okay=False, path_type=Path),
)
@click.option(
"-c",
"--config",
type=click.Path(dir_okay=False),
default=DEFAULT_CONFIGURATION,
callback=configure,
is_eager=True,
expose_value=False,
help="Read option defaults from the specified .toml file",
show_default=True,
)
@click.option("--spacing", type=int)
@click.option("--scaling", type=click.Choice(["linear", "db"]))
@click.option(
"--orbit-dir", type=click.Path(exists=True, file_okay=False, path_type=Path)
)
@click.option("--orbit-type", type=click.Choice(["POE", "RES", "either"]))
@click.option(
"--output-dir",
type=click.Path(exists=True, file_okay=False, path_type=Path),
default="/g/data/yp75/projects/sar-antractica-processing/pyrosar_gamma/",
)
@click.option(
"--gamma-lib-dir",
type=click.Path(exists=True, file_okay=False, path_type=Path),
default="/g/data/dg9/GAMMA/GAMMA_SOFTWARE-20230712",
)
@click.option(
"--gamma-env-var",
type=str,
default="/g/data/yp75/projects/pyrosar_processing/sar-pyrosar-nci:/apps/fftw3/3.3.10/lib:/apps/gdal/3.6.4/lib64",
)
def run_pyrosar_gamma_workflow(
scene,
spacing,
scaling,
orbit_dir,
orbit_type,
output_dir,
gamma_lib_dir,
gamma_env_var,
):

click.echo("Preparing orbit and DEM")
dem_output_dir = output_dir / "data/dem"

orbit, dem = get_orbit_and_dem(scene, dem_output_dir, orbit_dir, orbit_type)

click.echo(f" Identified orbit: {orbit}")
click.echo(f" Identified DEM: {dem}")

click.echo("Running processing")
print(scene, spacing, scaling, output_dir, gamma_lib_dir, gamma_env_var)
run_pyrosar_gamma_geocode(
scene=scene,
orbit=orbit,
dem=dem,
output=output_dir,
gamma_library=gamma_lib_dir,
gamma_env=gamma_env_var,
geocode_spacing=spacing,
geocode_scaling=scaling,
)


@click.command()
@click.argument("scene")
def find_orbits_for_scene(scene: str):
sensor = parse_scene_file_sensor(scene)
start_time, stop_time = parse_scene_file_dates(scene)

poe_paths = get_orbits_nci("POE", sensor)
relevent_poe_paths = filter_orbits_to_cover_time_window(
poe_paths, start_time, stop_time
)
for orbit in relevent_poe_paths:
print(orbit["orbit"])

res_paths = get_orbits_nci("RES", sensor)
relevant_res_paths = filter_orbits_to_cover_time_window(
res_paths, start_time, stop_time
)
for orbit in relevant_res_paths:
print(orbit["orbit"])
12 changes: 12 additions & 0 deletions sar_antarctica/nci/configs/EW.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
spacing = 40
scaling = "linear"
ncpu = "4"
mem = "64"
queue = "normal"
project = "u46"
walltime = "02:00:00"
orbit_dir = "/g/data/fj7/Copernicus/Sentinel-1/"
orbit_type = "POE"
output_dir = "/g/data/yp75/projects/sar-antractica-processing/pyrosar_gamma/"
gamma_lib_dir = "/g/data/dg9/GAMMA/GAMMA_SOFTWARE-20230712"
gamma_env_var = "/g/data/yp75/projects/pyrosar_processing/sar-pyrosar-nci:/apps/fftw3/3.3.10/lib:/apps/gdal/3.6.4/lib64"
12 changes: 12 additions & 0 deletions sar_antarctica/nci/configs/IW.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
spacing = 10
scaling = "linear"
ncpu = "4"
mem = "128"
queue = "normal"
project = "u46"
walltime = "02:00:00"
orbit_dir = "/g/data/fj7/Copernicus/Sentinel-1/"
orbit_type = "POE"
output_dir = "/g/data/yp75/projects/sar-antractica-processing/pyrosar_gamma_IW/"
gamma_lib_dir = "/g/data/dg9/GAMMA/GAMMA_SOFTWARE-20230712"
gamma_env_var = "/g/data/yp75/projects/pyrosar_processing/sar-pyrosar-nci:/apps/fftw3/3.3.10/lib:/apps/gdal/3.6.4/lib64"
12 changes: 12 additions & 0 deletions sar_antarctica/nci/configs/default.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
spacing = 40
scaling = "linear"
ncpu = "4"
mem = "32"
queue = "normal"
project = "u46"
walltime = "02:00:00"
orbit_dir = "/g/data/fj7/Copernicus/Sentinel-1/"
orbit_type = "POE"
output_dir = "/g/data/yp75/projects/sar-antractica-processing/pyrosar_gamma/"
gamma_lib_dir = "/g/data/dg9/GAMMA/GAMMA_SOFTWARE-20230712"
gamma_env_var = "/g/data/yp75/projects/pyrosar_processing/sar-pyrosar-nci:/apps/fftw3/3.3.10/lib:/apps/gdal/3.6.4/lib64"
26 changes: 22 additions & 4 deletions sar_antarctica/nci/filesystem.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
from pathlib import Path

from sar_antarctica.nci.preparation.orbits import find_orbits
from sar_antarctica.nci.preparation.dem import get_cop30_dem_for_bounds


def get_orbits_nci(orbit_type: str | None, sensor: str) -> list[Path]:
def get_orbits_nci(
orbit_type: str | None,
sensor: str,
nci_orbit_dir: Path = Path("/g/data/fj7/Copernicus/Sentinel-1/"),
) -> list[Path]:
"""For a given orbit type and sensor, compile the relevant orbit files

Parameters
Expand All @@ -12,7 +17,8 @@ def get_orbits_nci(orbit_type: str | None, sensor: str) -> list[Path]:
One of 'POE', 'RES', or None. If None, both POE and RES orbits will be included
sensor : str
Sensor (e.g. S1A or S1B) to search. Typically extracted from the scene ID

nci_orbit_dir : Path, optional
The path containing orbit files on the NCI, by default Path("/g/data/fj7/Copernicus/Sentinel-1/")
Returns
-------
list[Path]
Expand All @@ -25,7 +31,6 @@ def get_orbits_nci(orbit_type: str | None, sensor: str) -> list[Path]:
"""

# Constants for NCI
S1_DIR = Path("/g/data/fj7/Copernicus/Sentinel-1/")
POE_DIR = "POEORB"
RES_DIR = "RESORB"

Expand All @@ -39,9 +44,22 @@ def get_orbits_nci(orbit_type: str | None, sensor: str) -> list[Path]:
raise ValueError("orbit_type must be one of 'POE', 'RES', or None")

nci_orbit_directories = [
S1_DIR / orbit_dir / sensor for orbit_dir in orbit_type_directories
nci_orbit_dir / orbit_dir / sensor for orbit_dir in orbit_type_directories
]

orbits = find_orbits(nci_orbit_directories)

return orbits


def get_dem_nci(
scene: Path, scene_bounds: tuple[float, float, float, float], output_dir: Path
) -> Path:
if not output_dir.exists():
output_dir.mkdir(parents=True, exist_ok=True)
dem_file = output_dir / f"{scene.stem}.tif"

if not dem_file.exists():
_, _ = get_cop30_dem_for_bounds(scene_bounds, dem_file, ellipsoid_heights=True)

return dem_file
Loading
Loading