From 8d52fcfaa35e24e1d7b9705976632c9ac173c2a4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 17:02:18 -0600 Subject: [PATCH] Update develop-ref after #2506 (#2512) * Feature 2065 v5.1.0 beta1 (#2066) * updated version number * added release notes * Update docs/Users_Guide/release-notes.rst Co-authored-by: John Halley Gotway --------- Co-authored-by: John Halley Gotway * updated version with -dev * adding sphinx design to 3 files so dropdown menus will work in the release notes. * fix version numbers for python requirements for building documentation * fixed tab vs spaces * Bugfix #2070 var list numeric order (#2072) * Adding files for jet and hera * added commented process list that was accidentally removed -- this is used if the pre-processing steps are needed * Bugfix #2087 develop docs_pdf (#2091) * Feature 2076 release dropdown menu (#2083) * test dropdowns * Update release-notes.rst Attempting to resolve WARNING * testing dropdowns * adding dropdown menus * testing dropdown remove from warning section * dropdown testing * dropdown menu tests * dropdown menus after the warnings section, the dropdown menu only has one space instead of the normal 2 spaces. If it has 2 spaces, it gets sucked into the warning section. * spaces with warning * no spaces for warning * Update release-notes.rst warning note has to be indented 1 space. Originally it was no spaces but then all of the dropdown menus end up in the warning message. If it's 2 spaces, as is normal, then the warning is indented, which is unnecessary. 1 space is slightly indented and keeps the dropdown menus separate. --------- Co-authored-by: jprestop * Bugfix #2096/#2098 develop - fix skip if output exists and do not error if no commands were run (#2099) * Feature 1516 use case mvmode (#2094) Co-authored-by: Tracy Hertneky Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> * Fix for Dockerfile smell DL4000 (#2112) Co-authored-by: Giovanni Rosa * Changed "PROJECT" to "CYCLE" ASSIGNMENT * Feature 2115 update use cases (#2133) * Bugfix #2082 develop regrid.convert/censor_thresh/censor_val (#2140) fix #2082 main_v5.0 regrid.convert/censor_thresh/censor_val (#2101) * Bugfix #2137 develop PointStat -obs_valid_beg/end (#2141) * Feature #2143 5.1.0-beta2 release (#2144) * update release guide steps with new info based on changes to GitHub web interface * update version for development towards rc1 release * Feature #1977 ARGO use case (#2148) Co-authored-by: j-opatz <59586397+j-opatz@users.noreply.github.com> * Feature develop cycle change (#2150) * change PROJECT ASSIGNMENT to CYCLE ASSIGNMENT * change PROJECT ASSIGNMENT to CYCLE ASSIGNMENT * change PROJECT ASSIGNMENT to CYCLE ASSIGNMENT * change PROJECT ASSIGNMENT to CYCLE ASSIGNMENT * change PROJECT ASSIGNMENT to CYCLE ASSIGNMENT * change PROJECT ASSIGNMENT to CYCLE ASSIGNMENT * Added paths to ignore --------- Co-authored-by: jprestop * Documentation: Update Truth Data instructions (#2154) * upgrade python to 3.10 for documentation builds to fix failured introduced by urllib3 (see https://github.com/urllib3/urllib3/issues/2168) * update workflow to update input test data to use branch from pull down or enter branch by hand if branch does not exist in dtcenter/METplus repo, e.g. if updating data for a PR coming from a fork * Bugfix #2161 develop PCPCombine additional field arguments in -subtract mode (#2162) * changed order of workflow event triggering info to more easily see the repository and commit sha that triggered the workflow * fix docker compose install and call -- needed due to new Alpine Linux release 3.18.0 that does not include docker-compose in the apk repository * Bugfix #2168 develop - StatAnalysis time shift (#2169) * Feature 1978 update pyreq doc (#2177) * Updating for 5.1.0 * Adding greater than or equal to signs * Feature 2106 release support (#2182) * Added a paragraph for Release Support Policy * Added a sentence about contacting the team through the METplus GitHub Discussions Forum. * Added Release Support Policy info * Per #2159, modify instructions to reflect that we only want a coordinated release for the official releases and updates to the coordinated release section for the bugfix releases. (#2183) * Feature 2147 workflow doc (#2185) * Add new images for github workflow * Added PR section * Modified the Find the GitHub Issue to be Find or Create a GitHub issue * Trying out image keyword compared with figure keyword * Trying out various widths * Added new figures * Reverting to figures from images after modifying figures * Adding the old images which are better quality * Trying out new indention * Working on formatting again * Reducing image widths * Update docs/Contributors_Guide/github_workflow.rst Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> * Update docs/Contributors_Guide/github_workflow.rst Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> * Update docs/Contributors_Guide/github_workflow.rst Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> * Update github_workflow.rst --------- Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> * added scripts to create new conda environment for PANDA-C use cases * Bugfix #2189 develop - spaces in complex thresholds (#2191) * added release notes for completed issues for rc1 * Feature 2011 tci from cesm fluxnet2015 netcdf (#2192) Co-authored-by: Mrinal Biswas Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> * Bugfix #2179 develop TCPairs fix -diag argument (#2187) * sort list of files to make command more readable and make logic more easily testable * fix unit test to expect alphabetical order of files * Feature #2197 MODE new multi-variate options (#2203) * added to release notes * added release notes for other items completed for rc1 release * Feature #1626 TCDiag Wrapper (#2201) * Feature #1610 first round of SonarQube fixes (#2200) * Feature #2195 create v5.1.0-rc1 release (#2204) * Update version for development towards official release * updated script to use metplotpy as base and install pygrib because conda was failing trying to install matplotlib in Docker for some strange reason * Feature 2188 use case panda c (#2202) * added first use case, need to finish docs and add to list * added documentation files, 3 new cases * added 5th use case, docs * final use case, corrected paths for output * Update GridStat_fcstGFS_obsERA5_lowAndTotalCloudFrac.py * removed chars, added space to last section * turn off 5/6 new air quality and comp use cases because they are causing the disk to fill up in the automated tests and only 1 is needed to test the new behavior. Reordered use case groups to be alphabetical * disabled other new air quality use case because the disk is still filling up from this case * Feature 2136 cross spectra (#2208) * per #2212, continue instead of return so other forecast leads will not be skipped * Feature #2210 MODE multi-variate variable rename (#2211) * Bugfix diff tests (#2217) * added change from NCEP produtil that was somehow not included in the changes pulled from their repo before starting SonarQube work * Feature #2228 v5.1.0-rc2 release (#2229) * update version after rc2 release to note development towards official 5.1.0 release * Feature #2188 move PANDA-C cases to clouds category and fix automated tests (#2237) Co-authored-by: j-opatz * Feature 2198 use case amdar pbl (#2206) Co-authored-by: Daniel Adriaansen Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> * Bugfix #2235 rename multivar_itensity to multivar_intensity_flag (#2236) * Feature #2230 MvMODE usecase doc updates (#2239) This updates the use-case documentation to go along with the multivariate MODE enhancements. * combine release notes from development releases for 5.1.0 release * fix indentation to prevent incorrect nesting of drop down menus * Bugfix #2241 Create directory containing -out_stat file (#2242) * Enhance diff logic to control decimal precision to prevent failures (#2243) * Bugfix #2245 use unique run ID to name logger instance (#2247) * per #2245, add METplusConfig class function that is called when object is deleted to close log handlers. This prevents OSError: [Errno 24] Too many open files from running all pytests * Feature #1626 TCDiag updates to wrapper and basic use case (#2248) Co-authored-by: Jonathan Vigh * move new use case into another group * Bugfix #2244 develop fix diff tests (#2254) * skip diff for specific png images that produce diffs occasionally but look the same visually * add 2 more keywords for use cases that occasionally flag small, unnoticeable diffs in png images * Feature #2253 update tests for diff_util (#2256) Co-authored-by: root * Feature #1974 Documentation: update coding standards section (#2260) * Feature #2253 conftest fixture to set pytest tmpdir (#2261) * Feature #2151 Documentation: Add quick search keywords METplotpy/calcpy use cases (#2259) * Feature #2138 CI enhance MET Docker tag override (#2258) * Updating development instructions. * fixed typo * fixed another typo * Feature #2207 Documentation - Updates to Contributor's Guide (#2263) Co-authored-by: Dan Adriaansen * Feature develop update install files (#2266) * Updating installation files * Removing run_commands.sh * Updated the file to add a MINICONDA_PATH * Adding files for jet * Adding orion file * Removing beta references * Corrected met version * Adding files for WCOSS2 machines * Removing rc1 from acorn file * Removing beta1 * Bugfix #1853 develop - PointStat don't require mask variables to be set (#2262) * update version of certifi to match auto-generated dependabot PR #2267 * feature #2253 more tests for diff_util.py (#2264) * update versions of METplus components for the next official release * updated release notes for 5.1.0 release * removed duplicate entries in release notes * Added EC2 instance recipee with S3 mounting ability (#2269) * Updating the Subsetting Tests by Marker section (#2272) * update release date for 5.1.0 release (#2276) * update version for development towards 6.0.0-beta1 release * added new use case that was missing * Bugfix #2279 develop - buoy station file from 2022 (#2280) * Feature 2253 series analysis tests (#2277) * Fix typo in pull_request_template.md * Make code coverage report available (#2287) * Use updated dtcenter/metplus-action-data-update tag that fixes bug that causes GHA disk to exceed capacity when too many data volumes are created. Use specific commit of coveralls python action to ensure it will not change * removed climatology keyword from use cases that aren't relevant that were accidentally added with PR #1984 * update readme with current information * Feature #2282 coord_release_docs (#2288) Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> * continue workflow if coveralls step fails -- this typically happens on a pull request from a fork because the authentication fails * Feature 2253 system util tests (#2297) * Feature #2294 LSR use case (#2295) * Feature 2253 run util tests (#2307) * Release Guide - remove beta/rc tags/releases (#2309) * Add 'component: repository maintenance' label. Already ran the script to push this change and the NOAA OAR reporting label to all the METplus repos. * Hotfix for labels, adding a new one for 'component: input data' and also fixing the get_lablels.sh to search for up to 200 existing labels. Also work on the log messages. * Fix typo in comment * Feature #2283 time looping consolidation (#2311) Co-authored-by: John Halley Gotway * New issue template: Update Truth (#2332) Co-authored-by: John Halley Gotway * feature #2253 tests for run_util, 'Usage' bugfix (#2313) * Feature #2338 Debian 12 Conda environments (#2341) Co-authored-by: John Halley Gotway * Feature 1488 usecase satwinds (#2324) Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> * Feature #2283 include times (#2345) Co-authored-by: John Halley Gotway * feature #2253 tests for config_validate, mock logger in conftest (#2320) * Feature #2299 / #2310 Remove deprecated MET config env vars and TCMPRPlotter (#2347) Co-authored-by: John Halley Gotway * remove MODEL and OBTYPE to use defaults from MET config * Feature #2348 v6.0.0-beta1 release (#2351) * update version for development towards 6.0.0-beta2 release * copy libGL and libEGL files into docker image to prevent errors with geovista python package * run use that uses geovista to test * Feature #2156 release_acceptance_testing (#2352) * feature #2253 print error logs from conftest (#2358) * feature #2253 met_db_load tests (#2355) * Rename 5.1.0.lua_wcoss2 to 6.0.0.lua_wcoss2 * Update and rename 5.1.0_acorn to 6.0.0_acorn * Update 6.0.0_acorn * feature #2253 add tests for gfdl_tracker (#2354) Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> * Create 6.0.0_gaea * Update and rename 5.1.0_hera to 6.0.0_hera * Feature #2156 release_acceptance_testing take2 (#2361) Co-authored-by: lisagoodrich <33230218+lisagoodrich@users.noreply.github.com> * Feature #2329 Docker info in Installation Chapter (#2366) * feature_2253_extract_tiles_tests (#2368) * Feature 2253 tc pairs tests (#2369) * Feature 2253 tc csv writer (#2373) * update requirements for building docs to get around build failure where python packages required to build RTD have disappeared from the automatically generated commands from RTD * fix ReadTheDocs requirements to include pillow which is a dependency of sphinx-gallery: see https://blog.readthedocs.com/defaulting-latest-build-tools/ for more info on why this was necessary * Feature #2340 TCDiag one_time_per_file_flag (#2374) * Update and rename 5.1.0_jet to 6.0.0_jet * Added libssh * prune docker files before running use cases to prevent running out of disk space when running use cases, ci-run-all-diff * Feature 2253 command builder tests (#2378) * Feature 2253 series analysis test (#2380) * Feature 2253 py embed test (#2379) * ignore cyclone plotter from code coverage report because it will be replaced with METplotpy logic * Feature 898 headers (#2389) * changing _ to - for header consistency * changing _ to - for header consistency * updating all headers for consistency * updating all headers for consistency and adding spacing The spacing doesn't seem to be required but it is the convention that we follow for headers. * updating all headers for consistency * updating headers for consistency and adding capital letters to headers * Using the overline ### to keep index consistent with other indexes * updating all headers for consistency * update requirements for building docs to get around build failure where python packages required to build RTD have disappeared from the automatically generated commands from RTD * updating all headers and some spacing for consistency * updating headers for consistency * changing to ### for consistency * Per #898, fixed the headers for the Release Guide part, chapters, and sections. * Duplicating changes in develop branch for requirements.txt file * updating headers * Per #2669, updated header formatting to resolve errors * Per #2669, udpating header * Per #2669, udpating headers * Per #2669, udpating header * Per #2669, updated header formatting * Per #2669, update header formatting * updating headers * Per #898, removed space in front of title * Capitalizing Please * changing to just italics to match standard formatting * indenting for consistent formatting * fixing italics again * changing from note to warning for consistency * updating headers, adding some capitalizing to the headers * fixing typo Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> * This file was committed but never updated or used Per Minna, ok to delete. * Restructuring table of contents to make it more clear which guides are for users and which are for contributors * fixing formatting for clairity Co-authored-by: Julie Prestopnik --------- Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> Co-authored-by: Julie Prestopnik * Feature #2349 upgrade instructions for deprecated MET config files (#2386) * Feature 2123 di doc update (#2392) Co-authored-by: Tracy * change log to list name of config variable , e.g. GRID_STAT_CONFIG_FILE, to easily see which variable should be removed * Feature 1667 doc conventions (#2397) * New additions based on the old branch feature_1667_updating_overview * Moving the release-notes reference label * Added label for METplus_glossary for use in Documentation conentions section. * Adding images for the Documentation Conventions section * Modifying wording and testing formatting in Internal Links section * Second take on formatting * Third attempt at formatting * Fourth attempt at formatting * Modified wording, sections, and formatting * Minor modifications * Added period * Changed Pretty Table to PrettyTable * Modify informationg about converting an existing table and adding images * Resolving errors * Reformatting * Moving placement of reference label * Attempting to fix table title * Fixed incorrect alignment * Made changes based on Lisa's suggestions * Made changes based on Lisa's suggestions * Made corrections * Made corrections * Per #1667, fixing typos * Per #1667, corrected text --------- Co-authored-by: Julie Prestopnik * Feature #2377 Log to terminal only (#2398) * Update conda envs to use conda-forge only (#2402) * rearrange MET config env var tables for GridStat so they are in the order that they appear in the wrapped MET config file * use mamba instead of conda and update version of netcdf python package used to 1.6.2 * skip s2s_mid_lat WeatherRegime use case that produces different results often * updated version of xesmf because <0.7.1 does not work with mamba * per #2412, fix bug in GenVxMask to put quotes around argument so a grid specification string with spaces will be an accepted value * downgrade version of esmf package to fix bug described in https://github.com/pangeo-data/xESMF/issues/246 * Feature #2219 SeriesAnalysis multiple input files (#2408) * Adding 3 new requestors to the list of common_labels.txt for NOAA/NHC, CSU/CIRA, and Australian BOM ci-skip-all * Feature 2405 match tables2wrapper (#2416) Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> * per #2423, follow symbolic links when traversing directories to find files within a time window, ci-run-all-diff * Feature #2252 WaveletStat wrapper (#2427) Co-authored-by: j-opatz <59586397+j-opatz@users.noreply.github.com> * add WaveletStat use case to group and temporarily disable TCDiag use case because changes to the wrapper are needed to fix it after changes to the MET tool were merged * update version number for beta2 release (#2431) * update version for dev towards beta3 * Feature #2371 Embed use case upgrade demo video into upgrade instructions (#2444) * fix failing use case tests -- install python packages dateutil and requests via apk instead of pip because the pip commands began failing -- see PEP668 https://peps.python.org/pep-0668/ -- also changed scripts to create conda environments for use case tests to install all packages in a single call to mamba instead of individual calls * remove commands to install geovista from source because it is now installed from conda * Feature #1989: Add OMI use case (#2457) Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> * Feature #2432 TCDiag new config changes (#2453) * move medium range 10 use case into group with 3-5 to speed up runs * Feature #2334 land_mask (and topo_mask) in PointStat (#2456) * added use cases with pygrib * Feature #2430 TCPairs consensus.diag_required and consensus.diag_min_req (#2439) * Quickfix cloud use case desc imgs (#2464) * added pics, updated desc * add last two imgs * Fixing spelling and capitalization * Feature 2454 doc overview conv (#2471) * adding documentation in different sections * adding grid table section * fixing links * grammar updates * Per #2454, updated sections and wording. * Per #2454, added a period to the end of a sentence. * Per #2454, fixing formatting * Per #2454, updating wording * adding a section for line breaks in a table * adding :code: information * trying to fix warning * take 2 * take 3 or 4 * maybe fixed * updating link * fixing web link again * web link saga continues * Changed "ReadTheDocs" to "Read the Docs" * Updated "main_v" references to be "main_v12.0" * Removed references to main_v*, replacing with raw RST It is not maintainable to have links to branches which will become old. Since we can avoid it by adding the raw RST in the documentation, I have removed all references to main_v* in favor of placing the raw RST in the documentation. * Modified the "Code in a Paragraph" section * Reworded for consistency within the document * Added back the link for Sphinx code blocks --------- Co-authored-by: Julie Prestopnik * add argument to workflow dispatch event so that MET DockerHub repo used for tests can be easily overridden to test changes in a MET PR before merging * Feature dtcenter/MET#2796 GHA Node20 deprecation warnings (#2473) * per dtcenter/MET#2796, update versions of actions to prevent deprecated node warnings in GHA runs * change arguments to workflow dispatch so they are no longer required -- these are not needed to be set when triggering by hand through the web interface * Feature dtcenter/MET#2796 develop - Fix error log artifact creation (#2475) * updated version of pillow to fix security vulnerability alerted by dependabot in PR #2477 * remove docker image after runtime image is created from metplus image and conda env image * turn on use case to test image removal * prune images if image tag doesn't exist -- it appears that if the image is built on the fly (when PR is coming from fork) then the tag exists, but if not, the image tag is set to * support commands that must run in the shell to see if || will work in docker image pruning step * try to fix image removal * Feature 2383 use case sat alt (#2480) * new docs, files for use case * new files * updating to run use case * updated python libraries, changed test env * trying new point logic * added to script for nan removal * redid Python script to take adv of new MET ability for nans * Update run status * removed unused settings * run image prune commands separately * changed shell back to false * split up use case groups so the same envs are used by a group to see if that resolves the disk space issues * turn off use cases * feature 2253 fix empty pytest logs (#2485) * added more commands to free up disk space as suggested in https://github.com/apache/flink/blob/master/tools/azure-pipelines/free_disk_space.sh, ci-run-all-cases * Feature 2406 redo usecase rrfs (#2488) * issue #2406 RRFS use case files * issue #2406 added usecase to tests * Issue #2406 added metplotpy and metcalcpy as dependencies * Feature #2460 allow missing input (#2493) * changed template to use datetime format that works on MacOS * update logic to only write a file list file if there are more than 1 files, updated unit tests to match new behavior, added exception handling to series analysis to prevent crash if file does not exist * use getraw instead of getstr to prevent crash if providing a filename template tag to override a config variable on the command line * Add optional argument to subset file function to always write a file list text file even if there is only 1 file found. Use this argument in UserScript wrapper so that the environment variables that contain paths to file list files are consistent in format for use in user scripts * enhanced function to support different output variable types * removed the need for overriding clear function in specific wrappers and added optional argument to skip clearing input file list * clean up formatting * per #2460, start to implement logic to prevent errors when some input files are not found * isolate logic to find input files into find_input_files functions. clean up those functions to return boolean instead of sometimes returning None or a list of files to be consistent * remove python embedding checks because MET is now smart enough to determine if a python script is used with always setting file_type * turn on use cases to test error handling * merge artifacts * run only failed cases * always run merge step * run on a case that will succeed to test error log merge step * only run error log merge step if there were 'Save error logs' jobs that succeeded * run cases that will fail * fix condition to merge error logs * run group that will succeed but have diffs - check error logs doesn't fail * testing - add use case group that will succeed but will cause diffs becaus there is no truth data - to confirm that the error log merge step behaves properly in this case * run 3 jobs, 2 should error, to confirm that error_logs is created properly * repeat diff no error test but with * per dtcenter/MET#2796, fix error log artifact creation by merging error logs if any of the 'Save error logs' steps ran successfully * run test to confirm diff does not cause merge error logs to fail * Revert "run test to confirm diff does not cause merge error logs to fail" This reverts commit ff2d1cac57c431a047ee250e9dae9b0a813a78ba. * run test to confirm error logs are merged properly when 2 use case groups have errors * try checking output variable as string instead of boolean * Revert "run test to confirm error logs are merged properly when 2 use case groups have errors" This reverts commit 8106666a73685e654e0146d4fed56f2382f1bfc7. * run test again * test again * move check for error logs for shell script and use github env vars * Revert "run test again" This reverts commit 7a0a99c6e7031c5dafb1177d4b4ca3f32a999dac. * break 2 use cases to test that error logs are still created properly * checkout repo to get script used to merge error logs * Revert "break 2 use cases to test that error logs are still created properly" This reverts commit cb6d0b46db353b4b4709183be2fe7e5ce64ff5ff. * test merge error log again on no error diff run * fix script * move merge error logic back to workflow * break 2 use cases to test that error logs are still created properly * Revert "break 2 use cases to test that error logs are still created properly" This reverts commit 82aa0e11096aace3ccc2c79cd631533fc6426900. * remove testing use case group * Revert "remove python embedding checks because MET is now smart enough to determine if a python script is used with always setting file_type" This reverts commit de3b4b03a45bb871c71e770ff9e602739d6b63d5. * clean up lines * update logic to check that python embedding is set up properly to only try to set file_type automatically if it is not already set and if the wrapper is a tool that supports multiple input files via python embedding (which require file_type to be set). also changed error if not set properly to warning and use PYTHON_NUMPY as a default * remove run_count increment before run_at_time_once - set closer to find_input_files so run count and missing input count are consistent * return boolean from find_input_files function to be consistent with other functions * per #2460, warn instead of error if missing inputs are allowed, track counters for number of runs and missing inputs * per #2460, added check to report error if allowed missing input threshold is met * run clear before running plot_data_plane * removed test group * report warning instead of error if ALLOW_MISSING_INPUTS is True * cleanup * change function to pytest fixture so it can be used by other test scripts * update ascii2nc test to process more than 1 time to ensure commands are built properly for each run * add unit tests to ensure missing input file logic works properly for ascii2nc and grid_stat * set variable to skip RuntimeFreq logic to find input files to prevent duplicate increment of run_count -- these will be removed when the wrapper has been updated to find files using RuntimeFreq logic * remove unneccesary error checking * cleanup * call function to handle input templates that need to be handled separately for each item in the comma-separated list (for UserScript and GridDiag only) * add time_info to ALL_FILES dictionaries to be consistent with other wrappers * clean up logging for reporting error when missing inputs exceeds threshold * added function to get files for a single run time to be consistent with other functions * skip increment of run_count when FIND_FILES=True and RuntimeFreq input file logic is skipped to prevent duplicate increments * added empty test files * remove redundant variables * view warnings on a failed test run * add more empty test files * added unit tests for missing input logic * remove MANDATORY setting for EnsembleStat and GenEnsProd and instead pass mandatory argument to call to find model files so warnings/errors are properly displayed for other inputs * cleanup * remove allow missing input logic from ExtractTiles wrapper * added functions to parse template/dir variables from config, removed explicit calls to read those variables from GridStat * remove error if more labels than inputs are provided (for UserScript and GridDiag only) -- extra labels will just be ignored * added required boolean for input templates * per #2460, change warning messages to debug when checking a list of DA offsets since it is common that a given offset will not always be found in the files * added tests for missing input logic for many wrappers * cleanup * fix increment of number of runs * skip missing input logic * change how required is handled for input templates * warn instead of error if missing input is allowed * remove increment of missing input counters because it is handled in RuntimeFreq * check status of input files and increment counters in overridden run_once_per_lead. remove increment of missing input counters because it is handled in run_once_per_lead * added unit tests for missing input logic * skip missing input logic * cleanup * cleanup, use fixture for tests, add unit tests for missing input, bypass missing input logic on wrappers that don't need it * removed file that is not needed * added unit tests for pb2nc to test -valid_beg/end arguments and changes to properly support any runtime frequencies * warn instead of error if allowing missing inputs * cleanup * implement changes to properly support all runtime frequencies for pb2nc. previously all files that match a wildcard will be used instead of selecting only files that fall within the specified time range. some functions moved into pb2nc wrapper will eventually be moved up so that they are used by all wrappers to be consistent * added unit tests that will fail until wrapper is updated * replace functions in RuntimeFreq wrapper used to find input files so they can be used by all wrappers, updated ioda2nc wrapper to find input files properly to fix tests * cleanup * removed mtd version of get_input_templates and added logic to RuntimeFreq's version to get the same behavior * added unit tests for MTD missing input checks * per #2491, add release notes for beta3 * Feature #2491 v6.0.0 beta3 (#2495) * update version for beta3 release * fixed typos in release notes * update version to note development towards beta4 release * Per suggestion from @JohnHalleyGotway, create intermediate branch for updating truth data to avoid branch protection rules. I added a step to delete the intermediate branch locally if it exists to prevent conflicts with the update * added quotes to prevent error in echo caused by parenthesis * fix incorrect command * Revert "fix incorrect command" This reverts commit e7dffb6b0b351ab1b4bca5b563c1f5beef7737a9. * Revert "added quotes to prevent error in echo caused by parenthesis" This reverts commit c1cb3c4f0d7851bea720a50fac6011cd381017dc. * Revert "Per suggestion from @JohnHalleyGotway, create intermediate branch for updating truth data to avoid branch protection rules. I added a step to delete the intermediate branch locally if it exists to prevent conflicts with the update" This reverts commit 525809dc3bd73ace969b046062967796035f4d86. * Hotfix: Allow symbolic link to run_metplus.py to run (#2500) * Adding use case tests * Changing test environment * Testing environment changes * Documentation update * Updating Documentation * Updating documentation for disk space failure * Added new use case category * Fixing use case test * Fixing bug in use case file * Testing s2s after data removal * add back use cases that were accidentally removed * fix incorrect use case added * Setting tests to false for merge * Testing for old use cases * Setting tests to false for merge * update tests to update develop data -- modified commands to create new use case category directory if it does not already exist, move step to remove old data to be completed just after new data is copied to vX.Y --------- Co-authored-by: j-opatz <59586397+j-opatz@users.noreply.github.com> Co-authored-by: John Halley Gotway Co-authored-by: j-opatz Co-authored-by: metplus-bot <97135045+metplus-bot@users.noreply.github.com> Co-authored-by: Lisa Goodrich Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> Co-authored-by: Julie Prestopnik Co-authored-by: lisagoodrich <33230218+lisagoodrich@users.noreply.github.com> Co-authored-by: Tracy Hertneky <39317287+hertneky@users.noreply.github.com> Co-authored-by: Tracy Hertneky Co-authored-by: Giovanni Rosa Co-authored-by: Giovanni Rosa Co-authored-by: Dan Adriaansen Co-authored-by: mrinalbiswas Co-authored-by: Mrinal Biswas Co-authored-by: Christina Kalb Co-authored-by: jason-english <73247785+jason-english@users.noreply.github.com> Co-authored-by: Jonathan Vigh Co-authored-by: John Sharples <41682323+John-Sharples@users.noreply.github.com> Co-authored-by: root Co-authored-by: Hank Fisher Co-authored-by: reza-armuei <144857501+reza-armuei@users.noreply.github.com> Co-authored-by: Tracy Co-authored-by: Mallory Row Co-authored-by: bikegeek <3753118+bikegeek@users.noreply.github.com> --- .github/parm/use_case_groups.json | 10 +- docs/Contributors_Guide/add_use_case.rst | 82 ++++++---- docs/_static/s2s-zonal_means.png | Bin 26841 -> 0 bytes ...Script_fcstGFS_obsERA_StratosphereBias.png | Bin 0 -> 68554 bytes ...cript_fcstGFS_obsERA_StratospherePolar.png | Bin 0 -> 23362 bytes .../s2s_stratosphere/README.rst | 3 + ...Script_fcstGFS_obsERA_StratosphereBias.py} | 72 +++++---- ...Script_fcstGFS_obsERA_StratospherePolar.py | 151 ++++++++++++++++++ internal/tests/use_cases/all_use_cases.txt | 11 +- ...serScript_obsERA_obsOnly_Stratosphere.conf | 51 ------ .../meridonial_mean.py | 82 ---------- .../meridonial_mean.yaml | 2 - ...cript_fcstGFS_obsERA_StratosphereBias.conf | 148 +++++++++++++++++ .../README | 4 +- .../bias_plot_driver.py | 74 +++++++++ .../read_met_axis_mean.py | 60 +++++++ .../zonal_mean_driver.py | 81 ++++++++++ ...ript_fcstGFS_obsERA_StratospherePolar.conf | 130 +++++++++++++++ .../README | 9 ++ .../bias_rmse_plot_driver.py | 90 +++++++++++ .../polar_t_u_driver.py | 112 +++++++++++++ ush/run_metplus.py | 18 +-- 22 files changed, 974 insertions(+), 216 deletions(-) delete mode 100755 docs/_static/s2s-zonal_means.png create mode 100644 docs/_static/s2s_stratosphere-UserScript_fcstGFS_obsERA_StratosphereBias.png create mode 100644 docs/_static/s2s_stratosphere-UserScript_fcstGFS_obsERA_StratospherePolar.png create mode 100644 docs/use_cases/model_applications/s2s_stratosphere/README.rst rename docs/use_cases/model_applications/{s2s/UserScript_obsERA_obsOnly_Stratosphere.py => s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias.py} (56%) create mode 100644 docs/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar.py delete mode 100644 parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere.conf delete mode 100755 parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere/meridonial_mean.py delete mode 100644 parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere/meridonial_mean.yaml create mode 100644 parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias.conf rename parm/use_cases/model_applications/{s2s/UserScript_obsERA_obsOnly_Stratosphere => s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias}/README (70%) create mode 100755 parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/bias_plot_driver.py create mode 100644 parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/read_met_axis_mean.py create mode 100755 parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/zonal_mean_driver.py create mode 100644 parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar.conf create mode 100644 parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/README create mode 100755 parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/bias_rmse_plot_driver.py create mode 100755 parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/polar_t_u_driver.py diff --git a/.github/parm/use_case_groups.json b/.github/parm/use_case_groups.json index 5684f4f2cd..6963d1127e 100644 --- a/.github/parm/use_case_groups.json +++ b/.github/parm/use_case_groups.json @@ -194,11 +194,6 @@ "index_list": "5", "run": false }, - { - "category": "s2s", - "index_list": "6", - "run": false - }, { "category": "s2s_mid_lat", "index_list": "0-2", @@ -224,6 +219,11 @@ "index_list": "4", "run": false }, + { + "category": "s2s_stratosphere", + "index_list": "0", + "run": false + }, { "category": "short_range", "index_list": "0", diff --git a/docs/Contributors_Guide/add_use_case.rst b/docs/Contributors_Guide/add_use_case.rst index 2deea9dba5..eb6a4163e9 100644 --- a/docs/Contributors_Guide/add_use_case.rst +++ b/docs/Contributors_Guide/add_use_case.rst @@ -56,6 +56,7 @@ one of the following: * s2s (Subseasonal to Seasonal) * s2s_mid_lat (Subseasonal to Seasonal: Mid-Latitude) * s2s_mjo (Subseasonal to Seasonal: Madden-Julian Oscillation) +* s2s_stratosphere (Subseasonal to Seasonal: Stratosphere) * short_range (formerly convection_allowing_models) * space_weather * tc_and_extra_tc (Tropical Cyclone and Extratropical Cyclone) @@ -150,18 +151,24 @@ Use Case Rules - The use case should be run by someone other than the author to ensure that it runs smoothly outside of the development environment set up by the author. -.. _memory-intense-use-cases: +.. _actions-failure-use-cases: -Use Cases That Exceed Github Actions Memory Limit -------------------------------------------------- +Use Cases That Cannot be Run in GitHub Actions +---------------------------------------------- -Below is a list of use cases in the repository that cannot be run in Github -Actions due to their excessive memory usage. They have been tested and -cleared by reviewers of any other issues and can be used by METplus users in -the same manner as all other use cases. +Below is a list of use cases in the repository that cannot be run in GitHub +Actions due to either excessive memory or excessive disk space usage. They have +been tested and cleared by reviewers of any other issues and can be used by METplus +users in the same manner as all other use cases. +Use Cases that Exceed GitHub Actions Memory Limit +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - *model_applications/marine_and_cryosphere/GridStat_fcstRTOFS_obsGHRSST_climWOA_sst* +Use Cases that Exceed GitHub Actions Disk Space +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- *model_applications/s2s/UserScript_fcstGFS_obsERA_StratospherePolar* + .. _use_case_documentation: Document New Use Case @@ -790,9 +797,11 @@ environment, potential reasons include: - Referencing variables set in the user's configuration file or local environment - Memory usage of the use case exceeds the available memory in the - Github Actions environment + GitHub Actions environment +- Disk space usage of the use casee exceeds the available space in the + GitHub Actions environment -Github Actions has +GitHub Actions has `limited memory `_ available and will cause the use case to fail when exceeded. A failure caused by exceeding the memory allocation in a Python Embedding script @@ -802,9 +811,15 @@ memory profiler to check the Python script's memory usage. If the use case exceeds the limit, try to pare down the data held in memory and use less memory intensive Python routines. +Additionally, GitHub Actions has limited disk space available. The use case will +fail if the data files exceed the available disk space. If this is the case, consider +removing any unneeded variables from the data files, reducing the time steps run, or +creating a new use case category to keep file sizes down for each group. + If memory mitigation cannot move the use case’s memory usage below the -Github Actions limit, -see :ref:`exceeded-Github-Actions` for next steps. +GitHub Actions limit or data cannot be reduced further to fit inside +the available disk space +see :ref:`exceeded-GitHub-Actions` for next steps. Verify that the use case ran in a reasonable amount of time ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -859,19 +874,22 @@ processed in the automated tests. In **ci_overrides.conf**, set:: OBS_VAR1_THRESH = gt0, lt10.0 -.. _exceeded-Github-Actions: +.. _exceeded-GitHub-Actions: -Use Cases That Exceed Memory Allocations of Github Actions ----------------------------------------------------------- +Use Cases That Cannot be Run in GitHub Actions +---------------------------------------------- If a use case utilizing Python embedding does not run successfully in -Github Actions due to exceeding the memory limit and memory mitigation -steps were unsuccessful in lowering memory usage, please take the following steps. +GitHub Actions due to exceeding the memory limit and memory mitigation +steps were unsuccessful in lowering memory usage, or if a use case does +run successfully in GitHub Actions due to exceeding available disk space +and the data cannot be further pared down, please take the following steps. -- Document the Github Actions failure in the Github use case issue. +- Document the GitHub Actions failure in the GitHub use case issue. Utilize a Python memory profiler to identify as specifically as possible - where the script exceeds the memory limit. -- Add the use case to the :ref:`memory-intense-use-cases` list. + where the script exceeds the memory limit (if the failure is due to exceeding + the memory limit). +- Add the use case to the :ref:`actions-failure-use-cases` list. - In the *internal/tests/use_cases/all_use_cases.txt* file, ensure that the use case is listed as the lowest-listed use case in its respective category. Change the number in front of the new use case to an 'X', preceded @@ -882,13 +900,13 @@ steps were unsuccessful in lowering memory usage, please take the following step - In the *.github/parm/use_case_groups.json* file, remove the entry that was added during the :ref:`add_new_category_to_test_runs` for the new use case. This will stop the use case from running on a pull request. -- Push these two updated files to the working branch in Github and +- Push these two updated files to the working branch in GitHub and confirm that it now compiles successfully. - During the :ref:`create-a-pull-request` creation, inform the reviewer of - the Github Actions failure. The reviewer should confirm the use case is + the GitHub Actions failure. The reviewer should confirm the use case is successful when run manually, that the memory profiler output confirms that - the Python embedding script exceeds the Github Actions limit, and that - there are no other Github Actions compiling errors. + the Python embedding script exceeds the GitHub Actions limit, and that + there are no other GitHub Actions compiling errors. .. _create-a-pull-request: @@ -979,7 +997,9 @@ Paths may need to be adjusted. to_directory=${METPLUS_DATA_TARFILE_DIR}/v${METPLUS_VERSION}/model_applications/${METPLUS_USE_CASE_CATEGORY} echo $to_directory - ls $to_directory + ls $to_directory || echo CREATING $to_directory && mkdir -p $to_directory + +Note: If the use case is being added to a new use case category, the above command will create the directory for the new category if it does not already exist. **OR** @@ -997,6 +1017,13 @@ After verifying the directories are correct, copy the files:: cp -r $from_directory $to_directory/ +Remove old data (if applicable) +""""""""""""""""""""""""""""""" + +If the pull request notes mention an old directory path that should be removed, +please remove that directory from the next release version directory (vX.Y). +Be careful not to remove any files that are still needed. + Handle existing tarfile in vX.Y """"""""""""""""""""""""""""""" @@ -1026,13 +1053,6 @@ version**, then simply remove the tarfile link:: **CONDITION 3: IF the sample data tarfile for the category does not exist** (because it is a new use case category), continue to the next step. -Remove old data (if applicable) -""""""""""""""""""""""""""""""" - -If the pull request notes mention an old directory path that should be removed, -please remove that directory. Be careful not to remove any files that are -still needed. - Create the new sample data tarfile """""""""""""""""""""""""""""""""" diff --git a/docs/_static/s2s-zonal_means.png b/docs/_static/s2s-zonal_means.png deleted file mode 100755 index 3e5ab96dc491306227d6acb7dc71062a5734858b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26841 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

6iwz1ux-INc2FaXv}R>^It)Q&Pnu93|+ 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

M3uZ9rZI<&Ob_0 zBjbwnz(B#(x^z6u{>5XN`IvO#)4R&B8)T@rEsQ@v5qiuT$eAa&wieFa17Y);%6u1iv#(AHrpZgU#j^e_~kd zCzh---s!N=K#4yd#f3Z-6%bz_hOdzwl>?3t|ucPg7%~| zt@Z30e^+PoqKicV*U~b35ALjbzrWNlFhfOY4|&W_qDbC zySvN14o;~QCd%8&C(SC#bub)%c-#U<8732kNz#|%Zk*r}DH<*+SiaMelLuVYjNWZr$+ZylT0Bj-_p&BkwJ! zMR;6{69Bdok9F#EG54#Z`eQ>)k0dmhC9qL`JM%lom>TH}xK`|nqV|(0rvB9Ih{U{G zHI$BgJW}_+SaF(p)f{yWINo_04Ih zEi76IxYRw+SushNXS%i-e+<{#@H$L25^QWN?GZ-;0^(-td{fuQ3QjLbu|*tzaONXz z%X9E?U^CtM}iuX?&sA zz{AFfy^pIc1Nl6U4a>0|`T31g({f55sf)Vv&p7c33TmypCBo_iVSgR{!#UpLC63;# z%Z}8-nfx(jIB95cFg?gDSK;*g@%qMw#o=V7khnnI4?|KXxISQReO#<%7Pm~E@Y36} zZKf6dx3qhLajO6M1fHOoOxIEAeeK>BG0w7LY>w;w>m^ z7C?661$Ghmcox9Tw?Tm&&xOa@rqEllH}Zd8K&BH^<9f zK@%1dORu->rRj^PY}W?TJ3j+M^74Y{{H(A1&367^qpb2xt$Kgc`pvQ!TfoZMT{e6gROXQ!f%T*DU%4W59^=dq*#&z$GsVl0Nrl@XGH7U!zD0d~vxx*(Y}Ano!& zS0#Jsf4dIDpJ+KMEbhJH;dz|69S3>U4EC87#Xh~O+ULg?j1&bL!O@x>4gHYWr38tB zbM?N_*9ZbD9$m6Zj+XVyzK1C$$ov+6z2Pj>`ACg)SC43D8eOkly}GcT73c+@{FTQO zDx6INg}>LYK2y{OPg}*)GjU{&d3~)f_)VpCeZt7x@hyGupJ}6NAPox?ZMR%pgrN0C zq##IY1%zhYg5OVSfJcL7=uX1I@*waH0Fdn8aG3wg=U)<6XVVua>t2LG`IhX9D>}mS zLk0I~+z*dFRJ>JR-(Gw#xA${cQO27-9a0>`9J{N7_c(%M)2X^G6?`T$V|$2$!DvgAu+VvRRv{SX^IjHBf$id4VNqv zZ;&u&J`>uYp!vP^@sFH{su%iMzI!$4;V)v`l*1NZXxvv04(a)UU)D&#H%U#b9 zga{nq`1t#PeFS6NAu6u2V9wyUcy&zuA9ZkNeWmDdmWAoJO7c|WV$O>>e@Pk0a=Z#i|p z@NRj=&^YzX500Kbc~Hm$>yV4j^R=?PHHC|KHXk?kT7Jy;3&+z(p(DW- zK+V~^!G^xfaaW=LUY~O`4rL85K=6+b)<_)OBrV;%hIBvVmff9-^$YN0|d~$dltUeMMS70HLIfX@~FferX#Qp)|LQA zu>QSVZr){Im$>L}>~q?u@}N^(ggGw~QII5P76XdQB?v+SDPzp hnO|JQt?yj?NI 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 Aq5uE@ literal 0 HcmV?d00001 diff --git a/docs/_static/s2s_stratosphere-UserScript_fcstGFS_obsERA_StratospherePolar.png b/docs/_static/s2s_stratosphere-UserScript_fcstGFS_obsERA_StratospherePolar.png new file mode 100644 index 0000000000000000000000000000000000000000..253480cd5a581db6db05caca1093b8d02457c74b GIT binary patch literal 23362 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 literal 0 HcmV?d00001 diff --git a/docs/use_cases/model_applications/s2s_stratosphere/README.rst b/docs/use_cases/model_applications/s2s_stratosphere/README.rst new file mode 100644 index 0000000000..85138329be --- /dev/null +++ b/docs/use_cases/model_applications/s2s_stratosphere/README.rst @@ -0,0 +1,3 @@ +Subseasonal to Seasonal: Stratosphere +------------------------------------- +Subseasonal-to-Seasonal model configurations for Stratosphere evaluation diff --git a/docs/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere.py b/docs/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias.py similarity index 56% rename from docs/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere.py rename to docs/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias.py index 9f3fda7684..29d9f26d7c 100644 --- a/docs/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere.py +++ b/docs/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias.py @@ -1,10 +1,10 @@ """ -UserScript: Make zonal and meridonial means -======================================================================== +Bias Plot on Zonal Mean Wind and Temperature: UserScript, Series-Analysis +========================================================================== model_applications/ -s2s/ -UserScript_obsERA_obsOnly_Stratosphere.py +s2s_stratosphere/ +UserScript_fcstGFS_obsERA_StratosphereBias.py """ @@ -13,21 +13,25 @@ # -------------------- # # This use case calls functions in METcalcpy to create zonal and meridonial -# means +# means on U and T. It then runs Series-Analysis on the output zonal means +# and creates a contour plot of bias in latitude and pressure level. # ############################################################################## # Datasets # -------- # -# SSWC_v1.0_varFull_ERAi_d20130106_s20121107_e20130307_c20160701.nc +# GFS 24 hour forecasts: GFS_2018_02_24h.nc +# ERA: ERA_2018_02.nc +# ############################################################################## # METplus Components # ------------------ # # This use case runs the UserScript wrapper tool to run a user provided script, -# in this case, meridonial.py. +# in this case, zonal_mean_driver.py, runs Series-Analysis to compute the bias, +# and then runs another UserScript, bias_plot_driver.py, to create the bias plots. # ############################################################################## @@ -36,9 +40,9 @@ # # This use case does not loop but plots the entire time period of data # -# UserScript -# This uses data from 20130106,20121107,20130307,20160701 -# +# UserScript: Computes zonal and meridional means +# Series-Analysis: Computes the bias on zonal mean wind and temperature +# UserScript: Creates bias plots # ############################################################################## @@ -47,24 +51,40 @@ # # METplus first loads all of the configuration files found in parm/metplus_config, # then it loads any configuration files passed to METplus via the command line -# with the -c option, i.e. -c parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere.conf +# with the -c option, i.e. -c parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias.conf # # .. highlight:: bash -# .. literalinclude:: ../../../../parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere.conf +# .. literalinclude:: ../../../../parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias.conf # ############################################################################# # MET Configuration # --------------------- # -# There are no MET tools used in this use case. +# METplus sets environment variables based on user settings in the METplus configuration file. +# See :ref:`How METplus controls MET config file settings` for more details. +# +# **YOU SHOULD NOT SET ANY OF THESE ENVIRONMENT VARIABLES YOURSELF! THEY WILL BE OVERWRITTEN BY METPLUS WHEN IT CALLS THE MET TOOLS!** +# +# If there is a setting in the MET configuration file that is currently not supported by METplus you'd like to control, please refer to: +# :ref:`Overriding Unsupported MET config file settings` +# +# **SeriesAnalysisConfig_wrapped** +# +# .. note:: See the :ref:`Series-Analysis MET Configuration` section of the User's Guide for more information on the environment variables used in the file below: +# +# .. highlight:: bash +# .. literalinclude:: ../../../../parm/met_config/SeriesAnalysisConfig_wrapped # ############################################################################## # Python Embedding # ---------------- # -# There is no python embedding in this use case +# This use case uses a Python embedding script to read in the zonal mean data to Series-Analysis +# +# .. highlight:: bash +# .. literalinclude:: ../../../../parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/read_met_axis_mean.py # ############################################################################## @@ -73,14 +93,14 @@ # # This use case can be run two ways: # -# 1) Passing in meridonial_means.conf, +# 1) Passing in UserScript_fcstGFS_obsERA_StratosphereBias.conf, # then a user-specific system configuration file:: # -# run_metplus.py -c /path/to/METplus/parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere.conf -c /path/to/user_system.conf +# run_metplus.py -c /path/to/METplus/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias.conf -c /path/to/user_system.conf # -# 2) Modifying the configurations in parm/metplus_config, then passing in meridonial.conf:: +# 2) Modifying the configurations in parm/metplus_config, then passing in UserScript_fcstGFS_obsERA_StratosphereBias.conf: # -# run_metplus.py -c /path/to/METplus/parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere.conf +# run_metplus.py -c /path/to/METplus/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias.conf # # The former method is recommended. Whether you add them to a user-specific configuration file or modify the metplus_config files, the following variables must be set correctly: # @@ -89,9 +109,7 @@ # * **MET_INSTALL_DIR** - Path to location where MET is installed locally # # and for the [exe] section, you will need to define the location of NON-MET executables. -# If the executable is in the user's path, METplus will find it from the name. -# If the executable is not in the path, specify the full path to the executable here (i.e. RM = /bin/rm) -# The following executables are required for performing series analysis use cases: +# No executables are required for performing this use case. # # Example User Configuration File:: # @@ -100,13 +118,6 @@ # OUTPUT_BASE = /path/to/output/dir # MET_INSTALL_DIR = /path/to/met-X.Y # -# [exe] -# RM = /path/to/rm -# CUT = /path/to/cut -# TR = /path/to/tr -# NCAP2 = /path/to/ncap2 -# CONVERT = /path/to/convert -# NCDUMP = /path/to/ncdump # ############################################################################## @@ -126,10 +137,13 @@ # # * UserScriptUseCase # * S2SAppUseCase +# * S2SStratosphereAppUseCase +# * SeriesAnalysisUseCase # * METcalcpyUseCase +# * METplotpyUseCase # # Navigate to the :ref:`quick-search` page to discover other similar use cases. # # # -# sphinx_gallery_thumbnail_path = '_static/s2s-zonal_means.png' +# sphinx_gallery_thumbnail_path = '_static/s2s_stratosphere-UserScript_fcstGFS_obsERA_StratosphereBias.png' diff --git a/docs/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar.py b/docs/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar.py new file mode 100644 index 0000000000..e4c8af1857 --- /dev/null +++ b/docs/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar.py @@ -0,0 +1,151 @@ +""" +Bias Plot on Polar Cap Temperature and Polar Vortex U: UserScript, Stat-Analysis +================================================================================ + +model_applications/ +s2s_stratosphere/ +UserScript_fcstGFS_obsERA_StratospherePolar.py + +""" + +############################################################################## +# Scientific Objective +# -------------------- +# +# This use case calls functions in METcalcpy to create polar cap temperature +# and polar vortex wind. It then runs Stat-Analysis on the output zonal means +# and creates a contour plot of bias in lead time and pressure level. +# + +############################################################################## +# Datasets +# -------- +# +# * Forecast dataset: GFS Forecast U and T at multiple pressure levels +# * Observation dataset: ERA Reanlaysis U and T at multiple pressure levels +# +# Data for this use case is not contained in the sample data tar files due to +# its size. Rather, it is stored as additional data in a separate tar file. +# + +############################################################################## +# METplus Components +# ------------------ +# +# This use case runs the UserScript wrapper tool to run a user provided script, +# in this case, polar_t_u_driver.py which output data into MET's matched pair format. +# It then runs Stat-Analysis to compute the bias and RMSE, and another UserScript, +# bias_rmse_plot_driver.py, to create the plots. +# + +############################################################################## +# METplus Workflow +# ---------------- +# +# This use case loops over lead times for the first UserScript and Stat-Analysis, +# and the plotting proceeds over the entire time period +# +# UserScript: Computes polar cap temperature and polar vortex U +# Stat-Analysis: Computes ME and RMSE on polar cap temperature and polar vortex U +# UserScript: Creates ME and RMSE plots +# + +############################################################################## +# METplus Configuration +# --------------------- +# +# METplus first loads all of the configuration files found in parm/metplus_config, +# then it loads any configuration files passed to METplus via the command line +# with the -c option, i.e. -c parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar.conf +# +# .. highlight:: bash +# .. literalinclude:: ../../../../parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar.conf +# + +############################################################################# +# MET Configuration +# --------------------- +# +# METplus sets environment variables based on user settings in the METplus configuration file. +# See :ref:`How METplus controls MET config file settings` for more details. +# +# **YOU SHOULD NOT SET ANY OF THESE ENVIRONMENT VARIABLES YOURSELF! THEY WILL BE OVERWRITTEN BY METPLUS WHEN IT CALLS THE MET TOOLS!** +# +# If there is a setting in the MET configuration file that is currently not supported by METplus you'd like to control, please refer to: +# :ref:`Overriding Unsupported MET config file settings` +# +# **STATAnalysisConfig_wrapped** +# +# .. note:: See the :ref:`Series-Analysis MET Configuration` section of the User's Guide for more information on the environment variables used in the file below: +# +# .. highlight:: bash +# .. literalinclude:: ../../../../parm/met_config/STATAnalysisConfig_wrapped +# + +############################################################################## +# Python Embedding +# ---------------- +# +# This use case does not use python embedding +# + +############################################################################## +# Running METplus +# --------------- +# +# This use case can be run two ways: +# +# 1) Passing in UserScript_fcstGFS_obsERA_StratospherePolar.conf, +# then a user-specific system configuration file:: +# +# run_metplus.py -c /path/to/METplus/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar.conf -c /path/to/user_system.conf +# +# 2) Modifying the configurations in parm/metplus_config, then passing in UserScript_fcstGFS_obsERA_StratospherePolar.conf: +# +# run_metplus.py -c /path/to/METplus/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar.conf +# +# The former method is recommended. Whether you add them to a user-specific configuration file or modify the metplus_config files, the following variables must be set correctly: +# +# * **INPUT_BASE** - Path to directory where sample data tarballs are unpacked (See Datasets section to obtain tarballs). This is not required to run METplus, but it is required to run the examples in parm/use_cases +# * **OUTPUT_BASE** - Path where METplus output will be written. This must be in a location where you have write permissions +# * **MET_INSTALL_DIR** - Path to location where MET is installed locally +# +# and for the [exe] section, you will need to define the location of NON-MET executables. +# No executables are required for performing this use case. +# +# Example User Configuration File:: +# +# [dir] +# INPUT_BASE = /path/to/sample/input/data +# OUTPUT_BASE = /path/to/output/dir +# MET_INSTALL_DIR = /path/to/met-X.Y +# +# + +############################################################################## +# Expected Output +# --------------- +# +# A successful run will output the following both to the screen and to the logfile:: +# +# INFO: METplus has successfully finished running. +# + +############################################################################## +# Keywords +# -------- +# +# .. note:: +# +# * UserScriptUseCase +# * S2SAppUseCase +# * S2SStratosphereAppUseCase +# * StatAnalysisUseCase +# * METcalcpyUseCase +# * METplotpyUseCase +# +# Navigate to the :ref:`quick-search` page to discover other similar use cases. +# +# +# +# sphinx_gallery_thumbnail_path = '_static/s2s_stratosphere-UserScript_fcstGFS_obsERA_StratospherePolar.png' diff --git a/internal/tests/use_cases/all_use_cases.txt b/internal/tests/use_cases/all_use_cases.txt index 658f73d3dd..8aed023e48 100644 --- a/internal/tests/use_cases/all_use_cases.txt +++ b/internal/tests/use_cases/all_use_cases.txt @@ -105,6 +105,7 @@ Category: marine_and_cryosphere 9::PointStat_fcstGFS_obsASCAT_satelliteWinds::model_applications/marine_and_cryosphere/PointStat_fcstGFS_obsASCAT_satelliteWinds.conf:: icecover_env, py_embed 10::PointStat_fcstGFS_obsJASON3_satelliteAltimetry::model_applications/marine_and_cryosphere/PointStat_fcstGFS_obsJASON3_satelliteAltimetry.conf:: py_embed_base_env, py_embed + Category: medium_range 0::PointStat_fcstGFS_obsNAM_Sfc_MultiField_PrepBufr:: model_applications/medium_range/PointStat_fcstGFS_obsNAM_Sfc_MultiField_PrepBufr.conf 1::TCStat_SeriesAnalysis_fcstGFS_obsGFS_FeatureRelative_SeriesByInit:: model_applications/medium_range/TCStat_SeriesAnalysis_fcstGFS_obsGFS_FeatureRelative_SeriesByInit.conf:: netcdf4_env @@ -140,9 +141,8 @@ Category: s2s 1::TCGen_fcstGFSO_obsBDECKS_GDF_TDF:: model_applications/s2s/TCGen_fcstGFSO_obsBDECKS_GDF_TDF.conf:: metplotpy_env,cartopy,metplus 2::UserScript_obsPrecip_obsOnly_Hovmoeller:: model_applications/s2s/UserScript_obsPrecip_obsOnly_Hovmoeller.conf:: metplotpy_env,cartopy 3:: UserScript_fcstS2S_obsERAI_CrossSpectra:: model_applications/s2s/UserScript_fcstS2S_obsERAI_CrossSpectra.conf:: spacetime_env -4:: UserScript_obsERA_obsOnly_Stratosphere:: model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere.conf:: metplotpy_env,metdataio -5::SeriesAnalysis_fcstCFSv2_obsGHCNCAMS_climoStandardized_MultiStatisticTool:: model_applications/s2s/SeriesAnalysis_fcstCFSv2_obsGHCNCAMS_climoStandardized_MultiStatisticTool.conf:: netcdf4_env -6::GridStat_fcstCFSv2_obsGHCNCAMS_MultiTercile:: model_applications/s2s/GridStat_fcstCFSv2_obsGHCNCAMS_MultiTercile.conf:: netcdf4_env +4::SeriesAnalysis_fcstCFSv2_obsGHCNCAMS_climoStandardized_MultiStatisticTool:: model_applications/s2s/SeriesAnalysis_fcstCFSv2_obsGHCNCAMS_climoStandardized_MultiStatisticTool.conf:: netcdf4_env +5::GridStat_fcstCFSv2_obsGHCNCAMS_MultiTercile:: model_applications/s2s/GridStat_fcstCFSv2_obsGHCNCAMS_MultiTercile.conf:: netcdf4_env Category: s2s_mid_lat @@ -160,6 +160,11 @@ Category: s2s_mjo 4:: UserScript_obsCFSR_obsOnly_MJO_ENSO:: model_applications/s2s_mjo/UserScript_obsCFSR_obsOnly_MJO_ENSO.conf:: spacetime_env, metdataio +Category: s2s_stratosphere +0:: UserScript_fcstGFS_obsERA_StratosphereBias:: model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias.conf:: weatherregime_env,cartopy,metdataio +#X::UserScript_fcstGFS_obsERA_StratospherePolar:: model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar.conf:: weatherregime_env,cartopy,metdataio + + Category: short_range 0::EnsembleStat_fcstHRRRE_obsHRRRE_Sfc_MultiField::model_applications/short_range/EnsembleStat_fcstHRRRE_obsHRRRE_Sfc_MultiField.conf 1::MODE_fcstHRRR_obsMRMS_Hail_GRIB2::model_applications/short_range/MODE_fcstHRRR_obsMRMS_Hail_GRIB2.conf diff --git a/parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere.conf b/parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere.conf deleted file mode 100644 index 0d81594060..0000000000 --- a/parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere.conf +++ /dev/null @@ -1,51 +0,0 @@ -[config] - -# Documentation for this use case can be found at -# https://metplus.readthedocs.io/en/latest/generated/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere.html - -# For additional information, please see the METplus Users Guide. -# https://metplus.readthedocs.io/en/latest/Users_Guide - -### -# Processes to run -# https://metplus.readthedocs.io/en/latest/Users_Guide/systemconfiguration.html#process-list -### - -PROCESS_LIST = UserScript - - -### -# Time Info -# LOOP_BY options are INIT, VALID, RETRO, and REALTIME -# If set to INIT or RETRO: -# INIT_TIME_FMT, INIT_BEG, INIT_END, and INIT_INCREMENT must also be set -# If set to VALID or REALTIME: -# VALID_TIME_FMT, VALID_BEG, VALID_END, and VALID_INCREMENT must also be set -# LEAD_SEQ is the list of forecast leads to process -# https://metplus.readthedocs.io/en/latest/Users_Guide/systemconfiguration.html#timing-control -### - -LOOP_BY = REALTIME - -VALID_TIME_FMT = %Y -VALID_BEG = 2013 - -USER_SCRIPT_RUNTIME_FREQ = RUN_ONCE - - -### -# UserScript Settings -# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#userscript -### - -USER_SCRIPT_COMMAND = {PARM_BASE}/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere/meridonial_mean.py - -[user_env_vars] -INPUT_FILE_NAME = {INPUT_BASE}/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere/SSWC_v1.0_varFull_ERAi_d20130106_s20121107_e20130307_c20160701.nc -YAML_CONFIG_NAME = {METPLUS_BASE}/parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere/meridonial_mean.yaml - -LOG_FILE = "Meridonial_means.log" - -LOG_LEVEL = "INFO" - -OUTPUT_DIR = {OUTPUT_BASE} diff --git a/parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere/meridonial_mean.py b/parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere/meridonial_mean.py deleted file mode 100755 index 777be36ea6..0000000000 --- a/parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere/meridonial_mean.py +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env python3 - -""" -Create meridonial mean statistics - -""" -import os -import sys -import logging -import yaml -import xarray as xr # http://xarray.pydata.org/ -import metcalcpy.util.read_env_vars_in_config as readconfig -import metcalcpy.pre_processing.directional_means as directional_means -import METreadnc.util.read_netcdf as read_netcdf - - -def main(): - """ - Use existing default meridonial mean config file found in METcalcpy to - grab the test file - """ - - - """ - Read Meridial Mean YAML configuration file - user can use their own, if none specified at the command line, - use the "default" example YAML config file, spectra_plot_coh2.py - Using a custom YAML reader so we can use environment variables - """ - - try: - input_config_file = os.getenv("YAML_CONFIG_NAME","meridonial_mean.yaml") - config = readconfig.parse_config(input_config_file) - logging.info(config) - except yaml.YAMLError as exc: - logging.error(exc) - - """ - Read METplus config file paramaters - """ - #input_file_name = os.environ.get("INPUT_FILE_NAME","SSWC_v1.0_varFull_ERAi_d20130106_s20121107_e20130307_c20160701.nc") - input_file = config["input_filename"] - - """ - Setup logging - """ - logfile = "meridonial_mean.log" - logging_level = os.environ.get("LOG_LEVEL","logging.INFO") - logging.basicConfig(stream=logfile, level=logging_level) - - """ - Read dataset - """ - try: - logging.info('Opening ' + input_file[0]) - file_reader = read_netcdf.ReadNetCDF() - - #file_reader returns a list of xarrays even if there is only one file requested to be read - #so we change it from a list to a single - ds = file_reader.read_into_xarray(input_file)[0] - except IOError as exc: - logging.error('Unable to open ' + input_file) - logging.error(exc) - sys.exit(1) - logging.debug(ds) - ds = ds[['uwndFull_TS','vwndFull_TS','tempFull_TS','geopFull_TS']] - ds = ds.rename({'timeEv60':'time', - 'lat':'latitude', # pyzome currently expects dimensions named latitude and longitude - 'lon':'longitude', - 'uwndFull_TS':'u', - 'vwndFull_TS':'v', - 'tempFull_TS':'T', - 'geopFull_TS':'Z'}) - - uzm = directional_means.zonal_mean(ds.u) - Tzm = directional_means.zonal_mean(ds.T) - T_6090 = directional_means.meridional_mean(Tzm, 60, 90) - - print(T_6090) - -if __name__ == '__main__': - main() diff --git a/parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere/meridonial_mean.yaml b/parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere/meridonial_mean.yaml deleted file mode 100644 index 6cadc5160b..0000000000 --- a/parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere/meridonial_mean.yaml +++ /dev/null @@ -1,2 +0,0 @@ -input_filename: -- !ENV '${INPUT_FILE_NAME}' diff --git a/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias.conf b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias.conf new file mode 100644 index 0000000000..f2182e5c24 --- /dev/null +++ b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias.conf @@ -0,0 +1,148 @@ +[config] + +# Documentation for this use case can be found at +# https://metplus.readthedocs.io/en/latest/generated/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias.html + +# For additional information, please see the METplus Users Guide. +# https://metplus.readthedocs.io/en/latest/Users_Guide + +### +# Processes to run +# https://metplus.readthedocs.io/en/latest/Users_Guide/systemconfiguration.html#process-list +### +PROCESS_LIST = UserScript(obs_means), UserScript(fcst_means), SeriesAnalysis(sa_ut), UserScript(bias_plot) + + +### +# Time Info +# LOOP_BY options are INIT, VALID, RETRO, and REALTIME +# If set to INIT or RETRO: +# INIT_TIME_FMT, INIT_BEG, INIT_END, and INIT_INCREMENT must also be set +# If set to VALID or REALTIME: +# VALID_TIME_FMT, VALID_BEG, VALID_END, and VALID_INCREMENT must also be set +# LEAD_SEQ is the list of forecast leads to process +# https://metplus.readthedocs.io/en/latest/Users_Guide/systemconfiguration.html#timing-control +### + +LOOP_BY = VALID + +VALID_TIME_FMT = %Y%m%d +VALID_BEG = 20180201 +VALID_END = 20180228 +VALID_INCREMENT = 30d +LEAD_SEQ = 24 + +USER_SCRIPT_RUNTIME_FREQ = RUN_ONCE + +LOOP_ORDER = processes + + +### +# User Environment Variables +### +[user_env_vars] +OBS_INPUT_FILE_NAME = {INPUT_BASE}/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/ERA_2018_02.nc +FCST_INPUT_FILE_NAME = {INPUT_BASE}/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/GFS_2018_02_024h.nc + +OUTPUT_DIR = {OUTPUT_BASE}/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias + +PLOT_U_INPUT_FILE = {OUTPUT_BASE}/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/SeriesAnalysis/zonal_mean_U_stats_2018_02.nc +PLOT_U_BIAS_VAR = series_cnt_ME +PLOT_U_OBAR_VAR = series_cnt_OBAR +PLOT_U_LEVELS = 0,10,20,30,40,50,60,70,80,90,100 +PLOT_U_TITLE = GFS vs ERA 24h Forecast Zonal Mean Wind Bias (ME) 02/2018 +PLOT_U_OUTPUT_DIR = {OUTPUT_DIR}/plots +PLOT_U_OUTPUT_FILE = GFS_ERA_ME_2018_02_zonal_mean_U.png + +PLOT_T_INPUT_FILE = {OUTPUT_BASE}/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/SeriesAnalysis/zonal_mean_T_stats_2018_02.nc +PLOT_T_BIAS_VAR = series_cnt_ME +PLOT_T_OBAR_VAR = series_cnt_OBAR +PLOT_T_LEVELS = 200,210,220,230,240,250,260,270,280,290,300 +PLOT_T_TITLE = GFS vs ERA 24h Forecast Zonal Mean Temperature Bias (ME) 02/2018 +PLOT_T_OUTPUT_DIR = {OUTPUT_DIR}/plots +PLOT_T_OUTPUT_FILE = GFS_ERA_ME_2018_02_zonal_mean_T.png + + +### +# Zonal Mean UserScript Settings +# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#userscript +### +[obs_means] +USER_SCRIPT_COMMAND = {PARM_BASE}/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/zonal_mean_driver.py obs time + + +[fcst_means] +USER_SCRIPT_COMMAND = {PARM_BASE}/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/zonal_mean_driver.py fcst time + + +### +# Series Analysis Settings +### +[sa_ut] +SERIES_ANALYSIS_RUNTIME_FREQ = RUN_ONCE + +FCST_SERIES_ANALYSIS_INPUT_DIR = {OUTPUT_BASE}/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/FCST +FCST_SERIES_ANALYSIS_INPUT_TEMPLATE = FCST_zonal_mean_U_T_{valid?fmt=%Y%m}*_{valid?fmt=%H%M%S}.nc +FCST_SERIES_ANALYSIS_INPUT_DATATYPE = PYTHON_NUMPY + +OBS_SERIES_ANALYSIS_INPUT_DIR = {OUTPUT_BASE}/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/OBS +OBS_SERIES_ANALYSIS_INPUT_TEMPLATE = OBS_zonal_mean_U_T_{valid?fmt=%Y%m}*_{valid?fmt=%H%M%S}.nc +OBS_SERIES_ANALYSIS_INPUT_DATATYPE = PYTHON_NUMPY + +SERIES_ANALYSIS_CLIMO_MEAN_INPUT_DIR = +SERIES_ANALYSIS_CLIMO_MEAN_INPUT_TEMPLATE = + +SERIES_ANALYSIS_CLIMO_STDEV_INPUT_DIR = +SERIES_ANALYSIS_CLIMO_STDEV_INPUT_TEMPLATE = + +SERIES_ANALYSIS_OUTPUT_DIR = {OUTPUT_BASE}/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/SeriesAnalysis + +SERIES_ANALYSIS_DESC = + +SERIES_ANALYSIS_CAT_THRESH = + +SERIES_ANALYSIS_VLD_THRESH = + +SERIES_ANALYSIS_BLOCK_SIZE = + +SERIES_ANALYSIS_CTS_LIST = + +SERIES_ANALYSIS_REGRID_TO_GRID = +SERIES_ANALYSIS_REGRID_METHOD = +SERIES_ANALYSIS_REGRID_WIDTH = +SERIES_ANALYSIS_REGRID_VLD_THRESH = +SERIES_ANALYSIS_REGRID_SHAPE = + +SERIES_ANALYSIS_RUN_ONCE_PER_STORM_ID = False + +SERIES_ANALYSIS_IS_PAIRED = False + +SERIES_ANALYSIS_CONFIG_FILE = {PARM_BASE}/met_config/SeriesAnalysisConfig_wrapped + +SERIES_ANALYSIS_OUTPUT_STATS_CNT = TOTAL, ME, RMSE, FBAR, OBAR + +MODEL = GFS + +OBTYPE = ERA + +SERIES_ANALYSIS_OUTPUT_TEMPLATE = zonal_mean_{fcst_level}_stats_2018_02.nc + +FCST_SERIES_ANALYSIS_VAR1_NAME = {PARM_BASE}/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/read_met_axis_mean.py MET_PYTHON_INPUT_ARG u lat +# This level is used as a label only +FCST_SERIES_ANALYSIS_VAR1_LEVELS = U + +OBS_SERIES_ANALYSIS_VAR1_NAME = {PARM_BASE}/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/read_met_axis_mean.py MET_PYTHON_INPUT_ARG u lat + + +FCST_SERIES_ANALYSIS_VAR2_NAME = {PARM_BASE}/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/read_met_axis_mean.py MET_PYTHON_INPUT_ARG T lat +FCST_SERIES_ANALYSIS_VAR2_LEVELS = T + +OBS_SERIES_ANALYSIS_VAR2_NAME = {PARM_BASE}/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/read_met_axis_mean.py MET_PYTHON_INPUT_ARG T lat + + +### +# UserScript Bias Plot Settings +# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#userscript +### +[bias_plot] +USER_SCRIPT_COMMAND = {PARM_BASE}/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/bias_plot_driver.py diff --git a/parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere/README b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/README similarity index 70% rename from parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere/README rename to parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/README index 8111901811..de1e1d0abe 100644 --- a/parm/use_cases/model_applications/s2s/UserScript_obsERA_obsOnly_Stratosphere/README +++ b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/README @@ -1,8 +1,8 @@ These files are a use case to show how to compute meridial and zonal means -You need METcalcpy and METdataio in your python path or your conda environment +You need METcalcpy and METdatadb in your python path or your conda environment i.e. -export PYTHONPATH=/METdataio:/METcalcpy +export PYTHONPATH=/METdatadb:/METcalcpy The file SSWC_v1.0_varFull_ERAi_d20130106_s20121107_e20130307_c20160701.nc needs to be on disk somewhere on your computer and referenced correctly in the file diff --git a/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/bias_plot_driver.py b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/bias_plot_driver.py new file mode 100755 index 0000000000..dd28c190f3 --- /dev/null +++ b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/bias_plot_driver.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 + +""" +Creates a bias plot +""" +import os +import METreadnc.util.read_netcdf as read_netcdf +from metplotpy.contributed.stratosphere_diagnostics.stratosphere_plots import plot_zonal_bias + + +def main(): + """ + Read METplus environment variables + """ + print('Reading Input Environment Variables') + infile_u = [os.environ['PLOT_U_INPUT_FILE']] + invar_u = os.environ['PLOT_U_BIAS_VAR'] + omvar_u = os.environ['PLOT_U_OBAR_VAR'] + plot_levels_u_str = os.environ['PLOT_U_LEVELS'].split(',') + plot_levels_u = [int(pp) for pp in plot_levels_u_str] + plot_title_u = os.environ['PLOT_U_TITLE'] + output_dir_u = os.environ['PLOT_U_OUTPUT_DIR'] + output_file_u = os.environ.get('PLOT_U_OUTPUT_FILE','bias_plot.png') + plot_output_file_u = os.path.join(output_dir_u,output_file_u) + + infile_t = [os.environ['PLOT_T_INPUT_FILE']] + invar_t = os.environ['PLOT_T_BIAS_VAR'] + omvar_t = os.environ['PLOT_T_OBAR_VAR'] + plot_levels_t_str = os.environ['PLOT_T_LEVELS'].split(',') + plot_levels_t = [int(pp) for pp in plot_levels_t_str] + plot_title_t = os.environ['PLOT_T_TITLE'] + output_dir_t = os.environ['PLOT_T_OUTPUT_DIR'] + output_file_t = os.environ.get('PLOT_T_OUTPUT_FILE','bias_plot.png') + plot_output_file_t = os.path.join(output_dir_t,output_file_t) + + """ + Make plot output directory if it doesn't exist + """ + if not os.path.exists(output_dir_u): + os.makedirs(output_dir_u) + + if not os.path.exists(output_dir_t): + os.makedirs(output_dir_t) + + """ + Read dataset + """ + print('Reading Zonal Mean U Bias File: '+infile_u[0]) + file_reader_u = read_netcdf.ReadNetCDF() + dsu = file_reader_u.read_into_xarray(infile_u)[0] + bias_u = dsu[invar_u].values + lats_u = dsu['lat'].values + obar_u = dsu[omvar_u].values + levels_u = dsu['level'].values + + print('Reading Zonal Mean T Bias File: '+infile_t[0]) + file_reader_t = read_netcdf.ReadNetCDF() + dst = file_reader_t.read_into_xarray(infile_t)[0] + bias_t = dst[invar_t].values + lats_t = dst['lat'].values + obar_t = dst[omvar_t].values + levels_t = dst['level'].values + + """ + Create Bias Plots + """ + print('Plotting Zonal Mean U Bias') + plot_zonal_bias(lats_u,levels_u,bias_u,obar_u,plot_output_file_u,plot_title_u,plot_levels_u) + print('Plotting Zonal Mean T Bias') + plot_zonal_bias(lats_t,levels_t,bias_t,obar_t,plot_output_file_t,plot_title_t,plot_levels_t) + + +if __name__ == '__main__': + main() diff --git a/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/read_met_axis_mean.py b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/read_met_axis_mean.py new file mode 100644 index 0000000000..b3b4bc1aeb --- /dev/null +++ b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/read_met_axis_mean.py @@ -0,0 +1,60 @@ +import os +import sys +import numpy as np +import datetime as dt +import netCDF4 as nc4 + + +if len(sys.argv) != 4: + print("Must specify exactly one input file, variable name, and summary axis (lat, lon, latlon).") + sys.exit(1) + +# Read the input file as the first argument +input_file = os.path.expandvars(sys.argv[1]) +var_name = sys.argv[2] +axis = sys.argv[3] + +# Read the data +f = nc4.Dataset(input_file, 'r') +data = np.float64(f.variables[var_name][:]) +met_data = np.transpose(data).copy() + +if axis == "lon": + lats = list() + lons = list(np.float64(f.variables["lon"][:])) +elif axis == "lat": + lats = list(np.float64(f.variables["lat"][:])) + lons = list() + +pres = list(list(np.float64(f.variables["pres"][:]))) +times = list() + +lead_ma = f.variables["lead_time"][:] +lead = lead_ma.__int__() +vtime = f.variables["time"] +cur_date = nc4.num2date(vtime[:], vtime.units, vtime.calendar) +init = cur_date - dt.timedelta(hours=lead) +accum = "00" + +attrs = { + 'valid': cur_date.strftime("%Y%m%d_%H%M%S"), + 'init': init.strftime("%Y%m%d_%H%M%S"), + 'lead': str(int(lead)).zfill(2), + 'accum': accum, + + 'name': var_name, + 'long_name': str(getattr(f.variables[var_name], "long_name")), + 'level': axis + "_mean", + 'units': str(getattr(f.variables[var_name], "units")), + + 'grid': { + 'type' : "SemiLatLon", + 'name' : axis + "_mean", + 'lats' : lats, + 'lons' : lons, + 'levels' : pres, + 'times' : times + } +} + +print("Attributes: " + repr(attrs)) diff --git a/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/zonal_mean_driver.py b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/zonal_mean_driver.py new file mode 100755 index 0000000000..170bab1aba --- /dev/null +++ b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratosphereBias/zonal_mean_driver.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 + +""" +Create meridonial mean statistics + +""" +import os +import sys +import logging +import yaml +import xarray as xr # http://xarray.pydata.org/ +import metcalcpy.util.read_env_vars_in_config as readconfig +import metcalcpy.pre_processing.directional_means as directional_means +import METreadnc.util.read_netcdf as read_netcdf + + +def main(): + """ + Read arguments + """ + inlabel = sys.argv[1].upper() + timevar = sys.argv[2] + + """ + Read METplus environment variables + """ + print('Reading Input Environment Variables') + input_file = [os.environ[inlabel+'_INPUT_FILE_NAME']] + output_dir = os.environ['OUTPUT_DIR'] + full_output_dir = os.path.join(output_dir,inlabel) + + """ + Setup logging + """ + #logfile = "meridonial_mean.log" + #logging_level = os.environ.get("LOG_LEVEL","logging.INFO") + #logging.basicConfig(stream=logfile, level=logging_level) + + """ + Read dataset + """ + print('Reading input data') + file_reader = read_netcdf.ReadNetCDF() + ds = file_reader.read_into_xarray(input_file)[0] + ds = ds.rename({'lat':'latitude', + 'lon':'longitude'}) + + print('Computing Zonal means') + uzm = directional_means.zonal_mean(ds.u) + uzm = uzm.assign_coords(lat=("latitude",ds.latitude.values[:,0])) + Tzm = directional_means.zonal_mean(ds.T) + Tzm = Tzm.assign_coords(lat=("latitude",ds.latitude.values[:,0])) + + """ + Write output files if desired, by first creating a directory + """ + print('Writing output zonal mean files') + if not os.path.exists(full_output_dir): + os.makedirs(full_output_dir) + + datetimeindex = ds.indexes[timevar].to_datetimeindex() + out_ds = uzm.to_dataset() + out_ds.u.attrs = ds.u.attrs + out_ds['T'] = Tzm + out_ds.T.attrs = ds.T.attrs + for i in range(len(datetimeindex)): + cur_date = datetimeindex[i] + output_file = os.path.join(full_output_dir,inlabel+'_zonal_mean_U_T_'+cur_date.strftime('%Y%m%d_%H%M%S')+'.nc') + out_write = out_ds.isel(time=i) + # Add lead time as a variable + if inlabel == 'OBS': + out_write = out_write.assign(lead_time=[0.0]) + elif inlabel == 'FCST': + #Grab Forecast Lead + out_write = out_write.assign(lead_time=ds.lead_time[i]) + out_write.to_netcdf(output_file, 'w') + + + +if __name__ == '__main__': + main() diff --git a/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar.conf b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar.conf new file mode 100644 index 0000000000..c3cbbfc4ce --- /dev/null +++ b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar.conf @@ -0,0 +1,130 @@ +[config] + +# Documentation for this use case can be found at +# https://metplus.readthedocs.io/en/latest/generated/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar.html + +# For additional information, please see the METplus Users Guide. +# https://metplus.readthedocs.io/en/latest/Users_Guide + +### +# Processes to run +# https://metplus.readthedocs.io/en/latest/Users_Guide/systemconfiguration.html#process-list +### + +PROCESS_LIST = UserScript(means), StatAnalysis(sanal_cnt), UserScript(plots_t), UserScript(plots_u) + + +SCRUB_STAGING_DIR = False + +### +# Time Info +# LOOP_BY options are INIT, VALID, RETRO, and REALTIME +# If set to INIT or RETRO: +# INIT_TIME_FMT, INIT_BEG, INIT_END, and INIT_INCREMENT must also be set +# If set to VALID or REALTIME: +# VALID_TIME_FMT, VALID_BEG, VALID_END, and VALID_INCREMENT must also be set +# LEAD_SEQ is the list of forecast leads to process +# https://metplus.readthedocs.io/en/latest/Users_Guide/systemconfiguration.html#timing-control +### + +LOOP_BY = VALID + +VALID_TIME_FMT = %Y%m%d +VALID_BEG = 20180201 +VALID_END = 20180228 +VALID_INCREMENT = 30d +LEAD_SEQ = begin_end_incr(0,240,3),begin_end_incr(252,384,12) + +LOOP_ORDER = processes + + +### +# UserScript Settings +# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#userscript +### +[means] +USER_SCRIPT_RUNTIME_FREQ = RUN_ONCE_PER_LEAD + +# Template of filenames to input to the user-script +USER_SCRIPT_INPUT_TEMPLATE = {INPUT_BASE}/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/ERA/ERA_{valid?fmt=%Y}_{valid?fmt=%m}.nc, {INPUT_BASE}/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/GFS/GFS_{valid?fmt=%Y}_{valid?fmt=%m}_{lead?fmt=%HHH}h.nc + +# Name of the file containing the listing of input files +# The options are OBS_INPUT for observations or FCST_INPUT for forecast +# Or, set OBS_INPUT, FCST_INPUT if doing both and make sure the USER_SCRIPT_INPUT_TEMPLATE is ordered: +# observation_template, forecast_template +USER_SCRIPT_INPUT_TEMPLATE_LABELS = OBS_INPUT, FCST_INPUT + +USER_SCRIPT_COMMAND = {PARM_BASE}/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/polar_t_u_driver.py time {lead?fmt=%HHH} + + + +[user_env_vars] +MODEL_NAME = GFS + +OUTPUT_DIR = {OUTPUT_BASE}/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar + +PLOT_OUTPUT_DIR = {OUTPUT_DIR}/plots + +PLOT_INPUT_FILE = {OUTPUT_BASE}/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/SeriesAnalysis/zonal_mean_stats_2018_02.nc +PLOT_T_BIAS_LEVELS = -6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6 +PLOT_T_BIAS_TITLE = GFS vs ERA Polar Cap Temperature Bias (ME) 02/2018 +PLOT_T_RMSE_LEVELS = 0,0.5,1,1.5,2,2.5,3,3.5,4,4.5,5,5.5,6 +PLOT_T_RMSE_TITLE = GFS vs ERA Polar Cap Temperature RMSE 02/2018 +PLOT_T_BIAS_OUTPUT_FILE = ME_2018_02_polar_cap_T.png +PLOT_T_RMSE_OUTPUT_FILE = RMSE_2018_02_polar_cap_T.png + +PLOT_U_BIAS_LEVELS = -6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6 +PLOT_U_BIAS_TITLE = GFS vs ERA Polar Vortex U Bias (ME) 02/2018 +PLOT_U_RMSE_LEVELS = 0,0.5,1,1.5,2,2.5,3,3.5,4,4.5,5 +PLOT_U_RMSE_TITLE = GFS vs ERA Polar Vortex U RMSE 02/2018 +PLOT_U_BIAS_OUTPUT_FILE = ME_2018_02_polar_vortex_U.png +PLOT_U_RMSE_OUTPUT_FILE = RMSE_2018_02_polar_vortex_U.png + +[sanal_cnt] +MODEL1 = GFS +MODEL1_OBTYPE = ADPUPA + +STAT_ANALYSIS_CONFIG_FILE = {PARM_BASE}/met_config/STATAnalysisConfig_wrapped + +STAT_ANALYSIS_JOB1 = -job aggregate_stat -line_type MPR -out_line_type CNT -fcst_var PolarCapT -by FCST_LEV,FCST_LEAD -out_stat [out_stat_file]_PolarCapT_CNT.stat +STAT_ANALYSIS_JOB2 = -job aggregate_stat -line_type MPR -out_line_type CNT -fcst_var PolarVortexU -by FCST_LEV,FCST_LEAD -out_stat [out_stat_file]_PolarVortexU_CNT.stat + +MODEL_LIST = {MODEL1} +FCST_LEAD_LIST = 00, 03, 06, 09, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, 108, 111, 114, 117, 120, 123, 126, 129, 132, 135, 138, 141, 144, 147, 150, 153, 156, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 189, 192, 195, 198, 201, 204, 207, 210, 213, 216, 219, 222, 225, 228, 231, 234, 237, 240, 252, 264, 276, 288, 300, 312, 324, 336, 348, 360, 372, 384 + +GROUP_LIST_ITEMS = MODEL_LIST +LOOP_LIST_ITEMS = FCST_LEAD_LIST + +MODEL1_STAT_ANALYSIS_LOOKIN_DIR = {OUTPUT_BASE}/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/mpr + +STAT_ANALYSIS_OUTPUT_DIR = {OUTPUT_BASE}/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/StatAnalysis + +MODEL1_STAT_ANALYSIS_OUT_STAT_TEMPLATE = {model?fmt=%s}_ERA_{obs_valid_beg?fmt=%Y%m%d}_{obs_valid_end?fmt=%Y%m%d}_{lead?fmt=%H%M%S}L + + +[plots_t] +USER_SCRIPT_RUNTIME_FREQ = RUN_ONCE + +USER_SCRIPT_INPUT_TEMPLATE = {OUTPUT_BASE}/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/StatAnalysis/GFS_ERA_{valid?fmt=%Y%m%d}_*_{lead?fmt=%H%M%S}L_PolarCapT_CNT.stat + +# Name of the file containing the listing of input files +# The options are OBS_INPUT for observations or FCST_INPUT for forecast +# Or, set OBS_INPUT, FCST_INPUT if doing both and make sure the USER_SCRIPT_INPUT_TEMPLATE is ordered: +# observation_template, forecast_template +USER_SCRIPT_INPUT_TEMPLATE_LABELS = STAT_INPUT + +USER_SCRIPT_COMMAND = {PARM_BASE}/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/bias_rmse_plot_driver.py T + + +[plots_u] +USER_SCRIPT_RUNTIME_FREQ = RUN_ONCE + +USER_SCRIPT_INPUT_TEMPLATE = {OUTPUT_BASE}/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/StatAnalysis/GFS_ERA_{valid?fmt=%Y%m%d}_*_{lead?fmt=%H%M%S}L_PolarVortexU_CNT.stat + +# Name of the file containing the listing of input files +# The options are OBS_INPUT for observations or FCST_INPUT for forecast +# Or, set OBS_INPUT, FCST_INPUT if doing both and make sure the USER_SCRIPT_INPUT_TEMPLATE is ordered: +# observation_template, forecast_template +USER_SCRIPT_INPUT_TEMPLATE_LABELS = STAT_INPUT + +USER_SCRIPT_COMMAND = {PARM_BASE}/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/bias_rmse_plot_driver.py U diff --git a/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/README b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/README new file mode 100644 index 0000000000..de1e1d0abe --- /dev/null +++ b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/README @@ -0,0 +1,9 @@ +These files are a use case to show how to compute meridial and zonal means + +You need METcalcpy and METdatadb in your python path or your conda environment +i.e. +export PYTHONPATH=/METdatadb:/METcalcpy + +The file SSWC_v1.0_varFull_ERAi_d20130106_s20121107_e20130307_c20160701.nc needs to be +on disk somewhere on your computer and referenced correctly in the file +meridial_mean.yaml diff --git a/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/bias_rmse_plot_driver.py b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/bias_rmse_plot_driver.py new file mode 100755 index 0000000000..451a50aabc --- /dev/null +++ b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/bias_rmse_plot_driver.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 + +""" +Creates Polar Cap Bias and RMSE plots +""" +import os +import sys +import pandas as pd +import numpy as np +import METreadnc.util.read_netcdf as read_netcdf +from metplotpy.contributed.stratosphere_diagnostics.stratosphere_plots import plot_polar_bias,plot_polar_rmse + + +def main(): + plvar = sys.argv[1] + + """ + Read METplus environment variables + """ + plot_bias_levels_str = os.environ['PLOT_'+plvar+'_BIAS_LEVELS'].split(',') + plot_bias_levels = [float(pp) for pp in plot_bias_levels_str] + plot_bias_title = os.environ['PLOT_'+plvar+'_BIAS_TITLE'] + plot_rmse_levels_str = os.environ['PLOT_'+plvar+'_RMSE_LEVELS'].split(',') + plot_rmse_levels = [float(pp) for pp in plot_rmse_levels_str] + plot_rmse_title = os.environ['PLOT_'+plvar+'_RMSE_TITLE'] + output_dir = os.environ['PLOT_OUTPUT_DIR'] + bias_output_file = os.environ.get('PLOT_'+plvar+'_BIAS_OUTPUT_FILE','bias_plot.png') + rmse_output_file = os.environ.get('PLOT_'+plvar+'_RMSE_OUTPUT_FILE','rmse_plot.png') + plot_bias_output_file = os.path.join(output_dir,bias_output_file) + plot_rmse_output_file = os.path.join(output_dir,rmse_output_file) + + """ + Make plot output directory if it doesn't exist + """ + if not os.path.exists(output_dir): + os.makedirs(output_dir) + + """ + Read the list of files + """ + stat_filetxt = os.environ.get('METPLUS_FILELIST_STAT_INPUT','') + with open(stat_filetxt) as sf: + stat_infiles = sf.read().splitlines() + # Remove the first line if it's there + if (stat_infiles[0] == 'file_list'): + stat_infiles = stat_infiles[1:] + + """ + Read the first file and set up arrays + """ + fleads = len(stat_infiles) + dfin = pd.DataFrame(pd.read_csv(stat_infiles[0],delim_whitespace=True,header=0)) + dfin['FCST_LEV'] = dfin['FCST_LEV'].str.replace('P', '') + dfin['FCST_LEV'] = dfin['FCST_LEV'].astype('float64') + dfin = dfin.sort_values('FCST_LEV') + flvls = len(dfin) + plevels = np.empty([fleads,flvls],dtype=float) + pleads = np.empty([fleads,flvls],dtype=float) + prmse = np.empty([fleads,flvls],dtype=float) + pme = np.empty([fleads,flvls],dtype=float) + plevels[0,:] = dfin['FCST_LEV'].to_numpy() + pleads[0,:] = dfin['FCST_LEAD'].to_numpy()/10000 + prmse[0,:] = dfin['RMSE'].astype('float64') + pme[0,:] = dfin['ME'].astype('float64') + + """ + Read in the rest of the data + """ + for i in range(1,len(stat_infiles)): + df = pd.DataFrame(pd.read_csv(stat_infiles[i],delim_whitespace=True,header=0)) + df['FCST_LEV'] = df['FCST_LEV'].str.replace('P', '') + df['FCST_LEV'] = df['FCST_LEV'].astype('float64') + dfnew = df.sort_values('FCST_LEV') + plevels[i,:] = dfnew['FCST_LEV'].to_numpy() + #pleads[i] = dfnew['FCST_LEAD'].to_numpy()[0]/10000 + pleads[i,:] = dfnew['FCST_LEAD'].to_numpy()/10000 + prmse[i,:] = dfnew['RMSE'].astype('float64') + pme[i,:] = dfnew['ME'].astype('float64') + + """ + Create plots + """ + print(plot_bias_levels) + print(plot_rmse_levels) + plot_polar_bias(pleads,plevels,pme,plot_bias_output_file,plot_bias_title,plot_bias_levels) + plot_polar_rmse(pleads,plevels,prmse,plot_rmse_output_file,plot_rmse_title,plot_rmse_levels) + + +if __name__ == '__main__': + main() diff --git a/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/polar_t_u_driver.py b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/polar_t_u_driver.py new file mode 100755 index 0000000000..87e2e433c5 --- /dev/null +++ b/parm/use_cases/model_applications/s2s_stratosphere/UserScript_fcstGFS_obsERA_StratospherePolar/polar_t_u_driver.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 + +""" +Create Polar Cap Temperatures and Polar Vortex Winds + +""" +import os +import sys +import datetime +import numpy as np +import metcalcpy.pre_processing.directional_means as directional_means +import METreadnc.util.read_netcdf as read_netcdf +from metcalcpy.util.write_mpr import write_mpr_file + + +def main(): + """ + Read arguments + """ + timevar = sys.argv[1] + leadvar = sys.argv[2] + + """ + Read METplus filename lists + """ + obs_filetxt = os.environ.get('METPLUS_FILELIST_OBS_INPUT','') + fcst_filetxt = os.environ.get('METPLUS_FILELIST_FCST_INPUT','') + + with open(obs_filetxt) as ol: + obs_infiles = ol.read().splitlines() + # Remove the first line if it's there + if (obs_infiles[0] == 'file_list'): + obs_infiles = obs_infiles[1:] + with open(fcst_filetxt) as fl: + fcst_infiles = fl.read().splitlines() + # Remove the first line if it's there + if (fcst_infiles[0] == 'file_list'): + fcst_infiles = fcst_infiles[1:] + + output_dir = os.environ['OUTPUT_DIR'] + full_output_dir = os.path.join(output_dir,'mpr') + + """ + Read dataset + """ + file_reader = read_netcdf.ReadNetCDF() + dsO = file_reader.read_into_xarray(obs_infiles)[0] + dsO = dsO.rename({'lat':'latitude', + 'lon':'longitude'}) + file_reader2 = read_netcdf.ReadNetCDF() + dsF = file_reader2.read_into_xarray(fcst_infiles)[0] + dsF = dsF.rename({'lat':'latitude', + 'lon':'longitude'}) + + """ + Limit Dataset to 100 - 1 hPa + """ + dsO = dsO.sel(pres=slice(1,100)) + dsF = dsF.sel(pres=slice(1,100)) + + + """ + Create Polar Cap Temparatures for Forecast and Obs + """ + TzmO = directional_means.zonal_mean(dsO.T) + TzmO.assign_coords(lat=("latitude",dsO.latitude.values[:,0])) + TO_6090 = directional_means.meridional_mean(TzmO, 60, 90) + TzmF = directional_means.zonal_mean(dsF.T) + TzmF.assign_coords(lat=("latitude",dsF.latitude.values[:,0])) + TF_6090 = directional_means.meridional_mean(TzmF, 60, 90) + + """ + Create Polar Vortex Winds + """ + UzmO = directional_means.zonal_mean(dsO.u) + UzmO.assign_coords(lat=("latitude",dsO.latitude.values[:,0])) + UO_6090 = directional_means.meridional_mean(UzmO, 50, 80) + UzmF = directional_means.zonal_mean(dsF.u) + UzmF.assign_coords(lat=("latitude",dsF.latitude.values[:,0])) + UF_6090 = directional_means.meridional_mean(UzmF, 50, 80) + + + """ + Add P to the levels since they are pressure levels + """ + obs_lvls = ['P'+str(int(op)) for op in dsO.pres.values] + obs_lvls2 = [str(int(op)) for op in dsO.pres.values] + fcst_lvls = ['P'+str(int(fp)) for fp in dsF.pres.values] + + """ + Write output MPR files + """ + dlength1 = len(TO_6090[0,:]) + dlength = dlength1*2 + modname = os.environ.get('MODEL_NAME','GFS') + maskname = os.environ.get('MASK_NAME','FULL') + datetimeindex = dsF.indexes[timevar].to_datetimeindex() + for i in range(len(datetimeindex)): + valid_str = datetimeindex[i].strftime('%Y%m%d_%H%M%S') + leadstr = str(int(leadvar)).zfill(2)+'0000' + outobs = np.concatenate((TO_6090[i,:].values,UO_6090[i,:].values)) + outfcst = np.concatenate((TF_6090[i,:].values,UF_6090[i,:].values)) + write_mpr_file(outfcst,outobs,[0.0]*dlength,[0.0]*dlength,[leadstr]*dlength,[valid_str]*dlength, + ['000000']*dlength,[valid_str]*dlength,modname,'NA',['PolarCapT']*dlength1+['PolarVortexU']*dlength1, + ['K']*dlength1+['m/s']*dlength1,fcst_lvls*2,['PolarCapT']*dlength1+['PolarVortexU']*dlength1, + ['K']*dlength1+['m/s']*dlength1,obs_lvls*2,maskname,obs_lvls2*2,full_output_dir,'polar_cap_T_stat_'+modname) + + + + +if __name__ == '__main__': + main() diff --git a/ush/run_metplus.py b/ush/run_metplus.py index 482c67e81f..9886e1119b 100755 --- a/ush/run_metplus.py +++ b/ush/run_metplus.py @@ -16,13 +16,14 @@ f-string instead of the useful error message. """ -import os +from os.path import abspath, join, dirname, realpath, basename +from os import pardir import sys import traceback +################################################################################ # add metplus directory to path so the wrappers and utilities can be found -sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), - os.pardir))) +sys.path.insert(0, abspath(join(dirname(realpath(__file__)), pardir))) import produtil.setup @@ -44,8 +45,7 @@ def main(): return False # warn if calling master_metplus.py - script_name = os.path.basename(__file__) - if script_name == 'master_metplus.py': + if basename(__file__) == 'master_metplus.py': msg = ("master_metplus.py has been renamed to run_metplus.py. " "This script name will be removed in a future version.") config.logger.warning(msg) @@ -56,11 +56,7 @@ def main(): def usage(): - """! How to call this script. - """ - - filename = os.path.basename(__file__) - + """!How to call this script.""" print (''' Usage: %s arg1 arg2 arg3 -h|--help Display this usage statement @@ -69,7 +65,7 @@ def usage(): /path/to/parmfile.conf -- Specify custom configuration file to use section.option=value -- override conf options on the command line -'''%(filename)) +'''%(basename(__file__))) sys.exit(2)