Skip to content

Commit

Permalink
Switch the Bbox type to a namedtuple (#186)
Browse files Browse the repository at this point in the history
* use a `namedtuple` for `Bbox` for clarity of directions

* fix pre-commit errors for new type

* keep `Tuple` in pydantic for simpler YAML file

* coerce the tuple to a Bbox still

* force type in workflow
  • Loading branch information
scottstanie authored Jan 5, 2024
1 parent 6c5c0d1 commit ec8473a
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 15 deletions.
29 changes: 26 additions & 3 deletions src/dolphin/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import sys
from enum import Enum
from os import PathLike
from typing import TYPE_CHECKING, Tuple, TypeVar, Union
from typing import TYPE_CHECKING, NamedTuple, TypeVar, Union

if sys.version_info >= (3, 10):
from typing import ParamSpec
Expand All @@ -25,8 +25,31 @@
# TypeVar added for generic functions which should return the same type as the input
PathLikeT = TypeVar("PathLikeT", str, PathLikeStr)

# left, bottom, right, top
Bbox = Tuple[float, float, float, float]

class Bbox(NamedTuple):
"""Bounding box named tuple, defining extent in cartesian coordinates.
Usage:
Bbox(left, bottom, right, top)
Attributes
----------
left : float
Left coordinate (xmin)
bottom : float
Bottom coordinate (ymin)
right : float
Right coordinate (xmax)
top : float
Top coordinate (ymax)
"""

left: float
bottom: float
right: float
top: float


# Used for callable types
T = TypeVar("T")
Expand Down
2 changes: 1 addition & 1 deletion src/dolphin/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ def get_raster_bounds(
left, top = _apply_gt(gt=gt, x=0, y=0)
right, bottom = _apply_gt(gt=gt, x=xsize, y=ysize)

return (left, bottom, right, top)
return Bbox(left, bottom, right, top)


def get_raster_metadata(filename: Filename, domain: str = ""):
Expand Down
8 changes: 4 additions & 4 deletions src/dolphin/stitching.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ def get_combined_bounds_nodata(
else:
bounds = out_bounds # type: ignore
else:
bounds = min(xs), min(ys), max(xs), max(ys)
bounds = Bbox(min(xs), min(ys), max(xs), max(ys))

if target_aligned_pixels:
bounds = _align_bounds(bounds, res)
Expand All @@ -482,14 +482,14 @@ def _align_bounds(bounds: Iterable[float], res: tuple[float, float]):
right = math.ceil(right / res[0]) * res[0]
bottom = math.floor(bottom / res[1]) * res[1]
top = math.ceil(top / res[1]) * res[1]
return (left, bottom, right, top)
return Bbox(left, bottom, right, top)


def _reproject_bounds(bounds: Bbox, src_epsg: int, dst_epsg: int) -> Bbox:
t = Transformer.from_crs(src_epsg, dst_epsg, always_xy=True)
left, bottom, right, top = bounds
bbox: Bbox = (*t.transform(left, bottom), *t.transform(right, top)) # type: ignore
return bbox
b = (*t.transform(left, bottom), *t.transform(right, top))
return Bbox(*b)


def get_transformed_bounds(filename: Filename, epsg_code: Optional[int] = None):
Expand Down
14 changes: 10 additions & 4 deletions src/dolphin/workflows/config/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,15 +273,15 @@ class OutputOptions(BaseModel, extra="forbid"):
),
validate_default=True,
)
bounds: Optional[Bbox] = Field(
bounds: Optional[Tuple[float, float, float, float]] = Field(
None,
description=(
"Area of interest: (left, bottom, right, top) longitude/latitude "
"e.g. `bbox=(-150.2,65.0,-150.1,65.5)`"
"Area of interest: [left, bottom, right, top] coordinates. "
"e.g. `bbox=[-150.2,65.0,-150.1,65.5]`"
),
)
bounds_epsg: int = Field(
4326, description="EPSG code for the `bounds`, if specified."
4326, description="EPSG code for the `bounds` coordinates, if specified."
)

hdf5_creation_options: dict = Field(
Expand All @@ -294,6 +294,12 @@ class OutputOptions(BaseModel, extra="forbid"):
)

# validators
@field_validator("bounds", mode="after")
@classmethod
def _convert_bbox(cls, bounds):
if bounds:
return Bbox(*bounds)
return bounds

@field_validator("strides")
@classmethod
Expand Down
8 changes: 5 additions & 3 deletions src/dolphin/workflows/stitching_bursts.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from dolphin import stitching
from dolphin._log import get_log, log_runtime
from dolphin._types import Bbox
from dolphin.interferogram import estimate_interferometric_correlations

from .config import OutputOptions
Expand Down Expand Up @@ -59,12 +60,13 @@ def run(
stitched_ifg_dir.mkdir(exist_ok=True, parents=True)
# Also preps for snaphu, which needs binary format with no nans
logger.info("Stitching interferograms by date.")
out_bounds = Bbox(*output_options.bounds) if output_options.bounds else None
date_to_ifg_path = stitching.merge_by_date(
image_file_list=ifg_file_list, # type: ignore
file_date_fmt=file_date_fmt,
output_dir=stitched_ifg_dir,
output_suffix=".int",
out_bounds=output_options.bounds,
out_bounds=out_bounds,
out_bounds_epsg=output_options.bounds_epsg,
)
stitched_ifg_paths = list(date_to_ifg_path.values())
Expand All @@ -80,7 +82,7 @@ def run(
temp_coh_file_list,
outfile=stitched_temp_coh_file,
driver="GTiff",
out_bounds=output_options.bounds,
out_bounds=out_bounds,
out_bounds_epsg=output_options.bounds_epsg,
)

Expand All @@ -92,7 +94,7 @@ def run(
out_nodata=255,
driver="GTiff",
resample_alg="nearest",
out_bounds=output_options.bounds,
out_bounds=out_bounds,
out_bounds_epsg=output_options.bounds_epsg,
)

Expand Down

0 comments on commit ec8473a

Please sign in to comment.