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

Add GOES Data Download Manager Script #240

Merged
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
78 changes: 73 additions & 5 deletions satip/eumetsat.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import shutil
import time
import urllib
import warnings
import zipfile
from io import BytesIO
from urllib.error import HTTPError
Expand All @@ -28,9 +29,18 @@

from satip import utils
from satip.data_store import dateset_it_to_filename
from satip.goes_download_manager import GOESDownloadManager

log = structlog.stdlib.get_logger()

# Suppress FutureWarning related to 'H' argument
warnings.filterwarnings('ignore', category=FutureWarning)
# constants for different data sources
EUMETSAT_PROVIDER = "EUMETSAT"
GOES_PROVIDER = "GOES"



API_ENDPOINT = "https://api.eumetsat.int"

# Data Store searching endpoint
Expand Down Expand Up @@ -196,12 +206,10 @@ def dataset_id_to_link(collection_id, data_id, access_token):
)


class DownloadManager: # noqa: D205
"""
The DownloadManager class

provides a handler for downloading data from the EUMETSAT API,
managing: retrieval, logging and metadata
class EUMETSATDownloadManager:
"""
Manager class for downloading EUMETSAT data.
"""

def __init__(
Expand Down Expand Up @@ -679,3 +687,63 @@ def eumetsat_cloud_name_to_datetime(filename: str):
"""Takes a file from the EUMETSAT API and returns the it's datetime part for Cloud mask files"""
date_str = filename.split("0100-0100-")[-1].split(".")[0]
return datetime.datetime.strptime(date_str, "%Y%m%d%H%M%S")


class DownloadManager:
"""
Main download manager class to handle both EUMETSAT

and GOES data downloading based on the provider.
"""

def __init__(self, provider, user_key=None,
user_secret=None, data_dir=None,
log_directory=None):
"""
Initialize the DownloadManager.

Args:
provider (str): Provider name ('EUMETSAT' or 'GOES').
user_key (str): User key for accessing data (for EUMETSAT).
user_secret (str): User secret for accessing data (for EUMETSAT).
data_dir (str): Directory to save downloaded data.
log_directory (str): Directory to save logs.
"""
self.provider = provider

if self.provider == "EUMETSAT":
self.download_manager = EUMETSATDownloadManager(user_key, user_secret,
data_dir, log_directory)
elif self.provider == "GOES":
self.download_manager = GOESDownloadManager(data_dir, log_directory)
else:
raise ValueError("Invalid provider. Supported providers are 'EUMETSAT' and 'GOES'.")

def download_data(self, start_time, end_time):
"""
Download data for the specified time range.

Args:
start_time (datetime): Start of the download period.
end_time (datetime): End of the download period.
"""
if self.provider == "GOES":
self.download_manager.download_goes_data(start_time, end_time)


# Example usage
if __name__ == "__main__":
14Richa marked this conversation as resolved.
Show resolved Hide resolved
provider = "GOES"
user_key = "your_user_key"
user_secret = "your_user_secret"
data_dir = "path to data directory"
log_directory = "path to log diirectory"

start_time = datetime.datetime(2024, 3, 1, 0, 0)
end_time = datetime.datetime(2024, 3, 1, 6, 0)

if data_dir is not None:
manager = DownloadManager(provider, None, None, data_dir, log_directory)
manager.download_data(start_time, end_time)
else:
print("Error: 'data_dir' is not properly set.")
106 changes: 106 additions & 0 deletions satip/goes_download_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
"""
Script for downloading GOES data.
"""

import datetime
import logging
import os

from goes2go import GOES


class GOESDownloadManager:
14Richa marked this conversation as resolved.
Show resolved Hide resolved
"""
Manager class for downloading GOES data.
"""
def __init__(self, data_dir, log_directory=None):
"""
Initialize the GOESDownloadManager.

Args:
data_dir (str): Directory to save downloaded GOES data.
log_directory (str, optional): Directory to save logs.
If None, logging is printed to STDOUT.
"""
self.data_dir = data_dir
self.ensure_directory_exists(self.data_dir)

if log_directory:
self.ensure_directory_exists(log_directory)
logging.basicConfig(
filename=os.path.join(log_directory, 'goes_download.log'),
level=logging.INFO)
else:
logging.basicConfig(level=logging.INFO)

logging.info(f"GOESDownloadManager initialized. Data will be saved to: {data_dir}")

@staticmethod
def ensure_directory_exists(directory):
"""Ensures the specified directory exists, creating it if necessary."""
if not os.path.exists(directory):
try:
os.makedirs(directory)
logging.info(f"Created directory: {directory}")
except Exception as e:
logging.error(f"Error creating directory {directory}: {e}")
raise
def download_goes_data(self, start_time, end_time, product='ABI-L1b-RadC',
domain='F', satellite=16):
"""
Download GOES data for a specified time range and product.

Args:
start_time (datetime): Start of the download period.
end_time (datetime): End of the download period.
product (str): GOES product identifier. Default is 'ABI-L1b-RadC'.
domain (str): Domain for the product. Default is 'F' (Full Disk).
satellite (int): GOES satellite number. Default is 16.
"""
G = GOES(satellite=satellite, product=product, domain=domain)
current_time = start_time

# Determine time increment based on product/domain
time_increment = 1 # Default time increment (minutes)
if product == 'ABI-L1b-RadC' and domain == 'F':
time_increment = 10

while current_time <= end_time:
try:
# Download the data
ds = G.nearesttime(current_time)
14Richa marked this conversation as resolved.
Show resolved Hide resolved

# Get acquisition time from the dataset
acquisition_time = ds.time.data.item()

# Format the acquisition time for filename
date_string = acquisition_time.strftime("%Y-%m-%d_%H-%M-%S")
filename = f"goes_data_{date_string}.nc"
filepath = os.path.join(self.data_dir, filename)

# Check if data for current acquisition time already exists
if os.path.exists(filepath):
logging.info(f"Data for {date_string} already exists. Skipping.")
current_time += datetime.timedelta(minutes=time_increment)
continue

# Save to NetCDF
ds.to_netcdf(filepath)

logging.info(f"Downloaded and saved GOES data to: {filename}")
except Exception as e:
logging.error(f"Error downloading GOES data for {current_time}: {e}")

current_time += datetime.timedelta(minutes=time_increment)

logging.info("Completed GOES data download.")


if __name__ == "__main__":
14Richa marked this conversation as resolved.
Show resolved Hide resolved

data_dir = "path to data directory"
log_directory = "path to log directory"
start_time = datetime.datetime(2023, 1, 1, 0, 0)
end_time = datetime.datetime(2023, 1, 1, 1, 0)
manager = GOESDownloadManager(data_dir, log_directory)
manager.download_goes_data(start_time, end_time)