"""Download rinex files from CCIDS using curlftpfs.""" from concurrent.futures import ProcessPoolExecutor from datetime import datetime from pathlib import Path import click import tqdm from ...download.idownload.rinex.nasa_cddis import NasaCddisV3 from ...download.idownload.sp3.ccdis_igs_sp3 import NasaCddisIgsSp3 # ------------------------------------------ Global Variables ------------------------------ # USER EMAIL USER_EMAIL = "navigator@navigator.github.com" # ------------------------------------------ Click Commands ------------------------------------------------ @click.group(invoke_without_command=True, no_args_is_help=True) @click.pass_context @click.option( "-e", "--email", required=False, default=USER_EMAIL, help=f"Email to login to CCIDS. Default: {USER_EMAIL}", ) @click.option( "-t", "--threads", required=False, default=1, type=click.IntRange(1), help="Number of threads to use for downloading", ) @click.option( "-v", "--verbose", required=False, is_flag=True, default=False, help="Enable verbose logging", ) @click.version_option(version="1.0.0") def main(ctx: click.Context, email: str, threads: int, verbose: bool) -> None: """Download RINEX files from CCIDS using without mounting the server.""" # Ensure the context object is dict ctx.ensure_object(dict) # Add verbose to the context ctx.obj["verbose"] = verbose # Create the Downloader ctx.obj["downloader"] = NasaCddisV3(email=email, logging=verbose, threads=threads) return @main.command() @click.pass_context @click.option( "-p", "--path", required=True, type=click.Path(exists=True, dir_okay=True, writable=True, path_type=Path), help="Path to save the files", ) @click.option( "-y", "--year", required=True, type=click.INT, help="Year to download RINEX files" ) @click.option( "-d", "--day", required=True, type=click.IntRange(1, 366), help="Day of year to download RINEX files", ) @click.option( "-s", "--samples", required=False, type=click.INT, default=-1, help="Number of samples to download", ) @click.option( "-m", "--match", required=False, type=click.STRING, default=None, help="IGS station code to match", ) def daily( ctx: click.Context, path: Path, year: int, day: int, samples: int, match: str ) -> None: """Download RINEX files for the given year and day.""" # Download the files from downloader downloader: NasaCddisV3 = ctx.obj["downloader"] # Download the files for the given year and day downloader.download( year=year, day=day, save_path=path, num_files=samples, no_pbar=False, match_string=match, ) return @main.command() @click.pass_context @click.option( "-p", "--path", required=True, type=click.Path(exists=True, dir_okay=True, writable=True, path_type=Path), help="Path to save the files", ) @click.option( "-y", "--year", required=True, type=click.INT, help="Year to download RINEX files" ) @click.option( "-s", "--samples", required=False, type=click.INT, default=-1, help="Number of samples to download", ) @click.option( "--process", required=False, type=click.INT, default=1, help="Number of processes to use for downloading", ) @click.option( "-m", "--match", required=False, type=click.STRING, default=None, help="IGS station code to match", ) def yearly( ctx: click.Context, path: Path, year: int, samples: int, process: int, match: str ) -> None: """Download RINEX files for the given year.""" # Get the range of days start_day, end_day = 1, 366 # If current year, get the range of days till yesterday if year == datetime.now().year: start_day = 1 end_day = datetime.now().timetuple().tm_yday - 1 # Get the downloader downloader: NasaCddisV3 = ctx.obj["downloader"] # Disable the logging in multiprocessing downloader.logger.disabled = True # Download the files for the given year and day using multiprocessing with tqdm.tqdm(total=end_day - start_day + 1, desc="Downloading Files!") as pbar: with ProcessPoolExecutor(max_workers=process) as executor: for day in range(start_day, end_day + 1): future = executor.submit( downloader.download, year=year, day=day, save_path=path, num_files=samples, no_pbar=True, match_string=match, ) # Add the callback to update the progress bar future.add_done_callback(lambda p: pbar.update(1)) # noqa : ARG005 # Wait for all the processes to finish executor.shutdown(wait=True) return @main.command() @click.pass_context @click.option( "-p", "--path", required=True, type=click.Path(exists=True, dir_okay=True, writable=True, path_type=Path), help="Path to save the files", ) @click.option( "-y", "--year", required=True, type=click.INT, help="Year to download RINEX SP3 files", ) @click.option( "-m", "--month", required=True, type=click.IntRange(1, 12), help="Month of year to download RINEX SP3 files", ) @click.option( "-d", "--day", required=True, type=click.IntRange(1, 31), help="Day of month to download RINEX SP3 files", ) def sp3(ctx: click.Context, path: Path, year: int, month: int, day: int) -> None: """Download SP3 files for the given year, month and day.""" # Create the downloader downloader = NasaCddisIgsSp3(logging=ctx.obj["verbose"]) # Create a datetime object for the given year, month and day dt = datetime(year, month, day) # Download the SP3 files downloader.download_from_datetime( time=dt, save_dir=path, ) return # ------------------------------------------ END ---------------------------------------------------------------------------------- # ------------------------------------------ Main Function --------------------------------- if __name__ == "__main__": main() # ------------------------------------------ END ---------------------------------