Skip to content
Closed
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
8 changes: 1 addition & 7 deletions src/opera_utils/nisar/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

from __future__ import annotations

from ._download import download_gslcs, run_download
from ._geometry import prepare_incidence_angle
from ._download import run_download
from ._gunw_search import search_gunw
from ._mask import get_gslc_mask, get_gunw_mask
from ._info import (
find_intersecting_frames,
get_frame_latlon_bounds,
Expand All @@ -30,13 +28,9 @@
"OrbitDirection",
"OutOfBoundsError",
"UrlType",
"download_gslcs",
"find_intersecting_frames",
"get_frame_latlon_bounds",
"get_gslc_mask",
"get_gunw_mask",
"get_nisar_bbox",
"prepare_incidence_angle",
"load_gpkg",
"nisar_frame_info",
"open_file",
Expand Down
116 changes: 1 addition & 115 deletions src/opera_utils/nisar/_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,15 @@
from __future__ import annotations

import logging
from concurrent.futures import ThreadPoolExecutor, as_completed
from datetime import datetime
from pathlib import Path

import netrc
import shutil

import h5py
import numpy as np
import requests
from shapely import from_wkt
from tqdm.auto import tqdm
from tqdm.contrib.concurrent import process_map

from opera_utils._types import PathOrStr
from opera_utils.nisar._product import (
NISAR_GSLC_GRIDS,
NISAR_GSLC_IDENTIFICATION,
Expand All @@ -35,7 +29,7 @@

logger = logging.getLogger("opera_utils")

__all__ = ["download_gslcs", "process_file", "run_download"]
__all__ = ["process_file", "run_download"]


def process_file(
Expand Down Expand Up @@ -272,114 +266,6 @@ def _extract_subset_from_h5(
dst.attrs["source_file"] = source_name


def download_gslcs(
output_dir: PathOrStr,
bbox: tuple[float, float, float, float] | None = None,
track_frame_number: int | None = None,
relative_orbit_number: int | None = None,
orbit_direction: str | None = None,
start_datetime: datetime | None = None,
end_datetime: datetime | None = None,
max_jobs: int = 4,
short_name: str = "NISAR_L2_GSLC_BETA_V1",
) -> list[Path]:
"""Download full NISAR GSLC files matching the given search criteria.

Parameters
----------
output_dir : Path | str
Directory to save downloaded files to.
bbox : tuple[float, float, float, float], optional
Bounding box as (west, south, east, north) in degrees lon/lat.
track_frame_number : int, optional
Track frame number (stays constant for repeat passes).
relative_orbit_number : int, optional
Relative orbit number to filter by.
orbit_direction : str, optional
Orbit direction: "A" for ascending, "D" for descending.
start_datetime : datetime, optional
Start datetime of the product search.
end_datetime : datetime, optional
End datetime of the product search.
max_jobs : int, optional
Number of parallel downloads, by default 4.
short_name : str, optional
CMR collection short name, by default "NISAR_L2_GSLC_BETA_V1".

Returns
-------
list[Path]
List of paths to the downloaded files.

Examples
--------
Download by bounding box:

>>> download_gslcs( # doctest: +SKIP
... output_dir="./gslc_data",
... bbox=(-120.5, 35.0, -119.5, 36.0),
... )

Download by track/orbit:

>>> download_gslcs( # doctest: +SKIP
... output_dir="./gslc_data",
... relative_orbit_number=64,
... orbit_direction="A",
... )

"""
output_dir = Path(output_dir)
products = search(
bbox=bbox,
track_frame_number=track_frame_number,
relative_orbit_number=relative_orbit_number,
orbit_direction=orbit_direction,
start_datetime=start_datetime,
end_datetime=end_datetime,
url_type=UrlType.HTTPS,
short_name=short_name,
)

if not products:
logger.warning("No GSLC products found matching search criteria")
return []

logger.info(f"Found {len(products)} GSLC products to download")
output_dir.mkdir(exist_ok=True, parents=True)

auth = netrc.netrc().authenticators("urs.earthdata.nasa.gov")
if auth is None:
msg = "No .netrc entry found for urs.earthdata.nasa.gov"
raise ValueError(msg)
username, _, password = auth
session = requests.Session()
session.auth = (username, password)

def _download_one(product: GslcProduct) -> Path:
url = str(product.filename)
out_path = output_dir / Path(url).name
if out_path.exists():
logger.info(f"Skipped (exists): {out_path.name}")
return out_path
logger.debug(f"Downloading {out_path.name}")
with session.get(url, stream=True) as r:
r.raise_for_status()
with open(out_path, "wb") as f:
shutil.copyfileobj(r.raw, f)
return out_path

out_paths: list[Path] = []
with ThreadPoolExecutor(max_workers=max_jobs) as pool:
futures = {pool.submit(_download_one, p): p for p in products}
for future in tqdm(
as_completed(futures), total=len(futures), desc="Downloading GSLC"
):
out_paths.append(future.result())

return sorted(out_paths)


def _get_rowcol_slice(
product: GslcProduct,
bbox: tuple[float, float, float, float] | None,
Expand Down
175 changes: 0 additions & 175 deletions src/opera_utils/nisar/_geometry.py

This file was deleted.

Loading