Note
Go to the end to download the full example code.
UserScript: Make a Phase Diagram plot from input RMM or OMI
model_applications/s2s_mjo/UserScript_obsERA_obsOnly_PhaseDiagram.py
Scientific Objective
Phase diagrams are used to Indices for MJO and QBO. This use case produces a phase diagram using either OLR based MJO Index (OMI) or the Real-time Multivariate MJO index (RMM)
Version Added
METplus version 4.1
Datasets
Forecast: None
Observation: ERA Reanlaysis Outgoing Longwave Radiation
Climatology: None
Location: All of the input 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.
METplus Components
This use case runs UserScript twice, once to create a text file containing a listing of input files and then to create a Phase Diagram.
METplus Workflow
Beginning time (INIT_BEG): 2012-01-01
End time (INIT_END): 2012-03-31
Increment between beginning and end times (INIT_INCREMENT): 1 day
Sequence of forecast leads to process (LEAD_SEQ): 0 hour
The UserScript that creates a filelist is run once for each valid time, while the UserScript to create a phase diagram is run only once. It creates a phase diagram plot using the input files. Variables for the phase diagram are set in the [user_env_vars] section of the .conf file.
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_mjo/UserScript_obsERA_obsOnly_PhaseDiagram.conf
[config]
# Documentation for this use case can be found at
# https://metplus.readthedocs.io/en/latest/generated/model_applications/s2s_mjo/UserScript_obsERA_obsOnly_PhaseDiagram.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_time_filelist), UserScript(script_PhaseDiagram)
###
# 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 = 2012010100
VALID_END = 2012033100
VALID_INCREMENT = 86400
LEAD_SEQ = 0
# variables referenced in other sections
# Run the obs for these cases
OBS_RUN = True
FCST_RUN = False
# Input and Output Directories for the OBS OLR Files and output text file containing the file list
OBS_PDTIME_FMT = %Y%m%d-%H%M%S
OBS_PDTIME_INPUT_TEMPLATE = {valid?fmt=%Y%m%d-%H%M%S}
OBS_PDTIME_OUTPUT_DIR = {OUTPUT_BASE}/model_applications/s2s_mjo/UserScript_obsERA_obsOnly_PhaseDiagram/
OBS_PDTIME_OUTPUT_TEMPLATE = time_list_lead{lead?fmt=%HHH}.txt
###
# UserScript(obs_time_filelist) Settings
# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#userscript
###
# Create a time file that contains the times we want to filter for plotting
[obs_time_filelist]
# Find the files for each time
USER_SCRIPT_RUNTIME_FREQ = RUN_ONCE_FOR_EACH
USER_SCRIPT_COMMAND = {METPLUS_BASE}/parm/use_cases/model_applications/s2s_mjo/UserScript_obsERA_obsOnly_PhaseDiagram/save_input_files_txt.py {OBS_PDTIME_INPUT_TEMPLATE} {OBS_PDTIME_OUTPUT_DIR}/{OBS_PDTIME_OUTPUT_TEMPLATE}
# Configurations for the Phase Diagram Plotting Script
[user_env_vars]
# Whether to Run the model or obs
RUN_OBS = {OBS_RUN}
RUN_FCST = {FCST_RUN}
# Make OUTPUT_BASE Available to the script
SCRIPT_OUTPUT_BASE = {OUTPUT_BASE}
# Index to Plot
PLOT_INDEX = RMM
# Input Directories
OBS_PHASE_DIAGRAM_INPUT_DIR = {INPUT_BASE}/model_applications/s2s_mjo/UserScript_obsERA_obsOnly_PhaseDiagram
# Input filename template
OBS_PHASE_DIAGRAM_INPUT_FILE = rmm.1x.txt
# Input Time file
OBS_PHASE_DIAGRAM_INPUT_TIMELIST_TEXTFILE = {OBS_PDTIME_OUTPUT_DIR}/{OBS_PDTIME_OUTPUT_TEMPLATE}
OBS_PHASE_DIAGRAM_INPUT_TIME_FMT = {OBS_PDTIME_FMT}
# Plot Output Directory
PHASE_DIAGRAM_PLOT_OUTPUT_DIR = {OUTPUT_BASE}/s2s_mjo/UserScript_obsERA_obsOnly_PhaseDiagram/plots
# Plot Ouptut Name
OBS_PHASE_PLOT_OUTPUT_NAME = RMM_phase_diagram
###
# UserScript(script_PhaseDiagram) Settings
# https://metplus.readthedocs.io/en/latest/Users_Guide/wrappers.html#userscript
###
# Configurations for UserScript: Run the RMM Analysis driver
[script_PhaseDiagram]
# list of strings to loop over for each run time.
# Run the user script once per lead
USER_SCRIPT_RUNTIME_FREQ = RUN_ONCE_PER_LEAD
# Command to run the user script with input configuration file
USER_SCRIPT_COMMAND = {METPLUS_BASE}/parm/use_cases/model_applications/s2s_mjo/UserScript_obsERA_obsOnly_PhaseDiagram/PhaseDiagram_driver.py
MET Configuration
There are no MET configuration files in this use case.
Python Embedding
This use case does not use python embedding.
User Scripting
The first UserScript creates a listing of text file (save_inpput_file_txt). The second, PhaseDiagram_driver.py orchestrates the generation of a phase diagram plot. Inputs to the phase diagram driver are a text file containing the following columns, yyyy,mm,dd,hh,pc1,pc2,amp for OMI, or yyyy,mm,dd,pc1,pc2,phase,amp,source for RMM.
parm/use_cases/model_applications/s2s_mjo/UserScript_obsERA_obsOnly_PhaseDiagram/save_input_files_txt.py
#! /usr/bin/env python
import os
import sys
input_file = sys.argv[1]
output_file = sys.argv[2]
output_dir = os.path.dirname(output_file)
if not os.path.exists(output_dir):
print(f'Creating output dir: {output_dir}')
os.makedirs(output_dir)
filelist = open(output_file,'a+')
filelist.write(input_file + '\n')
filelist.close()
parm/use_cases/model_applications/s2s_mjo/UserScript_obsERA_obsOnly_PhaseDiagram/PhaseDiagram_driver.py
#!/usr/bin/env python3
"""
Driver Script to read in OMI or RMM indices and plot phase diagram for specified dates.
OMI values can be obtained from https://psl.noaa.gov/mjo/, RMM values can be obtained from
http://www.bom.gov.au/climate/mjo/graphics/rmm.74toRealtime.txt
"""
import os
import atexit
import numpy as np
import pandas as pd
import datetime
import warnings
import metplotpy.contributed.mjo_rmm_omi.plot_mjo_indices as pmi
def handle_exit(obs_timefile,fcst_timefile):
try:
os.remove(obs_timefile)
except:
pass
try:
os.remove(fcst_timefile)
except:
pass
def run_phasediagram_steps(inlabel, alldata_timefile, oplot_dir):
# which index are we plotting
indexname = os.environ['PLOT_INDEX']
pltfile = os.path.join(os.environ[inlabel+'_PHASE_DIAGRAM_INPUT_DIR'],
os.environ[inlabel+'_PHASE_DIAGRAM_INPUT_FILE'])
# read data from text file
if indexname=='OMI':
data = pd.read_csv(pltfile, header=None, delim_whitespace=True, names=['yyyy','mm','dd','hh','pc1','pc2','amp'],
parse_dates={'dtime':['yyyy','mm','dd','hh']})
elif indexname=='RMM':
data = pd.read_csv(pltfile, header=None, delim_whitespace=True,
names=['yyyy','mm','dd', 'pc1','pc2','phase','amp','source'], parse_dates={'dtime':['yyyy','mm','dd']})
# Get the file with the listing of times and format of this file
alldata_timefmt = os.environ[inlabel+'_PHASE_DIAGRAM_INPUT_TIME_FMT']
# Read the file
with open(alldata_timefile) as at:
alldata_time = at.read().splitlines()
keepdata = []
for dd in alldata_time:
timeloc = np.where(data.dtime == datetime.datetime.strptime(dd,alldata_timefmt))
if len(timeloc[0]) > 0:
for l in timeloc[0]:
keepdata.append(l)
pltdata = data.iloc[keepdata]
dates = np.array(pltdata.dtime.dt.strftime('%Y%m%d').values,dtype=int)
months = np.array(pltdata.dtime.dt.strftime('%m').values,dtype=int)
days = np.array(pltdata.dtime.dt.strftime('%d').values,dtype=int)
PC1 = np.array(pltdata.pc1.values)
PC2 = np.array(pltdata.pc2.values)
# plot the phase diagram
phase_plot_name = os.path.join(oplot_dir,os.environ.get(inlabel+'_PHASE_PLOT_OUTPUT_NAME',inlabel+'_phase'))
phase_plot_format = os.environ.get(inlabel+'_PHASE_PLOT_OUTPUT_FORMAT','png')
# plot the phase diagram
pmi.phase_diagram(indexname,PC1,PC2,dates,months,days,phase_plot_name,'png')
def main():
obs_timelist = os.path.join(os.environ.get('OBS_PHASE_DIAGRAM_INPUT_DIR',''),
os.environ.get('OBS_PHASE_DIAGRAM_INPUT_TIMELIST_TEXTFILE',''))
fcst_timelist = os.path.join(os.environ.get('FCST_PHASE_DIAGRAM_INPUT_DIR',''),
os.environ.get('FCST_PHASE_DIAGRAM_INPUT_TIMELIST_TEXTFILE',''))
atexit.register(handle_exit,obs_timelist,fcst_timelist)
# Check for an output plot directory in the configs. Create one if it does not exist
oplot_dir = os.environ.get('PHASE_DIAGRAM_PLOT_OUTPUT_DIR','')
if not oplot_dir:
obase = os.environ['OUTPUT_BASE']
oplot_dir = os.path.join(obase,'plots')
if not os.path.exists(oplot_dir):
os.makedirs(oplot_dir)
# Determine if doing forecast or obs
run_obs_phasediagram = os.environ.get('RUN_OBS','False').lower()
run_fcst_phasediagram = os.environ.get('FCST_RUN_FCST','False').lower()
# Run the steps to compute OMM
# Observations
if (run_obs_phasediagram == 'true'):
run_phasediagram_steps('OBS', obs_timelist, oplot_dir)
# Forecast
if (run_fcst_phasediagram == 'true'):
run_phasediagram_steps('FCST', fcst_timelist, oplot_dir)
# nothing selected
if (run_obs_phasediagram == 'false') and (run_fcst_phasediagram == 'false'):
warnings.warn('Forecast and Obs runs not selected, no plots will be created')
warnings.warn('Set RUN_FCST or RUN_OBS in the [user_en_vars] section to generate output')
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/s2s_mjo/UserScript_obsERA_obsOnly_PhaseDiagram.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/s2s_mjo/UserScript_obsERA_obsOnly_PhaseDiagram/plots The output is one plot:
* RMM_phase_diagram.png
Keywords
Note
S2SAppUseCase
S2SMJOAppUseCase
UserScriptUseCase
METplotpyUseCase
Navigate to METplus Quick Search for Use Cases to discover other similar use cases.