Source code for nowcast.workers.download_psy4

# Copyright 2016-2019 Doug Latornell, 43ravens
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""GoMSS NEMO nowcast worker to download Mercator Ocean PSY4 model fields.

A slice of the Mercator Ocean PSY4V1R2 daily average model product fields
are downloaded for use in the preparation of boundary condition files containing
u & v currents, sea surface height, salinity, and temperature.
"""
import logging
import os
import shlex
import subprocess

import arrow
from nemo_nowcast import NowcastWorker, WorkerError

NAME = "download_psy4"
logger = logging.getLogger(NAME)


[docs]def main(): """Set up and run the worker. For command-line usage see: :command:`python -m nowcast.workers.download_psy4 --help` """ worker = NowcastWorker(NAME, description=__doc__) worker.init_cli() worker.cli.add_date_option( "--psy4-date", default=arrow.now().floor("day"), help="Date for which to download the psy4 fields.", ) worker.run(download_psy4, success, failure)
def success(parsed_args): ymd = parsed_args.psy4_date.format("YYYY-MM-DD") logger.info( f"{ymd} psy4 daily average file download complete", extra={"psy4_date": ymd} ) msg_type = "success" return msg_type def failure(parsed_args): ymd = parsed_args.psy4_date.format("YYYY-MM-DD") logger.critical( f"{ymd} psy4 daily average file download failed", extra={"psy4_date": ymd} ) msg_type = "failure" return msg_type def download_psy4(parsed_args, config, *args): ## TODO: matlab script that makes boundary conditions files requires 1d ## per file, so download_psy4 needs to change to get n files instead of ## n days in one file if we want to run for more than 1d ymd = parsed_args.psy4_date.format("YYYY-MM-DD") logger.info( f"downloading psy4v1r2 daily average fields file for {ymd} run", extra={"psy4_date": ymd}, ) download_config = config["open boundaries"]["download"] user, password = os.environ["MOTU_CREDENTIALS"].split(":") min_lon, max_lon = download_config["lon range"] min_lat, max_lat = download_config["lat range"] min_depth, max_depth = download_config["depth range"] forecast_days = download_config["forecast days"] start_ymdhms = parsed_args.psy4_date.format("YYYY-MM-DD 00:00:00") end_ymdhms = parsed_args.psy4_date.shift(days=+forecast_days).format("YYYY-MM-DD 00:00:00") cmd = ( f'{download_config["motu client python"]} -m motu-client ' f"-u {user} -p {password} " f'-m {download_config["motu server"]} ' f'-s {download_config["motu service id"]} ' f'-d {download_config["dataset"]} ' f"-x {min_lon} -X {max_lon} -y {min_lat} -Y {max_lat} -z {min_depth} " f'-Z {max_depth} -t "{start_ymdhms}" -T "{end_ymdhms}"' ) cmd = " -v ".join((cmd, *(var for var in download_config["variables"]))) filename = download_config["file template"].format( yyyymmdd=parsed_args.psy4_date.format("YYYYMMDD") ) cmd = f'{cmd} -o {download_config["dest dir"]} -f {filename}' sanitized_cmd = cmd.replace(f"-u {user}", "-u ***").replace( f"-p {password}", "-p ***" ) logger.debug(f"running command in subprocess: {sanitized_cmd}") proc = subprocess.run( shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, ) try: proc.check_returncode() except subprocess.CalledProcessError: logger.error(f"motu-client failed: {proc.stdout}") raise WorkerError for line in proc.stdout.splitlines(): # Exclude download progress if " - " not in line and not line.endswith("%)"): # Strip leading "HH:MM:SS [ INFO]" logger.debug(line[17:]) checklist = {"psy4 date": ymd} return checklist if __name__ == "__main__": main() # pragma: no cover