Note
Go to the end to download the full example code
Blocking Calculation: ERA RegridDataPlane, PcpCombine, and Blocking python code
model_applications/ s2s_mid_lat/ UserScript_obsERA_obsOnly_Blocking.py
Scientific Objective
To compute the frequency of blocking using the Pelly-Hoskins method. Specifically the blocking calculation consits of computing the Central Blocking Latitude (CBL), Instantaneousy blocked latitudes (IBL), Group Instantaneousy blocked latitudes (GIBL), and the frequency of atmospheric blocking. The CBL calculation had an option to use an observed climatology.
The following reference contains the specific equations and methodology used to compute blocking:
Datasets
Forecast dataset: None
Observation dataset: ERA Reanlaysis 500 mb height.
External Dependencies
You will need to use a version of Python 3.6+ that has the following packages installed:
* numpy
* netCDF4
* datetime
* bisect
* scipy
If the version of Python used to compile MET did not have these libraries at the time of compilation, you will need to add these packages or create a new Python environment with these packages.
If this is the case, you will need to set the MET_PYTHON_EXE environment variable to the path of the version of Python you want to use. If you want this version of Python to only apply to this use case, set it in the [user_env_vars] section of a METplus configuration file.:
[user_env_vars] MET_PYTHON_EXE = /path/to/python/with/required/packages/bin/python
METplus Components
This use case runs the blocking driver script which runs the steps the user lists in STEPS_OBS. The possible steps are regridding, time averaging, computing a running mean, computing anomalies, computing CBLs (CBL), plotting CBLs (PLOTCBL), computing IBLs (IBL), plotting IBL frequency (PLOTIBL), computing GIBLs (GIBL), computing blocks (CALCBLOCKS), and plotting the blocking frequency (PLOTBLOCKS). Regridding, time averaging, running means, and anomaloies are set up in the UserScript .conf file and are formatted as follows: PROCESS_LIST = RegridDataPlane(regrid_obs), PcpCombine(daily_mean_obs), PcpCombine(running_mean_obs), PcpCombine(anomaly_obs), UserScript(script_blocking)
The other steps are listed in the Blocking .conf file and are formatted as follows: OBS_STEPS = CBL+PLOTCBL+IBL+PLOTIBL+GIBL+CALCBLOCKS+PLOTBLOCKS
METplus Workflow
The blocking python code is run for each time for the forecast and observations data. This example loops by valid time. This version is set to only process the blocking steps (CBL, PLOTCBL, IBL, PLOTIBL, GIBL, CALCBLOCKS, PLOTBLOCKS), omitting the regridding, time averaging, running mean, and anomaly pre-processing steps. However, the configurations for pre-processing are available for user reference.
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 i.e. parm/use_cases/model_applications/s2s_mid_lat/UserScript_obsERA_obsOnly_Blocking.py. The file UserScript_obsERA_obsOnly_Blocking.conf runs the python program, and the variables for all steps of the Blocking use case are set in the [user_env_vars] section.
[config]
# Documentation for this use case can be found at
# https://metplus.readthedocs.io/en/latest/generated/model_applications/s2s_mid_lat/UserScript_obsERA_obsOnly_Blocking.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
###
# All steps, including pre-processing:
# PROCESS_LIST = RegridDataPlane(regrid_obs), PcpCombine(daily_mean_obs), PcpCombine(running_mean_obs), PcpCombine(anomaly_obs), UserScript(script_blocking)
# Only Blocking Analysis script for the observations
PROCESS_LIST = UserScript(script_blocking)
###
# 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 = 1979120100
VALID_END = 2017022800
VALID_INCREMENT = 86400
LEAD_SEQ = 0
# Only Process DJF
SKIP_TIMES = "%m:begin_end_incr(3,11,1)", "%m%d:0229"
# Run the obs data
# A variable set to be used in the pre-processing steps
OBS_RUN = True
###
# RegridDataPlane(regrid_obs) Settings
# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#regriddataplane
###
# Regrid the observations to 1 degree using regrid_data_plane
[regrid_obs]
VALID_END = 2017022818
VALID_INCREMENT = 21600
OBS_REGRID_DATA_PLANE_RUN = {OBS_RUN}
OBS_DATA_PLANE_ONCE_PER_FIELD = False
OBS_REGRID_DATA_PLANE_VAR1_INPUT_FIELD_NAME = Z
OBS_REGRID_DATA_PLANE_VAR1_INPUT_LEVEL = P500
OBS_REGRID_DATA_PLANE_VAR1_OUTPUT_FIELD_NAME = Z500
REGRID_DATA_PLANE_VERIF_GRID = latlon 360 90 89 0 -1.0 1.0
REGRID_DATA_PLANE_METHOD = BILIN
REGRID_DATA_PLANE_WIDTH = 2
OBS_REGRID_DATA_PLANE_INPUT_DIR = /gpfs/fs1/collections/rda/data/ds627.0/ei.oper.an.pl
OBS_REGRID_DATA_PLANE_OUTPUT_DIR = {OUTPUT_BASE}/s2s_mid_lat/UserScript_fcstGFS_obsERA_Blocking/ERA/Regrid
OBS_REGRID_DATA_PLANE_INPUT_TEMPLATE = {valid?fmt=%Y%m}/ei.oper.an.pl.regn128sc.{valid?fmt=%Y%m%d%H}
OBS_REGRID_DATA_PLANE_OUTPUT_TEMPLATE = {valid?fmt=%Y%m%d}/Z500_6hourly_{init?fmt=%Y%m%d%H}_NH.nc
###
# PCPCombine(daily_mean_obs) Settings
# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#pcpcombine
###
# Perform a sum over the 4 daily times that have been regridded using pcp_combine
# 00, 06, 12, 18 UTC
[daily_mean_obs]
VALID_BEG = 1979120118
VALID_END = 2017022818
OBS_PCP_COMBINE_RUN = {OBS_RUN}
OBS_PCP_COMBINE_METHOD = DERIVE
OBS_PCP_COMBINE_STAT_LIST = MEAN
OBS_PCP_COMBINE_INPUT_ACCUMS = 6
OBS_PCP_COMBINE_INPUT_NAMES = Z500
OBS_PCP_COMBINE_INPUT_LEVELS = "(*,*)"
OBS_PCP_COMBINE_INPUT_OPTIONS = convert(x) = x / 9.81; set_attr_valid = "{valid?fmt=%Y%m%d_%H%M%S?shift=-64800}";
OBS_PCP_COMBINE_OUTPUT_ACCUM = 24
OBS_PCP_COMBINE_DERIVE_LOOKBACK = 24
OBS_PCP_COMBINE_OUTPUT_NAME = Z500
OBS_PCP_COMBINE_INPUT_DIR = {OUTPUT_BASE}/s2s_mid_lat/UserScript_fcstGFS_obsERA_Blocking/ERA/Regrid
OBS_PCP_COMBINE_OUTPUT_DIR = {OUTPUT_BASE}/s2s_mid_lat/UserScript_fcstGFS_obsERA_Blocking/ERA/Daily
OBS_PCP_COMBINE_INPUT_TEMPLATE = {valid?fmt=%Y%m%d}/Z500_6hourly_{valid?fmt=%Y%m%d%H}_NH.nc
OBS_PCP_COMBINE_OUTPUT_TEMPLATE = Z500_daily_{valid?fmt=%Y%m%d?shift=-64800}_NH.nc
###
# PCPCombine(running_mean_obs) Settings
# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#pcpcombine
###
# Perform a 5 day running mean on the data using pcp_combine
[running_mean_obs]
# Add the first/last 2 days to the skip times to compute the running mean
SKIP_TIMES = "%m:begin_end_incr(3,11,1)", "%m%d:1201,1202,1203,1204,0229"
OBS_PCP_COMBINE_RUN = {OBS_RUN}
OBS_PCP_COMBINE_METHOD = DERIVE
OBS_PCP_COMBINE_STAT_LIST = MEAN
OBS_PCP_COMBINE_INPUT_ACCUMS = 24
OBS_PCP_COMBINE_INPUT_NAMES = Z500
OBS_PCP_COMBINE_INPUT_LEVELS = "(*,*)"
OBS_PCP_COMBINE_INPUT_OPTIONS = set_attr_valid = "{valid?fmt=%Y%m%d_%H%M%S?shift=-172800}";
# Running mean is 5 days
OBS_PCP_COMBINE_OUTPUT_ACCUM = 120
OBS_PCP_COMBINE_DERIVE_LOOKBACK = 120
OBS_PCP_COMBINE_OUTPUT_NAME = Z500
OBS_PCP_COMBINE_INPUT_DIR = {OUTPUT_BASE}/s2s_mid_lat/UserScript_fcstGFS_obsERA_Blocking/ERA/Daily
OBS_PCP_COMBINE_OUTPUT_DIR = {OUTPUT_BASE}/s2s_mid_lat/UserScript_fcstGFS_obsERA_Blocking/ERA/Rmean5d
OBS_PCP_COMBINE_INPUT_TEMPLATE = Z500_daily_{valid?fmt=%Y%m%d}_NH.nc
OBS_PCP_COMBINE_OUTPUT_TEMPLATE = Z500_5daymean_{valid?fmt=%Y%m%d?shift=-172800}_NH.nc
###
# PCPCombine(anomaly_obs) Settings
# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#pcpcombine
###
# Compute anomalies using the daily means and 5 day running mean using pcp_combine
[anomaly_obs]
# Add the first/last 2 days to the skip times to compute the running mean
SKIP_TIMES = "%m:begin_end_incr(3,11,1)", "%m%d:1201,1202,0227,0228,0229"
OBS_PCP_COMBINE_RUN = {OBS_RUN}
OBS_PCP_COMBINE_METHOD = USER_DEFINED
OBS_PCP_COMBINE_COMMAND = -subtract {OBS_PCP_COMBINE_INPUT_DIR}/Daily/Z500_daily_{valid?fmt=%Y%m%d}_NH.nc {OBS_PCP_COMBINE_INPUT_DIR}/Rmean5d/Z500_5daymean_{valid?fmt=%Y%m%d}_NH.nc -field 'name="Z500"; level="(*,*)";'
OBS_PCP_COMBINE_INPUT_DIR = {OUTPUT_BASE}/s2s_mid_lat/UserScript_fcstGFS_obsERA_Blocking/ERA
OBS_PCP_COMBINE_OUTPUT_DIR = {OUTPUT_BASE}/s2s_mid_lat/UserScript_fcstGFS_obsERA_Blocking/ERA/Anomaly
OBS_PCP_COMBINE_INPUT_TEMPLATE = Z500_daily_{valid?fmt=%Y%m%d}_NH.nc
OBS_PCP_COMBINE_OUTPUT_TEMPLATE = Z500_anomaly_{valid?fmt=%Y%m%d}_NH.nc
# Variables set for the Blocking Analysis
[user_env_vars]
# Steps to Run
OBS_STEPS = CBL+PLOTCBL+IBL+PLOTIBL+GIBL+CALCBLOCKS+PLOTBLOCKS
# Number of Seasons and Days per season that should be available
# The code will fill missing data, but requires the same number of days per
# season for each year. You may need to omit leap days if February is part of
# the processing
CBL_NUM_SEASONS = 38
IBL_NUM_SEASONS = 38
DAYS_PER_SEASON = 86
# Make the OUTPUT_BASE available to the UserScript
SCRIPT_OUTPUT_BASE = {OUTPUT_BASE}
# Variable Name for the Z500 anomaly data to read in to the blocking python code
OBS_BLOCKING_ANOMALY_VAR = Z500_ANA
# Variable for the Z500 data
OBS_BLOCKING_VAR = Z500
# Number of model grid points used for a moving average
# Must be odd
OBS_SMOOTHING_PTS = 9
# Lat Delta, to allow for offset from the Central Blocking Latitude
OBS_LAT_DELTA = -5,0,5
# Meridional Extent of blocks (NORTH_SOUTH_LIMITS/2)
OBS_NORTH_SOUTH_LIMITS = 30
# Maximum number of grid points between IBLs for everything in between to be included as an IBL
OBS_IBL_DIST = 7
# Number of grid points in and IBL to make a GIBL
OBS_IBL_IN_GIBL = 15
# Number of grid points that must overlap across days for a GIBL
OBS_GIBL_OVERLAP = 10
# Time duration in days needed for a block
OBS_BLOCK_TIME = 5
# Number of grid points a block must travel to terminate
OBS_BLOCK_TRAVEL = 45
# Method to compute blocking. Currently, the only option is 'PH' for the
# Pelly-Hoskins Method
OBS_BLOCK_METHOD = PH
# Plot Output Directory
BLOCKING_PLOT_OUTPUT_DIR = {OUTPUT_BASE}/s2s_mid_lat/UserScript_obsERA_obsOnly_Blocking/plots/
#CBL plot title and name
OBS_CBL_PLOT_MTHSTR = DJF
OBS_CBL_PLOT_OUTPUT_NAME = ERA_CBL_avg
# IBL plot title and name
OBS_IBL_PLOT_TITLE = DJF ERA Instantaneous Blocked Longitude
OBS_IBL_PLOT_OUTPUT_NAME = ERA_IBL_Freq_DJF
# Blocking plot title and name
OBS_BLOCKING_PLOT_TITLE = DJF ERA Blocking Frequency
OBS_BLOCKING_PLOT_OUTPUT_NAME = ERA_Block_Freq_DJF
###
# UserScript(script_blocking) Settings
# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#userscript
###
# Run the Blocking Analysis Script
[script_blocking]
# Skip the days on the edges that are not available due to the running mean
SKIP_TIMES = "%m:begin_end_incr(3,11,1)", "%m%d:1201,1202,0227,0228,0229"
# Run the user script once per lead
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_mid_lat/UserScript_fcstGFS_obsERA_Blocking/ERA/Anomaly/Z500_anomaly_{valid?fmt=%Y%m%d}_NH.nc,{INPUT_BASE}/model_applications/s2s_mid_lat/UserScript_fcstGFS_obsERA_Blocking/ERA/Daily/Z500_daily_{valid?fmt=%Y%m%d}_NH.nc
# Name of the file containing the listing of input files
# The options are OBS_CBL_INPUT, FCST_CBL_INPUT, OBS_IBL_INPUT, and FCST_IBL_INPUT
# *** Make sure the order is the same as the order of templates listed in USER_SCRIPT_INPUT_TEMPLATE
USER_SCRIPT_INPUT_TEMPLATE_LABELS = OBS_CBL_INPUT,OBS_IBL_INPUT
# Command to run the user script with input configuration file
USER_SCRIPT_COMMAND = {METPLUS_BASE}/parm/use_cases/model_applications/s2s_mid_lat/UserScript_obsERA_obsOnly_Blocking/Blocking_driver.py
MET Configuration
METplus sets environment variables based on the values in the METplus configuration file. These variables are referenced in the MET configuration file. 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 not controlled by an environment variable, you can add additional environment variables to be set only within the METplus environment using the [user_env_vars] section of the METplus configuration files. See the ‘User Defined Config’ section on the ‘System Configuration’ page of the METplus User’s Guide for more information.
See the following files for more information about the environment variables set in this configuration file.
parm/use_cases/met_tool_wrapper/RegridDataPlane/RegridDataPlane.py parm/use_cases/met_tool_wrapper/PCPCombine/PCPCombine_derive.py parm/use_cases/met_tool_wrapper/PCPCombine/PCPCombine_subtract.py
Python Scripts
This use case uses Python scripts to perform the blocking calculation
parm/use_cases/model_applications/s2s_mid_lat/UserScript_obsERA_obsOnly_Blocking/Blocking_driver.py: This script calls the requested steps in the blocking analysis for a forecast, observation, or both.
metcalcpy/contributed/blocking_weather_regime/Blocking.py: This script runs the requested steps, containing the code for computing CBLs, computing IBLs, computing GIBLs, and computing blocks. See the METcalcpy Blocking Calculation Script for more information.
metcalcpy/contributed/blocking_weather_regime/Blocking_WeatherRegime_util.py: This script contains functions used by both the blocking anwd weather regime analysis, including the code for determining which steps the user wants to run, and finding and reading the input files in the format from the output pre-processing steps. See the METcalcpy Utility script for more information.
#!/usr/bin/env python3
import sys
import os
import numpy as np
import datetime
import netCDF4
import warnings
from metcalcpy.contributed.blocking_weather_regime.Blocking import BlockingCalculation
from metcalcpy.contributed.blocking_weather_regime.Blocking_WeatherRegime_util import parse_steps, write_mpr_file
from metplotpy.contributed.blocking_s2s import plot_blocking as pb
from metplotpy.contributed.blocking_s2s.CBL_plot import create_cbl_plot
def main():
steps_list_fcst,steps_list_obs = parse_steps()
if not steps_list_obs and not steps_list_fcst:
warnings.warn('No processing steps requested for either the model or observations,')
warnings.warn(' nothing will be run')
warnings.warn('Set FCST_STEPS and/or OBS_STEPS in the [user_env_vars] section to process data')
######################################################################
# Blocking Calculation and Plotting
######################################################################
# Set up the data
steps_fcst = BlockingCalculation('FCST')
steps_obs = BlockingCalculation('OBS')
# Check to see if there is a plot directory
oplot_dir = os.environ.get('BLOCKING_PLOT_OUTPUT_DIR','')
if not oplot_dir:
obase = os.environ['SCRIPT_OUTPUT_BASE']
oplot_dir = os.path.join(obase,'plots')
if not os.path.exists(oplot_dir):
os.makedirs(oplot_dir)
# Check to see if there is a mpr output directory
mpr_dir = os.environ.get('BLOCKING_MPR_OUTPUT_DIR','')
if not mpr_dir:
obase = os.environ['SCRIPT_OUTPUT_BASE']
mpr_dir = os.path.join(obase,'mpr')
# Check to see if CBL's are used from an obs climatology
use_cbl_obs = os.environ.get('USE_CBL_OBS','False').lower()
# Get the days per season
dseasons = int(os.environ['DAYS_PER_SEASON'])
# Grab the Anomaly (CBL) text files
obs_cbl_filetxt = os.environ.get('METPLUS_FILELIST_OBS_CBL_INPUT','')
fcst_cbl_filetxt = os.environ.get('METPLUS_FILELIST_FCST_CBL_INPUT','')
# Grab the Daily (IBL) text files
obs_ibl_filetxt = os.environ.get('METPLUS_FILELIST_OBS_IBL_INPUT','')
fcst_ibl_filetxt = os.environ.get('METPLUS_FILELIST_FCST_IBL_INPUT','')
# Calculate Central Blocking Latitude
if ("CBL" in steps_list_obs):
print('Computing Obs CBLs')
# Read in the list of CBL files
cbl_nseasons = int(os.environ['CBL_NUM_SEASONS'])
with open(obs_cbl_filetxt) as ocl:
obs_infiles = ocl.read().splitlines()
if (obs_infiles[0] == 'file_list'):
obs_infiles = obs_infiles[1:]
if len(obs_infiles) != (cbl_nseasons*dseasons):
raise Exception('Invalid Obs data; each year must contain the same date range to calculate seasonal averages.')
cbls_obs,lats_obs,lons_obs,mhweight_obs,cbl_time_obs = steps_obs.run_CBL(obs_infiles,cbl_nseasons,dseasons)
if ("CBL" in steps_list_fcst) and (use_cbl_obs == 'false'):
# Add in step to use obs for CBLS
print('Computing Forecast CBLs')
cbl_nseasons = int(os.environ['CBL_NUM_SEASONS'])
with open(fcst_cbl_filetxt) as fcl:
fcst_infiles = fcl.read().splitlines()
if (fcst_infiles[0] == 'file_list'):
fcst_infiles = fcst_infiles[1:]
if len(fcst_infiles) != (cbl_nseasons*dseasons):
raise Exception('Invalid Fcst data; each year must contain the same date range to calculate seasonal averages.')
cbls_fcst,lats_fcst,lons_fcst,mhweight_fcst,cbl_time_fcst = steps_fcst.run_CBL(fcst_infiles,cbl_nseasons,dseasons)
elif ("CBL" in steps_list_fcst) and (use_cbl_obs == 'true'):
if not ("CBL" in steps_list_obs):
raise Exception('Must run observed CBLs before using them as a forecast.')
cbls_fcst = cbls_obs
lats_fcst = lats_obs
lons_fcst = lons_obs
mhweight_fcst = mhweight_obs
cbl_time_fcst = cbl_time_obs
#Plot Central Blocking Latitude
if ("PLOTCBL" in steps_list_obs):
if not ("CBL" in steps_list_obs):
raise Exception('Must run observed CBLs before plotting them.')
print('Plotting Obs CBLs')
cbl_plot_mthstr = os.environ['OBS_CBL_PLOT_MTHSTR']
cbl_plot_outname = os.path.join(oplot_dir,os.environ.get('OBS_CBL_PLOT_OUTPUT_NAME','obs_cbl_avg'))
create_cbl_plot(lons_obs, lats_obs, cbls_obs, mhweight_obs, cbl_plot_mthstr, cbl_plot_outname,
do_averaging=True)
if ("PLOTCBL" in steps_list_fcst):
if not ("CBL" in steps_list_fcst):
raise Exception('Must run forecast CBLs before plotting them.')
print('Plotting Forecast CBLs')
cbl_plot_mthstr = os.environ['FCST_CBL_PLOT_MTHSTR']
cbl_plot_outname = os.path.join(oplot_dir,os.environ.get('FCST_CBL_PLOT_OUTPUT_NAME','fcst_cbl_avg'))
create_cbl_plot(lons_fcst, lats_fcst, cbls_fcst, mhweight_fcst, cbl_plot_mthstr, cbl_plot_outname,
do_averaging=True)
# Run IBL
if ("IBL" in steps_list_obs):
if not ("CBL" in steps_list_obs):
raise Exception('Must run observed CBLs before running IBLs.')
print('Computing Obs IBLs')
ibl_nseasons = int(os.environ['IBL_NUM_SEASONS'])
with open(obs_ibl_filetxt) as oil:
obs_infiles = oil.read().splitlines()
if (obs_infiles[0] == 'file_list'):
obs_infiles = obs_infiles[1:]
if len(obs_infiles) != (ibl_nseasons*dseasons):
raise Exception('Invalid Obs data; each year must contain the same date range to calculate seasonal averages.')
ibls_obs,ibl_time_obs = steps_obs.run_Calc_IBL(cbls_obs,obs_infiles,ibl_nseasons,dseasons)
daynum_obs = np.arange(0,len(ibls_obs[0,:,0]),1)
if ("IBL" in steps_list_fcst):
if (not "CBL" in steps_list_fcst):
raise Exception('Must run forecast CBLs or use observed CBLs before running IBLs.')
print('Computing Forecast IBLs')
ibl_nseasons = int(os.environ['IBL_NUM_SEASONS'])
with open(fcst_ibl_filetxt) as fil:
fcst_infiles = fil.read().splitlines()
if (fcst_infiles[0] == 'file_list'):
fcst_infiles = fcst_infiles[1:]
if len(fcst_infiles) != (ibl_nseasons*dseasons):
raise Exception('Invalid Fcst data; each year must contain the same date range to calculate seasonal averages.')
ibls_fcst,ibl_time_fcst = steps_fcst.run_Calc_IBL(cbls_fcst,fcst_infiles,ibl_nseasons,dseasons)
daynum_fcst = np.arange(0,len(ibls_fcst[0,:,0]),1)
if ("IBL" in steps_list_obs) and ("IBL" in steps_list_fcst):
# Print IBLs to output matched pair file
i_mpr_outdir = os.path.join(mpr_dir,'IBL')
if not os.path.exists(i_mpr_outdir):
os.makedirs(i_mpr_outdir)
modname = os.environ.get('MODEL_NAME','GFS')
maskname = os.environ.get('MASK_NAME','FULL')
ibl_outfile_prefix = os.path.join(i_mpr_outdir,'IBL_stat_'+modname)
cbls_avg = np.nanmean(cbls_obs,axis=0)
write_mpr_file(ibls_obs,ibls_fcst,cbls_avg,lons_obs,ibl_time_obs,ibl_time_fcst,modname,
'NA','IBLs','block','Z500','IBLs','block','Z500',maskname,'500',ibl_outfile_prefix)
# Plot IBLS
if("PLOTIBL" in steps_list_obs) and not ("PLOTIBL" in steps_list_fcst):
if not ("IBL" in steps_list_obs):
raise Exception('Must run observed IBLs before plotting them.')
print('Plotting Obs IBLs')
ibl_plot_title = os.environ.get('OBS_IBL_PLOT_TITLE','Instantaneous Blocked Longitude')
ibl_plot_outname = os.path.join(oplot_dir,os.environ.get('OBS_IBL_PLOT_OUTPUT_NAME','obs_IBL_Freq'))
ibl_plot_label1 = os.environ.get('IBL_PLOT_OBS_LABEL','')
pb.plot_ibls(ibls_obs,lons_obs,ibl_plot_title,ibl_plot_outname,label1=ibl_plot_label1)
elif ("PLOTIBL" in steps_list_fcst) and not ("PLOTIBL" in steps_list_obs):
if not ("IBL" in steps_list_fcst):
raise Exception('Must run forecast IBLs before plotting them.')
print('Plotting Forecast IBLs')
ibl_plot_title = os.environ.get('FCST_IBL_PLOT_TITLE','Instantaneous Blocked Longitude')
ibl_plot_outname = os.path.join(oplot_dir,os.environ.get('FCST_IBL_PLOT_OUTPUT_NAME','fcst_IBL_Freq'))
ibl_plot_label1 = os.environ.get('IBL_PLOT_FCST_LABEL','')
pb.plot_ibls(ibls_fcst,lons_fcst,ibl_plot_title,ibl_plot_outname,label1=ibl_plot_label1)
elif ("PLOTIBL" in steps_list_obs) and ("PLOTIBL" in steps_list_fcst):
if (not "IBL" in steps_list_obs) and (not "IBL" in steps_list_fcst):
raise Exception('Must run forecast and observed IBLs before plotting them.')
print('Plotting Obs and Forecast IBLs')
ibl_plot_title = os.environ['IBL_PLOT_TITLE']
ibl_plot_outname = os.path.join(oplot_dir,os.environ.get('IBL_PLOT_OUTPUT_NAME','IBL_Freq'))
#Check to see if there are plot legend labels
ibl_plot_label1 = os.environ.get('IBL_PLOT_OBS_LABEL','Observation')
ibl_plot_label2 = os.environ.get('IBL_PLOT_FCST_LABEL','Forecast')
pb.plot_ibls(ibls_obs,lons_obs,ibl_plot_title,ibl_plot_outname,data2=ibls_fcst,lon2=lons_fcst,
label1=ibl_plot_label1,label2=ibl_plot_label2)
# Run GIBL
if ("GIBL" in steps_list_obs):
if not ("IBL" in steps_list_obs):
raise Exception('Must run observed IBLs before running GIBLs.')
print('Computing Obs GIBLs')
gibls_obs = steps_obs.run_Calc_GIBL(ibls_obs,lons_obs)
if ("GIBL" in steps_list_fcst):
if not ("IBL" in steps_list_fcst):
raise Exception('Must run Forecast IBLs before running GIBLs.')
print('Computing Forecast GIBLs')
gibls_fcst = steps_fcst.run_Calc_GIBL(ibls_fcst,lons_fcst)
# Calc Blocks
if ("CALCBLOCKS" in steps_list_obs):
if not ("GIBL" in steps_list_obs):
raise Exception('Must run observed GIBLs before calculating blocks.')
print('Computing Obs Blocks')
block_freq_obs = steps_obs.run_Calc_Blocks(ibls_obs,gibls_obs,lons_obs,daynum_obs)
if ("CALCBLOCKS" in steps_list_fcst):
if not ("GIBL" in steps_list_fcst):
raise Exception('Must run Forecast GIBLs before calculating blocks.')
print('Computing Forecast Blocks')
block_freq_fcst = steps_fcst.run_Calc_Blocks(ibls_fcst,gibls_fcst,lons_fcst,daynum_fcst)
# Write out a Blocking MPR file if both obs and forecast blocking calculation performed
if ("CALCBLOCKS" in steps_list_obs) and ("CALCBLOCKS" in steps_list_fcst):
b_mpr_outdir = os.path.join(mpr_dir,'Blocks')
if not os.path.exists(b_mpr_outdir):
os.makedirs(b_mpr_outdir)
# Print Blocks to output matched pair file
modname = os.environ.get('MODEL_NAME','GFS')
maskname = os.environ.get('MASK_NAME','FULL')
blocks_outfile_prefix = os.path.join(b_mpr_outdir,'blocking_stat_'+modname)
cbls_avg = np.nanmean(cbls_obs,axis=0)
write_mpr_file(block_freq_obs,block_freq_fcst,cbls_avg,lons_obs,ibl_time_obs,ibl_time_fcst,modname,
'NA','Blocks','block','Z500','Blocks','block','Z500',maskname,'500',blocks_outfile_prefix)
# Plot Blocking Frequency
if ("PLOTBLOCKS" in steps_list_obs):
if not ("CALCBLOCKS" in steps_list_obs):
raise Exception('Must compute observed blocks before plotting them.')
print('Plotting Obs Blocks')
blocking_plot_title = os.environ.get('OBS_BLOCKING_PLOT_TITLE','Obs Blocking Frequency')
blocking_plot_outname = os.path.join(oplot_dir,os.environ.get('OBS_BLOCKING_PLOT_OUTPUT_NAME','obs_Block_Freq'))
pb.plot_blocks(block_freq_obs,gibls_obs,ibls_obs,lons_obs,blocking_plot_title,blocking_plot_outname)
if ("PLOTBLOCKS" in steps_list_fcst):
if not ("CALCBLOCKS" in steps_list_fcst):
raise Exception('Must compute forecast blocks before plotting them.')
print('Plotting Forecast Blocks')
blocking_plot_title = os.environ.get('FCST_BLOCKING_PLOT_TITLE','Forecast Blocking Frequency')
blocking_plot_outname = os.path.join(oplot_dir,os.environ.get('FCST_BLOCKING_PLOT_OUTPUT_NAME','fcst_Block_Freq'))
pb.plot_blocks(block_freq_fcst,gibls_fcst,ibls_fcst,lons_fcst,blocking_plot_title,blocking_plot_outname)
if __name__ == "__main__":
main()
Running METplus
This use case is run in the following ways:
Passing in UserScript_obsERA_obsOnly_Blocking.py then a user-specific system configuration file:
run_metplus.py -c /path/to/METplus/parm/use_cases/model_applications/s2s_mid_lat/UserScript_obsERA_obsOnly_Blocking.py -c /path/to/user_system.conf
Modifying the configurations in parm/metplus_config, then passing in UserScript_obsERA_obsOnly_Blocking.py:
run_metplus.py -c /path/to/METplus/parm/use_cases/model_applications/s2s_mid_lat/UserScript_obsERA_obsOnly_Blocking.py
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
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
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 model_applications/s2s_mid_lat/Blocking (relative to OUTPUT_BASE) and will contain output for the steps requested. This may include the regridded data, daily averaged files, running mean files, and anomaly files. In addition, output CBL, IBL, and Blocking frequency plots can be generated. The location of these output plots can be specified as BLOCKING_PLOT_OUTPUT_DIR. If it is not specified, plots will be sent to OUTPUT_BASE/plots. MET format matched pair output will also be generated for IBLs and blocks if a user runs these steps on both the model and observation data. The location the matched pair output can be specified as BLOCKING_MPR_OUTPUT_DIR. If it is not specified, plots will be sent to OUTPUT_BASE/mpr.
Keywords
Note
RegridDataPlaneToolUseCase
PCPCombineToolUseCase
S2SAppUseCase
S2SMidLatAppUseCase
NetCDFFileUseCase
GRIB2FileUseCase
METcalcpyUseCase
METplotpyUseCase
Navigate to the METplus Quick Search for Use Cases page to discover other similar use cases.
sphinx_gallery_thumbnail_path = ‘_static/s2s_mid_lat-UserScript_obsERA_obsOnly_Blocking.png’
Total running time of the script: (0 minutes 0.000 seconds)