Source code for radarx.io.aws_data

#!/usr/bin/env python
# Copyright (c) 2024-2025, Radarx Developers.
# Distributed under the MIT License. See LICENSE for more info.

"""
AWS Radar Data Utilities
=========================

This module provides utilities to interact with AWS S3 buckets
containing radar data. It supports listing available files in
specific paths and downloading them locally.

Supported Buckets
-----------------

- **NEXRAD Level II Archive**: ``noaa-nexrad-level2``
- **NEXRAD Level II Real-Time**: ``unidata-nexrad-level2-chunks``
- **NEXRAD Level III Real-Time**: ``unidata-nexrad-level3``
- **MRMS Data**: ``noaa-mrms-pds``

Usage Examples
--------------

1. List available files::

       from radarx.io.aws_data import list_available_files
       files = list_available_files('noaa-nexrad-level2', '2016/10/06/KAMX/')
       print(files)

2. Download a file::

       from radarx.io.aws_data import download_file
       file_path = download_file('noaa-nexrad-level2',
           '2016/10/06/KAMX/KAMX20161006_170414_V06', './downloads')
       print('File downloaded to', file_path)

This sub-module contains functions necessary to grid the radar data.

.. autosummary::
   :nosignatures:
   :toctree: generated/

   {}
"""

__all__ = [
    "get_s3_client",
    "list_available_files",
    "download_file",
]

__doc__ = __doc__.format("\n   ".join(__all__))

import boto3
import botocore
import os

# AWS Buckets for different radar data
AWS_BUCKETS = {
    "NEXRAD_ARCHIVE": "noaa-nexrad-level2",
    "NEXRAD_REALTIME": "unidata-nexrad-level2-chunks",
    "NEXRAD_LEVEL3": "unidata-nexrad-level3",
    "MRMS": "noaa-mrms-pds",
}


[docs] def get_s3_client(anonymous=True): """ Create an S3 client. Parameters ---------- anonymous : bool, optional If True, creates an anonymous S3 client. Default is True. Returns ------- boto3.client Configured S3 client. Examples -------- Create an anonymous client: >>> s3 = get_s3_client() Create an authenticated client: >>> s3 = get_s3_client(anonymous=False) """ if anonymous: session = boto3.session.Session() return session.client( service_name="s3", config=botocore.client.Config(signature_version=botocore.UNSIGNED), ) else: return boto3.client("s3") # pragma: no cover
[docs] def list_available_files(bucket, prefix, anonymous=True): """ List files in an S3 bucket with the given prefix. Parameters ---------- bucket : str Name of the AWS S3 bucket. prefix : str Prefix path in the bucket to search for files. anonymous : bool, optional If True, uses anonymous access. Default is True. Returns ------- list List of file paths available under the prefix. Examples -------- List files in the NEXRAD Level II archive bucket: >>> files = list_available_files("noaa-nexrad-level2", "2016/10/06/KAMX/") >>> print(files) List files in the MRMS bucket: >>> files = list_available_files("noaa-mrms-pds", "CONUS/ReflectivityAtLowestAltitude_00.50/") >>> print(files) """ s3 = get_s3_client(anonymous=anonymous) try: # pragma: no cover response = s3.list_objects_v2(Bucket=bucket, Prefix=prefix) files = [item["Key"] for item in response.get("Contents", [])] return files except botocore.exceptions.ClientError as e: # pragma: no cover print(f"Failed to list files: {e}") # pragma: no cover return [] # pragma: no cover
[docs] def download_file(bucket, file_key, save_dir, anonymous=True): """ Download a file from S3. Parameters ---------- bucket : str Name of the AWS S3 bucket. file_key : str Key of the file to download. save_dir : str Directory to save the downloaded file. anonymous : bool, optional If True, uses anonymous access. Default is True. Returns ------- str Path to the downloaded file. Examples -------- Download a NEXRAD Level II file: >>> file_path = download_file( ... "noaa-nexrad-level2", ... "2016/10/06/KAMX/KAMX20161006_170414_V06", ... "./downloads" ... ) >>> print(f"File downloaded to: {file_path}") Download an MRMS file: >>> file_path = download_file( ... "noaa-mrms-pds", ... "CONUS/ReflectivityAtLowestAltitude_00.50/2016/10/06/" + "ReflectivityAtLowestAltitude_00.50_20161006-1700.grib2.gz", ... "./downloads" ... ) >>> print(f"File downloaded to: {file_path}") """ s3 = get_s3_client(anonymous=anonymous) os.makedirs(save_dir, exist_ok=True) local_file = os.path.join(save_dir, os.path.basename(file_key)) try: s3.download_file(bucket, file_key, local_file) print(f"Downloaded: {local_file}") # pragma: no cover return local_file # pragma: no cover except botocore.exceptions.ClientError as e: print(f"Failed to download {file_key}: {e}") return None