Point-Stat, Stat-Analysis, UserScript, DataIngest: CREDIT and GFS point statistics, Data Download, Plots

model_applications/medium_range/PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime.conf

Scientific Objective

This use case is an example for verification within RAL to illustrate how to compare two models and also how to download data automatically. The use case was originally set up to be run in real-time using the now keyword in VALID_BEG and VALID_END. However, a specified date is provided used here for our automated testing. The case demonstrates how to run statistics for two models, NSF NCAR Community Research Earth Digital Intelligence Twin (CREDIT) and GFS, and how to make plots of continuous statistics (ME, MAE and RMSE) and categorical statistics (CSI and FBIAS) on some of the variables. In contrast to the GridStat_fcstCREDIT_GFS_obsGFS_6hrRealtime use case, this case uses point observations whereas that one used gridded observations. Also, that use case shows how to process multiple valid times while this one uses only a single valid time.

Version Added

METplus version 6.2

Datasets

Forecast: CREDIT ~0.28 degree model and GFS 0.25 degree model

Observation: GDAS

Climatology: None

Location: The CREDIT model data required for this use case can be found in a sample data tarball. Each use case category will have one or more sample data tarballs. It is only necessary to download the tarball with the use case’s dataset and not the entire collection of sample data. Click here to access the METplus releases page and download sample data for the appropriate release: https://github.com/dtcenter/METplus/releases This tarball should be unpacked into the directory that you will set the value of INPUT_BASE. See Running METplus section for more information.

The GFS model data and GDAS observations are downloaded automatically. Make sure you have an internet connection.

METplus Components

This use case calls DataIngest once, PointStat 3 times, StatAnalysis once, and UserScript 4 times. One of the PointStat calls is for the CREDIT model and 2 are for the GFS model (one for the surface data and one for the upper air data). The 4 UserScripts require METcalcpy, METplotpy, and METdataio are required to run this use case. The METcalcpy scripts accessed include the following:

  • metcalcpy/util/read_env_vars_in_config.py

The METplopty scrips accessed include the following:

  • metplotpy/plots/line/line.py

The METdataio scripts accessed include the following:

  • METdbLoad/ush/read_data_files.py

  • METdbLoad/ush/read_load_xml.py

  • METreformat/write_stat_ascii.py

METplus Workflow

Beginning time (VALID_BEG): 2025-09-24 00Z

End time (VALID_END): 2025-09-24 00Z

Increment between beginning and end times (VALID_INCREMENT): 6 hours

Sequence of forecast leads to process (LEAD_SEQ): 0 - 120 in 6 hour intervals

DataIngest, PointStat, and StatAnalysis tools are run for each time, whereas StatAnalysis is run once. This example loops by valid times. It processes 20 lead times for 1 valid time for a total of 20 runs. All 4 UserScripts are each run once. The first UserScript reformats the PointStat CNT output while the second reformats the PointStat CTS output so that they can be used for plotting. The third and fourth UserScript calls creates plots, one for the CNT output and the other for the CTS output.

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, e.g. parm/use_cases/model_applications/medium_range/PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime.conf

[config]

# 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 = DataIngest, PB2NC(gdas), PointStat(credit), PointStat(gfs_surface), PointStat(gfs_upper_air), StatAnalysis, UserScript(reformat_CNT), UserScript(reformat_CTS), UserScript(plot_CNT), UserScript(plot_CTS)


###
# 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%H
VALID_BEG = 2025092400
VALID_END = 2025092400
VALID_INCREMENT = 6H

LEAD_SEQ = begin_end_incr(6, 120, 6)


###
# DataIngest File I/O for DataIngets, PB2NC, and PointStat
# https://metplus.readthedocs.io/en/latest/Users_Guide/systemconfiguration.html#directory-and-filename-template-info
###

DATA_INGEST_1_INPUT_TEMPLATE = https://dtcenter.ucar.edu/dfiles/code/METplus/DataIngest_input/GDAS/{valid?fmt=%Y%m%d_%H%M}.prepbufr.nr
DATA_INGEST_1_OUTPUT_TEMPLATE = {OUTPUT_BASE}/data_ingest/GDAS/{valid?fmt=%Y%m%d}/{valid?fmt=%Y%m%d_%H%M}.prepbufr.nr
DATA_INGEST_1_SKIP_IF_OUTPUT_EXISTS = True
DATA_INGEST_1_AUTO_DECOMPRESS = False

DATA_INGEST_2_INPUT_TEMPLATE = https://dtcenter.ucar.edu/dfiles/code/METplus/DataIngest_input/GFS/{init?fmt=%Y%m%d%H}/gfs.t{init?fmt=%H}z.sfluxgrbf{lead?fmt=%HHH}.grib2
DATA_INGEST_2_OUTPUT_TEMPLATE = {OUTPUT_BASE}/data_ingest/GFS/{init?fmt=%Y%m%d%H}/gfs.t{init?fmt=%H}z.sfluxgrbf{lead?fmt=%HHH}.grib2
DATA_INGEST_2_SKIP_IF_OUTPUT_EXISTS = True
DATA_INGEST_2_AUTO_DECOMPRESS = False

DATA_INGEST_3_INPUT_TEMPLATE = https://dtcenter.ucar.edu/dfiles/code/METplus/DataIngest_input/GFS/{init?fmt=%Y%m%d%H}/gfs.t{init?fmt=%H}z.pgrb2.0p25.f{lead?fmt=%HHH}
DATA_INGEST_3_OUTPUT_TEMPLATE = {OUTPUT_BASE}/data_ingest/GFS/{init?fmt=%Y%m%d%H}/gfs.t{init?fmt=%H}z.pgrb2.0p25.f{lead?fmt=%HHH}
DATA_INGEST_3_SKIP_IF_OUTPUT_EXISTS = True
DATA_INGEST_3_AUTO_DECOMPRESS = False

PB2NC_INPUT_DIR =
PB2NC_INPUT_TEMPLATE = {DATA_INGEST_1_OUTPUT_TEMPLATE}

PB2NC_OUTPUT_DIR = {OUTPUT_BASE}/GDAS
PB2NC_OUTPUT_TEMPLATE = prepbufr.gdas.{valid?fmt=%Y%m%d%H}.nc

OBS_POINT_STAT_INPUT_DIR = {PB2NC_OUTPUT_DIR}
OBS_POINT_STAT_INPUT_TEMPLATE = {PB2NC_OUTPUT_TEMPLATE}


###
# PB2NC Settings
# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#pb2nc
###

OBS_PB2NC_WINDOW_BEGIN = -2700
OBS_PB2NC_WINDOW_END = 2700

PB2NC_SKIP_IF_OUTPUT_EXISTS = False

PB2NC_QUALITY_MARK_THRESH = 3

PB2NC_PB_REPORT_TYPE = 120, 122, 132, 180, 181, 182, 183, 187, 192, 193, 194, 220, 221, 222, 232, 280, 281, 282, 284, 287, 292, 293, 294

PB2NC_LEVEL_CATEGORY = 0, 1, 4, 6

PB2NC_GRID =
PB2NC_POLY =
PB2NC_STATION_ID =
PB2NC_MESSAGE_TYPE =

PB2NC_OBS_BUFR_VAR_LIST = QOB, TOB, ZOB, UOB, VOB, POB

PB2NC_TIME_SUMMARY_FLAG = False
PB2NC_TIME_SUMMARY_BEG = 000000
PB2NC_TIME_SUMMARY_END = 235959
PB2NC_TIME_SUMMARY_VAR_NAMES = PMO,TOB,TDO,UOB,VOB,PWO,TOCC
PB2NC_TIME_SUMMARY_TYPES = min, max, range, mean, stdev, median, p80


###
# PointStat Common Settings
# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#pointstat
###

POINT_STAT_ONCE_PER_FIELD = False

POINT_STAT_CONFIG_FILE ={PARM_BASE}/met_config/PointStatConfig_wrapped

POINT_STAT_INTERP_TYPE_METHOD = BILIN
POINT_STAT_INTERP_TYPE_WIDTH = 2

POINT_STAT_OUTPUT_FLAG_CTC = STAT
POINT_STAT_OUTPUT_FLAG_CTS = STAT
POINT_STAT_OUTPUT_FLAG_CNT = STAT
POINT_STAT_OUTPUT_FLAG_SL1L2 = STAT
POINT_STAT_OUTPUT_FLAG_VL1L2 = STAT
POINT_STAT_OUTPUT_FLAG_VCNT = STAT
POINT_STAT_OUTPUT_FLAG_MPR = NONE

OBTYPE = GDAS

POINT_STAT_MESSAGE_TYPE = ADPSFC, SFCSHP, ADPUPA

OBS_POINT_STAT_WINDOW_BEGIN = -1800
OBS_POINT_STAT_WINDOW_END = 1800


# StatAnalysis Common Settings
###
# StatAnalysis File I/O
# https://metplus.readthedocs.io/en/latest/Users_Guide/systemconfiguration.html#directory-and-filename-template-info
###

MODEL1_STAT_ANALYSIS_LOOKIN_DIR = {OUTPUT_BASE}/point_stat/CREDIT/6h
MODEL2_STAT_ANALYSIS_LOOKIN_DIR = {OUTPUT_BASE}/point_stat/GFS

STAT_ANALYSIS_OUTPUT_DIR = {OUTPUT_BASE}/StatAnalysis/6h

MODEL1_STAT_ANALYSIS_OUT_STAT_TEMPLATE = {model?fmt=%s}_GDAS_{fcst_valid_beg?fmt=%Y%m%d%H}_{fcst_valid_end?fmt=%Y%m%d%H}_allleads
MODEL2_STAT_ANALYSIS_OUT_STAT_TEMPLATE = {MODEL1_STAT_ANALYSIS_OUT_STAT_TEMPLATE}


###
# StatAnalysis Settings
# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#statanalysis
###

STAT_ANALYSIS_CONFIG_FILE = {PARM_BASE}/met_config/STATAnalysisConfig_wrapped

MODEL1 = CREDIT
MODEL2 = GFS

# Stat-Analysis Jobs
STAT_ANALYSIS_JOB1 = -job aggregate_stat -line_type SL1L2 -out_line_type CNT -by FCST_VAR,FCST_LEAD,VX_MASK -out_stat [out_stat_file]_all_stations_allValidHours_CNT.stat

STAT_ANALYSIS_JOB2 =  -job aggregate_stat -line_type CTC -out_line_type CTS -by FCST_VAR,VX_MASK,FCST_LEAD,FCST_THRESH -out_stat [out_stat_file]_all_stations_allValidHours_CTS.stat

STAT_ANALYSIS_JOB3 = -job aggregate_stat -line_type VL1L2 -out_line_type VCNT -by FCST_VAR,FCST_LEAD,VX_MASK -out_stat [out_stat_file]_all_stations_hourly_VCNT.stat


MODEL_LIST = {MODEL1},{MODEL2}
GROUP_LIST_ITEMS = 
LOOP_LIST_ITEMS = MODEL_LIST


[gdas]
# Convert only 1 set of obs
LEAD_SEQ = 0


[credit]
###
# PointStat File I/O
# https://metplus.readthedocs.io/en/latest/Users_Guide/systemconfiguration.html#directory-and-filename-template-info
###

FCST_POINT_STAT_INPUT_DIR = {INPUT_BASE}/model_applications/medium_range/PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime/creditout/6h
FCST_POINT_STAT_INPUT_TEMPLATE = {init?fmt=%Y%m%d%H}/{init?fmt=%Y-%m-%dT%H}Z/pred_{init?fmt=%Y-%m-%dT%H}Z_{lead?fmt=%HHH}.nc

POINT_STAT_OUTPUT_DIR = {OUTPUT_BASE}/point_stat/CREDIT/6h
POINT_STAT_OUTPUT_TEMPLATE = {init?fmt=%Y%m%d%H}
POINT_STAT_OUTPUT_PREFIX = CREDIT


###
# PointStat Field Info
# https://metplus.readthedocs.io/en/latest/Users_Guide/systemconfiguration.html#field-info
###

FCST_POINT_STAT_VAR1_NAME = t2m
FCST_POINT_STAT_VAR1_LEVELS = "(0,*,*)"
FCST_POINT_STAT_VAR1_THRESH = >273
FCST_POINT_STAT_VAR1_OPTIONS = set_attr_lead = "{lead?fmt=%HH}"; set_attr_name = "TMP";
OBS_POINT_STAT_VAR1_NAME = TMP
OBS_POINT_STAT_VAR1_LEVELS = Z2
OBS_POINT_STAT_VAR1_THRESH = >273

FCST_POINT_STAT_VAR2_NAME = Z500
FCST_POINT_STAT_VAR2_LEVELS = "(0,*,*)"
FCST_POINT_STAT_VAR2_OPTIONS = convert(x) = x / 9.81; set_attr_lead = "{lead?fmt=%HH}"; set_attr_units = "gpm";
OBS_POINT_STAT_VAR2_NAME = HGT
OBS_POINT_STAT_VAR2_LEVELS = P500
OBS_POINT_STAT_VAR2_OPTIONS = set_attr_name = "Z500";

FCST_POINT_STAT_VAR3_NAME = T500
FCST_POINT_STAT_VAR3_LEVELS = "(0,*,*)"
FCST_POINT_STAT_VAR3_OPTIONS = set_attr_lead = "{lead?fmt=%HH}";
OBS_POINT_STAT_VAR3_NAME = TMP
OBS_POINT_STAT_VAR3_LEVELS = P500
OBS_POINT_STAT_VAR3_OPTIONS = set_attr_name = "T500";

FCST_POINT_STAT_VAR4_NAME = Q
FCST_POINT_STAT_VAR4_LEVELS = "(0,15,*,*)"
FCST_POINT_STAT_VAR4_OPTIONS = set_attr_lead = "{lead?fmt=%HH}"; set_attr_name = "SPFH";
OBS_POINT_STAT_VAR4_NAME = SPFH
OBS_POINT_STAT_VAR4_LEVELS = Z2

FCST_POINT_STAT_VAR5_NAME = U
FCST_POINT_STAT_VAR5_LEVELS = "(0,15,*,*)"
FCST_POINT_STAT_VAR5_OPTIONS = is_u_wind = TRUE; set_attr_lead = "{lead?fmt=%HH}"; set_attr_name = "UGRD";
OBS_POINT_STAT_VAR5_NAME = UGRD
OBS_POINT_STAT_VAR5_LEVELS = Z10

FCST_POINT_STAT_VAR6_NAME = V
FCST_POINT_STAT_VAR6_LEVELS = "(0,15,*,*)"
FCST_POINT_STAT_VAR6_OPTIONS = is_v_wind = TRUE; set_attr_lead = "{lead?fmt=%HH}"; set_attr_name = "VGRD";
OBS_POINT_STAT_VAR6_NAME = VGRD
OBS_POINT_STAT_VAR6_LEVELS = Z10

MODEL = CREDIT


[gfs_surface]
###
# PointStat File I/O
# https://metplus.readthedocs.io/en/latest/Users_Guide/systemconfiguration.html#directory-and-filename-template-info
###

FCST_POINT_STAT_INPUT_DIR = 
FCST_POINT_STAT_INPUT_TEMPLATE = {DATA_INGEST_2_OUTPUT_TEMPLATE}

POINT_STAT_OUTPUT_DIR = {OUTPUT_BASE}/point_stat/GFS
POINT_STAT_OUTPUT_TEMPLATE = {init?fmt=%Y%m%d%H}
POINT_STAT_OUTPUT_PREFIX = GFS_surface


###
# PointStat Field Info
# https://metplus.readthedocs.io/en/latest/Users_Guide/systemconfiguration.html#field-info
###

FCST_POINT_STAT_VAR1_NAME = TMP
FCST_POINT_STAT_VAR1_LEVELS = Z2
FCST_POINT_STAT_VAR1_THRESH = >273
OBS_POINT_STAT_VAR1_NAME = TMP
OBS_POINT_STAT_VAR1_LEVELS = Z2
OBS_POINT_STAT_VAR1_THRESH = >273

FCST_POINT_STAT_VAR2_NAME = SPFH
FCST_POINT_STAT_VAR2_LEVELS = Z2
OBS_POINT_STAT_VAR2_NAME = SPFH
OBS_POINT_STAT_VAR2_LEVELS = Z2

FCST_POINT_STAT_VAR3_NAME = UGRD
FCST_POINT_STAT_VAR3_LEVELS = Z10
FCST_POINT_STAT_VAR3_OPTIONS = is_u_wind = TRUE; 
OBS_POINT_STAT_VAR3_NAME = UGRD
OBS_POINT_STAT_VAR3_LEVELS = Z10

FCST_POINT_STAT_VAR4_NAME = VGRD
FCST_POINT_STAT_VAR4_LEVELS = Z10
FCST_POINT_STAT_VAR4_OPTIONS = is_v_wind = TRUE; 
OBS_POINT_STAT_VAR4_NAME = VGRD
OBS_POINT_STAT_VAR4_LEVELS = Z10

MODEL = GFS


[gfs_upper_air]
###
# PointStat File I/O
# https://metplus.readthedocs.io/en/latest/Users_Guide/systemconfiguration.html#directory-and-filename-template-info
###

FCST_POINT_STAT_INPUT_DIR =
FCST_POINT_STAT_INPUT_TEMPLATE = {DATA_INGEST_3_OUTPUT_TEMPLATE}

POINT_STAT_OUTPUT_DIR = {OUTPUT_BASE}/point_stat/GFS
POINT_STAT_OUTPUT_TEMPLATE = {init?fmt=%Y%m%d%H}
POINT_STAT_OUTPUT_PREFIX = GFS_upper_air

###
# PointStat Field Info
# https://metplus.readthedocs.io/en/latest/Users_Guide/systemconfiguration.html#field-info
###
FCST_POINT_STAT_VAR1_NAME = HGT
FCST_POINT_STAT_VAR1_LEVELS = P500
FCST_POINT_STAT_VAR1_OPTIONS = set_attr_name = "Z500";
OBS_POINT_STAT_VAR1_NAME = HGT
OBS_POINT_STAT_VAR1_LEVELS = P500
OBS_POINT_STAT_VAR1_OPTIONS = set_attr_name = "Z500";

FCST_POINT_STAT_VAR2_NAME = TMP
FCST_POINT_STAT_VAR2_LEVELS = P500
FCST_POINT_STAT_VAR2_OPTIONS = set_attr_name = "T500";
OBS_POINT_STAT_VAR2_NAME = TMP 
OBS_POINT_STAT_VAR2_LEVELS = P500
OBS_POINT_STAT_VAR2_OPTIONS = set_attr_name = "T500";

MODEL = GFS


[reformat_CNT]
###
# UserScript Settings to reformat the CNT linetype
# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#userscript
###

USER_SCRIPT_RUNTIME_FREQ = RUN_ONCE
USER_SCRIPT_COMMAND = {PARM_BASE}/use_cases/model_applications/medium_range/PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime/reformat_linetype.py {PARM_BASE}/use_cases/model_applications/medium_range/PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime/reformat_CNT.yaml


[reformat_CTS]
###
# UserScript Settings to reformat the CTS linetype
# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#userscript
###

USER_SCRIPT_RUNTIME_FREQ = RUN_ONCE
USER_SCRIPT_COMMAND = {PARM_BASE}/use_cases/model_applications/medium_range/PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime/reformat_linetype.py {PARM_BASE}/use_cases/model_applications/medium_range/PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime/reformat_CTS.yaml


[plot_CNT]
###
# UserScript Settings to create the CNT plots
# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#userscript
###

USER_SCRIPT_RUNTIME_FREQ = RUN_ONCE
USER_SCRIPT_COMMAND = {PARM_BASE}/use_cases/model_applications/medium_range/PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime/plot_line_stats.py


[plot_CTS]
###
# UserScript Settings to create the CTS plots
# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#userscript
###

USER_SCRIPT_RUNTIME_FREQ = RUN_ONCE
USER_SCRIPT_COMMAND = {PARM_BASE}/use_cases/model_applications/medium_range/PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime/plot_line_stats_CTS.py


[user_env_vars]
# This section contains some needed variables for the reformatting and plotting

# Paths to METdataio, METcalcpy, and METplotpy as needed for the use case
METDATAIO_BASE = {METPLUS_BASE}/../METdataio
METCALCPY_BASE = {METPLUS_BASE}/../METcalcpy
METPLOTPY_BASE = {METPLUS_BASE}/../METplotpy
PYTHONPATH = {METDATAIO_BASE}:{METDATAIO_BASE}/METdbLoad:{METDATAIO_BASE}/METdbLoad/ush:{METDATAIO_BASE}/METreformat:{METCALCPY_BASE}:{METCALCPY_BASE}/metcalcpy:{METPLOTPY_BASE}:{METPLOTPY_BASE}/metplotpy/plots


###
# Settings for the reformatting of the CNT linetype, to later be used for plotting
### 
# Input directory where the .stat files you need to reformat are located 
REFORMAT_CNT_INPUT_DIR = {OUTPUT_BASE}/StatAnalysis/6h

# Output directory to store the reformatted data
REFORMAT_CNT_OUTPUT_DIR = {OUTPUT_BASE}/reformatted/6h

# Name of the output file containing reformatted data
REFORMAT_CNT_OUTPUT_FILENAME = reformat_CNT_6h.data

# Line type to reformat
# Currently support FHO, CTC, CTS, CNT, SL1L2, VL1L2, PCT, MCTC, VCNT, ECNT, RHIST, TCDiag, and MPR line types
REFORMAT_CNT_LINETYPE = CNT


###
# Settings for the reformatting of the CTS linetype, to later be used for plotting
### 
# Input directory where the .stat files you need to reformat are located 
REFORMAT_CTS_INPUT_DIR = {REFORMAT_CNT_INPUT_DIR}

# Output directory to store the reformatted data
REFORMAT_CTS_OUTPUT_DIR = {REFORMAT_CNT_OUTPUT_DIR}

# Name of the output file containing reformatted data
REFORMAT_CTS_OUTPUT_FILENAME = reformat_CTS_6h.data

# Line type to reformat
# Currently support FHO, CTC, CTS, CNT, SL1L2, VL1L2, PCT, MCTC, VCNT, ECNT, RHIST, TCDiag, and MPR line types
REFORMAT_CTS_LINETYPE = CTS


###
# Settings for creating the plots of ME, MAE, and RMSE for the CNT Data
###
# Directory where the YAML configurations for plotting are located
PLOTTING_CNT_YAML_CONFIG_DIR = {PARM_BASE}/use_cases/model_applications/medium_range/PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime

# YAML Configuration file list
PLOTTING_CNT_YAML_CONFIG_FILE_LIST = custom_2line_6h.yaml

PLOTTING_CNT_FCST_STAT_LIST = MAE, ME, RMSE

# A list of variables to be plotted
PLOTTING_CNT_FCST_VAR_LIST = TMP, PRES, Z500, T500

# A list of the long names to be used in the plotting titles
# This should be in the same order as PLOTTING_INPUT_FCST_VAR_LIST
PLOTTING_CNT_FCST_VAR_NAME_LIST = 2m Temperature, Surface Pressure, 500mb Height, 500mb Temperature

# A list of variable units to be used in the plotting axis labels
# This should be in the same order as PLOTTING_INPUT_FCST_VAR_LIST
PLOTTING_CNT_FCST_VAR_UNITS_LIST = K, hPa, gpm, K

# A list of the long names to be used in the plotting titles
PLOTTING_CNT_VX_MASK_LIST = FULL

#Input for plotting (this is the Reformatted data above 
PLOTTING_CNT_STAT_INPUT = {REFORMAT_CNT_OUTPUT_DIR}/{REFORMAT_CNT_OUTPUT_FILENAME}

# Output directory for plots
PLOTTING_CNT_OUTPUT_DIR = {OUTPUT_BASE}/plots/6h

# Log file for the plotting
PLOTTING_CNT_LOG_FILENAME = {LOG_DIR}/plotting_cnt_6h.log


###
# Settings for creating the plots of FBIAS and CSI for the CTS Data
###
# Directory where the YAML configurations for plotting are located
PLOTTING_CTS_YAML_CONFIG_DIR = {PARM_BASE}/use_cases/model_applications/medium_range/PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime

# YAML Configuration file list
PLOTTING_CTS_YAML_CONFIG_FILE_LIST = custom_2line_cat_6h.yaml

PLOTTING_CTS_FCST_STAT_LIST = FBIAS, CSI

# A list of variables to be plotted
PLOTTING_CTS_FCST_VAR_LIST = TMP

# A list of the long names to be used in the plotting titles
# This should be in the same order as PLOTTING_INPUT_FCST_VAR_LIST
PLOTTING_CTS_FCST_VAR_NAME_LIST = 2m Temperature

# A list of variable units to be used in the plotting axis labels
# This should be in the same order as PLOTTING_INPUT_FCST_VAR_LIST
PLOTTING_CTS_FCST_VAR_UNITS_LIST = K

# A list of the long names to be used in the plotting titles
PLOTTING_CTS_VX_MASK_LIST = FULL

#Input for plotting (this is the Reformatted data above 
PLOTTING_CTS_STAT_INPUT = {REFORMAT_CTS_OUTPUT_DIR}/{REFORMAT_CTS_OUTPUT_FILENAME}

# Output directory for plots
PLOTTING_CTS_OUTPUT_DIR = {OUTPUT_BASE}/plots/6h

# Log file for the plotting
PLOTTING_CTS_LOG_FILENAME = {LOG_DIR}/plotting_cts_6h.log

MET Configuration

METplus sets environment variables based on user settings in the METplus configuration file. See 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: Overriding Unsupported MET config file settings

GridStatConfig_wrapped
////////////////////////////////////////////////////////////////////////////////
//
// Grid-Stat configuration file.
//
// For additional information, see the MET_BASE/config/README file.
//
////////////////////////////////////////////////////////////////////////////////

//
// Output model name to be written
//
// model =
${METPLUS_MODEL}

//
// Output description to be written
// May be set separately in each "obs.field" entry
//
// desc =
${METPLUS_DESC}

//
// Output observation type to be written
//
// obtype =
${METPLUS_OBTYPE}

////////////////////////////////////////////////////////////////////////////////

//
// Verification grid
//
// regrid = {
${METPLUS_REGRID_DICT}

////////////////////////////////////////////////////////////////////////////////

//censor_thresh =
${METPLUS_CENSOR_THRESH}
//censor_val =
${METPLUS_CENSOR_VAL}
//cat_thresh =
${METPLUS_CAT_THRESH}
cnt_thresh  	 = [ NA ];
cnt_logic   	 = UNION;
wind_thresh 	 = [ NA ];
wind_logic  	 = UNION;
eclv_points      = 0.05;
//nc_pairs_var_name =
${METPLUS_NC_PAIRS_VAR_NAME}
nc_pairs_var_suffix = "";
//hss_ec_value =
${METPLUS_HSS_EC_VALUE}

rank_corr_flag   = FALSE;

//
// Forecast and observation fields to be verified
//
fcst = {
  ${METPLUS_FCST_FILE_TYPE}
  ${METPLUS_FCST_FIELD}
  ${METPLUS_FCST_CLIMO_MEAN_DICT}
  ${METPLUS_FCST_CLIMO_STDEV_DICT}
}
obs = {
  ${METPLUS_OBS_FILE_TYPE}
  ${METPLUS_OBS_FIELD}
  ${METPLUS_OBS_CLIMO_MEAN_DICT}
  ${METPLUS_OBS_CLIMO_STDEV_DICT}
}

////////////////////////////////////////////////////////////////////////////////

//
// Climatology mean data
//
//climo_mean = {
${METPLUS_CLIMO_MEAN_DICT}


//climo_stdev = {
${METPLUS_CLIMO_STDEV_DICT}

//
// May be set separately in each "obs.field" entry
//
//climo_cdf = {
${METPLUS_CLIMO_CDF_DICT}

////////////////////////////////////////////////////////////////////////////////

//
// Verification masking regions
//
// mask = {
${METPLUS_MASK_DICT}

////////////////////////////////////////////////////////////////////////////////

//
// Confidence interval settings
//
ci_alpha  = [ 0.05 ];

boot = {
   interval = PCTILE;
   rep_prop = 1.0;
   n_rep    = 0;
   rng      = "mt19937";
   seed     = "";
}

////////////////////////////////////////////////////////////////////////////////

//
// Data smoothing methods
//
//interp = {
${METPLUS_INTERP_DICT}

////////////////////////////////////////////////////////////////////////////////

//
// Neighborhood methods
//
nbrhd = {
   field      = BOTH;
   // shape =
   ${METPLUS_NBRHD_SHAPE}
   // width =
   ${METPLUS_NBRHD_WIDTH}
   // cov_thresh =
   ${METPLUS_NBRHD_COV_THRESH}
   vld_thresh = 1.0;
}

////////////////////////////////////////////////////////////////////////////////

//
// Fourier decomposition
// May be set separately in each "obs.field" entry
//
//fourier = {
${METPLUS_FOURIER_DICT}

////////////////////////////////////////////////////////////////////////////////

//
// Gradient statistics
// May be set separately in each "obs.field" entry
//
//gradient = {
${METPLUS_GRADIENT_DICT}

////////////////////////////////////////////////////////////////////////////////

//
// Distance Map statistics
// May be set separately in each "obs.field" entry
//
//distance_map = {
${METPLUS_DISTANCE_MAP_DICT}


////////////////////////////////////////////////////////////////////////////////
// Threshold for SEEPS p1 (Probability of being dry)

//seeps_p1_thresh =
${METPLUS_SEEPS_P1_THRESH}

////////////////////////////////////////////////////////////////////////////////

//
// Statistical output types
//
//output_flag = {
${METPLUS_OUTPUT_FLAG_DICT}

//
// NetCDF matched pairs output file
// May be set separately in each "obs.field" entry
//
// nc_pairs_flag = {
${METPLUS_NC_PAIRS_FLAG_DICT}

////////////////////////////////////////////////////////////////////////////////

//ugrid_dataset =
${METPLUS_UGRID_DATASET}

//ugrid_max_distance_km =
${METPLUS_UGRID_MAX_DISTANCE_KM}

//ugrid_coordinates_file =
${METPLUS_UGRID_COORDINATES_FILE}

////////////////////////////////////////////////////////////////////////////////

//grid_weight_flag =
${METPLUS_GRID_WEIGHT_FLAG}

tmp_dir = "${MET_TMP_DIR}";

// output_prefix =
${METPLUS_OUTPUT_PREFIX}

////////////////////////////////////////////////////////////////////////////////

${METPLUS_TIME_OFFSET_WARNING}
${METPLUS_MET_CONFIG_OVERRIDES}
StatAnalysisConfig_wrapped
////////////////////////////////////////////////////////////////////////////////
//
// STAT-Analysis configuration file.
//
// For additional information, see the MET_BASE/config/README file.
//
////////////////////////////////////////////////////////////////////////////////

//
// Filtering input STAT lines by the contents of each column
//
//model = [
${METPLUS_MODEL}

//desc  = [
${METPLUS_DESC}

//fcst_lead = [
${METPLUS_FCST_LEAD}

//obs_lead  = [
${METPLUS_OBS_LEAD}

//fcst_valid_beg  =
${METPLUS_FCST_VALID_BEG}

//fcst_valid_end  =
${METPLUS_FCST_VALID_END}

fcst_valid_inc  = [];
fcst_valid_exc  = [];

//fcst_valid_hour = [
${METPLUS_FCST_VALID_HOUR}


//obs_valid_beg   =
${METPLUS_OBS_VALID_BEG}

//obs_valid_end   =
${METPLUS_OBS_VALID_END}

obs_valid_inc   = [];
obs_valid_exc   = [];

//obs_valid_hour  = [
${METPLUS_OBS_VALID_HOUR}


//fcst_init_beg   =
${METPLUS_FCST_INIT_BEG}

//fcst_init_end   =
${METPLUS_FCST_INIT_END}

fcst_init_inc   = [];
fcst_init_exc   = [];

//fcst_init_hour  = [
${METPLUS_FCST_INIT_HOUR}


//obs_init_beg    =
${METPLUS_OBS_INIT_BEG}

//obs_init_end    =
${METPLUS_OBS_INIT_END}

obs_init_inc    = [];
obs_init_exc    = [];

//obs_init_hour   = [
${METPLUS_OBS_INIT_HOUR}


//fcst_var = [
${METPLUS_FCST_VAR}
//obs_var  = [
${METPLUS_OBS_VAR}

//fcst_units = [
${METPLUS_FCST_UNITS}
//obs_units  = [
${METPLUS_OBS_UNITS}

//fcst_lev = [
${METPLUS_FCST_LEVEL}
//obs_lev  = [
${METPLUS_OBS_LEVEL}

//obtype = [
${METPLUS_OBTYPE}

//vx_mask = [
${METPLUS_VX_MASK}

//interp_mthd = [
${METPLUS_INTERP_MTHD}

//interp_pnts = [
${METPLUS_INTERP_PNTS}

//fcst_thresh = [
${METPLUS_FCST_THRESH}
//obs_thresh = [
${METPLUS_OBS_THRESH}
//cov_thresh = [
${METPLUS_COV_THRESH}

//alpha = [
${METPLUS_ALPHA}

//line_type = [
${METPLUS_LINE_TYPE}

//column = [
${METPLUS_COLUMN}

//weight = [
${METPLUS_WEIGHT}

////////////////////////////////////////////////////////////////////////////////

//
// Array of STAT-Analysis jobs to be performed on the filtered data
//
//jobs = [
${METPLUS_JOBS}

////////////////////////////////////////////////////////////////////////////////

//
// Confidence interval settings
//
out_alpha = 0.05;

boot = {
   interval = PCTILE;
   rep_prop = 1.0;
   n_rep    = 0;
   rng      = "mt19937";
   seed     = "";
}

////////////////////////////////////////////////////////////////////////////////

//
// WMO mean computation logic
//
wmo_sqrt_stats   = [ "CNT:FSTDEV",  "CNT:OSTDEV",  "CNT:ESTDEV",
                     "CNT:RMSE",    "CNT:RMSFA",   "CNT:RMSOA",
                     "VCNT:FS_RMS", "VCNT:OS_RMS", "VCNT:RMSVE",
                     "VCNT:FSTDEV", "VCNT:OSTDEV" ];

wmo_fisher_stats = [ "CNT:PR_CORR", "CNT:SP_CORR",
                     "CNT:KT_CORR", "CNT:ANOM_CORR" ];

////////////////////////////////////////////////////////////////////////////////

//
// Skill score index options
//
//ss_index_name =
${METPLUS_SS_INDEX_NAME}
//ss_index_vld_thresh =
${METPLUS_SS_INDEX_VLD_THRESH}

////////////////////////////////////////////////////////////////////////////////

//hss_ec_value =
${METPLUS_HSS_EC_VALUE}
rank_corr_flag = FALSE;
vif_flag       = FALSE;

tmp_dir = "${MET_TMP_DIR}";

//version        = "V10.0";

${METPLUS_MET_CONFIG_OVERRIDES}

Python Embedding

This use case does not use Python embedding.

User Scripting

There are three Python scripts used in this use case, called using the “UserScript” keyword in the METplus wrappers PROCESS_LIST configuration item. These scripts provide an interface to the functions in the METdataio, METcalcpy, and METplotpy Python modules of METplus. The functions used in these scripts demonstrate reformatting aggregated StatAnalysis output to meet the format required by METcalcpy and METplotpy, and then plotting that reformatted output using functions from METcalcpy and METplotpy.

The first Python scripts is called reformat_linetype.py. This script takes the aggregated output linetype from Stat Analysis and reformats it so that the data can be plotted. The script takes an input .yaml file of which there are 2, reformat_CNT.yaml and reformat_CTS.yaml. Environment variables in the yaml file are specified in the [user_env_vars] section of the PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime.conf METplus configuration file.

The second Python script is plot_line_stats.py. This script creates line plots for CREDIT and GFS of MAE, ME and RMSE with lead time, using the YAML file custom_2line_6h.yaml. Input variables to this script are also specified in the [user_env_vars] section of the PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime.conf METplus configuration file.

The third Python script is plot_line_stats_CTS.py. This script creates line plots for CREDIT and GFS of CSI and Frequency Bias with lead time, using the YAML file custom_2line_cat_6h.yaml. Input variables to this script are also specified in the [user_env_vars] section of the PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime.conf METplus configuration file.

For more information about YAML configuration options for the line plots shown here, see the METplotpy line plot documentation.

Both Python scripts are located at:

parm/use_cases/model_applications/medium_range/PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime
reformat_linetype.py
#!/usr/bin/env python3


import os
import sys
import time
import logging

from METdbLoad.ush.read_data_files import ReadDataFiles
from METdbLoad.ush.read_load_xml import XmlLoadFile
from METreformat.write_stat_ascii import WriteStatAscii
from metcalcpy.util import read_env_vars_in_config as readconfig


logger = logging.getLogger(__name__)

def main():

    if len(sys.argv) == 2:
        input_config_file = sys.argv[1]
    else:
        print("Must specify exactly one input yaml configuration file.")
        sys.exit(1)

    # Read in the YAML configuration file.  Environment variables in the 
    # configuration file are supported.
    #input_cnt_config_file = os.getenv(input_yaml_file, "reformat_VCNT.yaml")
    settings = readconfig.parse_config(input_config_file)
    logging.info(settings)

    # Replacing the need for an XML specification file, pass in the XMLLoadFile and
    # ReadDataFile parameters
    rdf_obj: ReadDataFiles = ReadDataFiles()
    xml_loadfile_obj: XmlLoadFile = XmlLoadFile(None)

    # Retrieve all the filenames in the data_dir specified in the YAML config file
    load_files = xml_loadfile_obj.filenames_from_template(settings['input_data_dir'],{})
    flags = xml_loadfile_obj.flags
    line_types = xml_loadfile_obj.line_types
    beg_read_data = time.perf_counter()
    rdf_obj.read_data(flags, load_files, line_types)
    end_read_data = time.perf_counter()
    time_to_read = end_read_data - beg_read_data
    logger.info("Time to read input .stat data files using METdbLoad: %f", time_to_read)
    file_df = rdf_obj.stat_data

    # Check if the output directory exists.  If not, make it
    if not os.path.exists(settings['output_dir']):
        os.makedirs(settings['output_dir'])

    # Check if the output file already exists, if so, delete it to avoid
    # appending output from subsequent runs into the same file.
    existing_output_file = os.path.join(settings['output_dir'], settings['output_filename'])
    logger.info("Checking if {existing_output_file}  already exists")
    if os.path.exists(existing_output_file):
        logger.info("Removing existing output file {existing_output_file}")
        os.remove(existing_output_file)

    # Write stat file in ASCII format
    stat_lines_obj: WriteStatAscii = WriteStatAscii(settings, logger)
    stat_lines_obj.write_stat_ascii(file_df, settings)


if __name__ == "__main__":
    main()
plot_line_stats.py
#!/usr/bin/env python3

import os
from time import perf_counter
import logging
import yaml
import metcalcpy.util.read_env_vars_in_config as readconfig
from metplotpy.plots.line import line

def main():

    # Read the input data, input files, and output files
    ploting_stat_list_str = os.environ['PLOTTING_CNT_FCST_STAT_LIST'].split(',')
    plotting_stat_list = [ps.lstrip() for ps in ploting_stat_list_str]
    plotting_vars_str = os.environ['PLOTTING_CNT_FCST_VAR_LIST'].split(',')
    plotting_vars = [pv.lstrip() for pv in plotting_vars_str]
    var_longnames_str = os.environ['PLOTTING_CNT_FCST_VAR_NAME_LIST'].split(',')
    var_longnames = [vl.lstrip() for vl in var_longnames_str]
    var_units_str = os.environ['PLOTTING_CNT_FCST_VAR_UNITS_LIST'].split(',')
    var_units = [vu.lstrip() for vu in var_units_str]
    plotting_masks_str = os.environ['PLOTTING_CNT_VX_MASK_LIST'].split(',')
    plotting_masks = [pm.lstrip() for pm in plotting_masks_str]
    yaml_files_str = os.environ['PLOTTING_CNT_YAML_CONFIG_FILE_LIST'].split(',')
    yaml_files = [yf.lstrip() for yf in yaml_files_str]
    yaml_file_dir = os.environ['PLOTTING_CNT_YAML_CONFIG_DIR']
    plot_output_dir = os.environ['PLOTTING_CNT_OUTPUT_DIR']

    # Make output plot directory if if doesn't exist
    if not os.path.exists(plot_output_dir):
        os.makedirs(plot_output_dir)

    # Check to make sure that the lists are the same size
    if not len(plotting_vars) == len(var_longnames) == len(var_units):
        raise RuntimeError('The length of PLOTTING_CNT_FCST_VAR_LIST must be equal to the lengths of PLOTTING_CNT_FCST_VAR_NAME_LIST and PLOTTING_CNT_FCST_VAR_UNITS_LIST')

    # Loop through the stats
    for s in plotting_stat_list:
        os.environ['PLOTTING_STAT'] = s

        if s == 'MAE':
            os.environ['PLOTTING_STAT_LONG'] = 'Mean Absolute Error'
        elif s == 'ME':
            os.environ['PLOTTING_STAT_LONG'] = 'Mean Error'
        elif s == 'RMSE':
            os.environ['PLOTTING_STAT_LONG'] = 'Root Mean Squared Error'
        else:
            os.environ['PLOTTING_STAT_LONG'] = s

        # Loop through the variables
        for v,n,u in zip(plotting_vars,var_longnames,var_units):

            os.environ['FCST_VAR_VAL1'] = v
            os.environ['PLOTTING_CNT_LONG_VAR'] = n
            os.environ['PLOTTING_CNT_VAR_UNITS'] = u

            # Loop throuth masks
            for m in plotting_masks:

                os.environ['PLOTTING_CNT_OUTPUT_FILENAME'] = os.path.join(plot_output_dir,v+'_'+m)
                os.environ['PLOTTING_CNT_MASK'] = m

                # Loop through data
                for i in yaml_files:

                    # Build yaml config file name
                    os.environ['PLOTTING_CNT_YAML_CONFIG_NAME'] = os.path.join(yaml_file_dir,i)

                    # Read in the YAML configuration file.  Environment variables in
                    # the configuration file are supported.
                    try:
                        input_config_file = os.getenv("PLOTTING_CNT_YAML_CONFIG_NAME", "custom_line.yaml")
                        settings = readconfig.parse_config(input_config_file)
                        logging.info(settings)
                    except yaml.YAMLError as exc:
                        logging.error(exc)

                    try:
                        start = perf_counter()
                        plot = line.Line(settings)
                        plot.save_to_file()
                        plot.write_html()
                        plot.write_output_file()
                        end = perf_counter()
                        execution_time = end - start
                        plot.logger.info(f"Finished creating line plot, execution time: {execution_time} seconds")
                    except ValueError as val_er:
                        print(val_er)

if __name__ == "__main__":
  main()
plot_line_stats_CTS.py
#!/usr/bin/env python3

import os
from time import perf_counter
import logging
import yaml
import metcalcpy.util.read_env_vars_in_config as readconfig
from metplotpy.plots.line import line

def main():

    # Read the input data, input files, and output files
    ploting_stat_list_str = os.environ['PLOTTING_CTS_FCST_STAT_LIST'].split(',')
    plotting_stat_list = [ps.lstrip() for ps in ploting_stat_list_str]
    plotting_vars_str = os.environ['PLOTTING_CTS_FCST_VAR_LIST'].split(',')
    plotting_vars = [pv.lstrip() for pv in plotting_vars_str]
    var_longnames_str = os.environ['PLOTTING_CTS_FCST_VAR_NAME_LIST'].split(',')
    var_longnames = [vl.lstrip() for vl in var_longnames_str]
    var_units_str = os.environ['PLOTTING_CTS_FCST_VAR_UNITS_LIST'].split(',')
    var_units = [vu.lstrip() for vu in var_units_str]
    plotting_masks_str = os.environ['PLOTTING_CTS_VX_MASK_LIST'].split(',')
    plotting_masks = [pm.lstrip() for pm in plotting_masks_str]
    yaml_files_str = os.environ['PLOTTING_CTS_YAML_CONFIG_FILE_LIST'].split(',')
    yaml_files = [yf.lstrip() for yf in yaml_files_str]
    yaml_file_dir = os.environ['PLOTTING_CTS_YAML_CONFIG_DIR']
    plot_output_dir = os.environ['PLOTTING_CTS_OUTPUT_DIR']

    # Make output plot directory if if doesn't exist
    if not os.path.exists(plot_output_dir):
        os.makedirs(plot_output_dir)

    # Check to make sure that the lists are the same size
    if not len(plotting_vars) == len(var_longnames) == len(var_units):
        raise RuntimeError('The length of PLOTTING_CTS_FCST_VAR_LIST must be equal to the lengths of PLOTTING_CTS_FCST_VAR_NAME_LIST and PLOTTING_CTS_FCST_VAR_UNITS_LIST')

    # Loop through the stats
    for s in plotting_stat_list:
        os.environ['PLOTTING_STAT'] = s

        if s == 'MAE':
            os.environ['PLOTTING_STAT_LONG'] = 'Mean Absolute Error'
        elif s == 'ME':
            os.environ['PLOTTING_STAT_LONG'] = 'Mean Error'
        elif s == 'RMSE':
            os.environ['PLOTTING_STAT_LONG'] = 'Root Mean Squared Error'
        elif s == 'CSI':
            os.environ['PLOTTING_STAT_LONG'] = 'Critical Success Index'
        elif s == 'FBIAS':
            os.environ['PLOTTING_STAT_LONG'] = 'Frequency Bias'
        else:
            os.environ['PLOTTING_STAT_LONG'] = s

        # Loop through the variables
        for v,n,u in zip(plotting_vars,var_longnames,var_units):

            os.environ['FCST_VAR_VAL1'] = v
            os.environ['PLOTTING_CTS_LONG_VAR'] = n
            os.environ['PLOTTING_CTS_VAR_UNITS'] = u

            # Loop throuth masks
            for m in plotting_masks:

                os.environ['PLOTTING_CTS_OUTPUT_FILENAME'] = os.path.join(plot_output_dir,v+'_'+m)
                os.environ['PLOTTING_CTS_MASK'] = m

                # Loop through data
                for i in yaml_files:

                    # Build yaml config file name
                    os.environ['PLOTTING_CTS_YAML_CONFIG_NAME'] = os.path.join(yaml_file_dir,i)

                    # Read in the YAML configuration file.  Environment variables in
                    # the configuration file are supported.
                    try:
                        input_config_file = os.getenv("PLOTTING_CTS_YAML_CONFIG_NAME", "custom_line.yaml")
                        settings = readconfig.parse_config(input_config_file)
                        logging.info(settings)
                    except yaml.YAMLError as exc:
                        logging.error(exc)

                    try:
                        start = perf_counter()
                        plot = line.Line(settings)
                        plot.save_to_file()
                        plot.write_html()
                        plot.write_output_file()
                        end = perf_counter()
                        execution_time = end - start
                        plot.logger.info(f"Finished creating line plot, execution time: {execution_time} seconds")
                    except ValueError as val_er:
                        print(val_er)

if __name__ == "__main__":
  main()

Running METplus

Pass the use case configuration file to the run_metplus.py script along with any user-specific system configuration files if desired:

run_metplus.py /path/to/METplus/parm/use_cases/model_applications/medium_range/PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime.conf /path/to/user_system.conf

See Running METplus for more information.

Expected Output

A successful run will output the following both to the screen and to the logfile:

INFO: METplus has successfully finished running.

Refer to the value set for OUTPUT_BASE to find where the output data was generated. Output for this use case will be found in {OUTPUT_BASE}/model_applications/medium_range/PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime. There will be 6 directories, data_ingest, GDAS, plots, point_stat, reformatted, and StatAnalaysis. The data_ingest directory contains the observation dat that has been downloaded and contains 2 subdirectories, GDAS and GFS. The GDAS directory contains 1 subdirectory, 20250924, with 2 files:

  • 20250924_0000.prepbufr.nr

  • 20250924_0600.prepbufr.nr

The data inside the GFS directory is sorted by model initialization time and contains both surface and upper air data. These files have the format, where II is the model initialzation hours and HHH is the lead time in hours:

  • gfs.tIIz.pgrb2.0p25.fHHH

  • gfs.tIIz.sfluxgrbfHHH.grib2

Inside the GDAS directory contains the GDAS observations that have been converted from prepbufr to netCDF. The directory contains 2 files:

  • prepbufr.gdas.2025092400.nc

  • prepbufr.gdas.2025092406.nc

The plots directory contains one subdirectory, 6h, that has 11 plots:

  • T500_FULL_MAE.png

  • T500_FULL_ME.png

  • T500_FULL_RMSE.png

  • TMP_FULL_CSI.png

  • TMP_FULL_FBIAS.png

  • TMP_FULL_MAE.png

  • TMP_FULL_ME.png

  • TMP_FULL_RMSE.png

  • Z500_FULL_MAE.png

  • Z500_FULL_ME.png

  • Z500_FULL_RMSE.png

The point_stat directory also has 2 subdirectories, CREDIT/6h and GFS. The files output to CREDIT/6h are also stored in subdirectories dated with model initialization time in the format of YYYYMMDDHH. These files have the following format, where the dates labeled are lead time, valid year, month, and day, and valid hour, minute, and second:

  • point_stat_CREDIT_surface_HHMMSSL_YYYYMMDD_HHMMSSV.stat

The files output to the GFS directory are also stored in subdirectories dated with model initialization time in the format of YYYYMMDDHH. These files have the same format as above where the dates labeled are lead time, valid year, month, and day, and valid hour, minute, and second:

  • point_stat_GFS_surface_HHMMSSL_YYYYMMDD_HHMMSSV.stat

  • point_stat_GFS_upper_air_HHMMSSL_YYYYMMDD_HHMMSSV.stat

The reformatted directory contains the reformatted output from StatAnalysis that is used in plotting. There is one subdirectory (6h) that contains 2 files:

  • reformat_CNT_6h.data

  • reformat_CTS_6h.data

The StatAnalysis directory contains 1 subdirectory (6h). Inside that directory are 6 output files:

  • CREDIT_GDAS_2025092400_2025092406_allleads_all_stations_allValidHours_CNT.stat

  • CREDIT_GDAS_2025092400_2025092406_allleads_all_stations_allValidHours_CTS.stat

  • CREDIT_GDAS_2025092400_2025092406_allleads_all_stations_hourly_VCNT.stat

  • GFS_GDAS_2025092400_2025092406_allleads_all_stations_allValidHours_CNT.stat

  • GFS_GDAS_2025092400_2025092406_allleads_all_stations_allValidHours_CTS.stat

  • GFS_GDAS_2025092400_2025092406_allleads_all_stations_hourly_VCNT.stat

Keywords

Note

  • DataIngestToolUseCase

  • PB2NCToolUseCase

  • PointStatToolUseCase

  • StatAnalysisToolUseCase

  • UserScriptUseCase

  • MediumRangeAppUseCase

  • NCAROrgUseCase

  • GRIB2FileUseCase

  • NetCDFFileUseCase

  • METdbLoadUseCase

  • METcalcpyUseCase

  • METplotpyUseCase

Navigate to the METplus Quick Search for Use Cases page to discover other similar use cases.

sphinx_gallery_thumbnail_path = ‘_static/medium_range-PointStat_fcstCREDIT_GFS_obsGDAS_6hrRealtime.png’

Gallery generated by Sphinx-Gallery