Metview's documentation is now on readthedocs!

Download source and data


ENS Tephigram Example
#Metview Macro

#  **************************** LICENSE START ***********************************
# 
#  Copyright 2020 ECMWF. This software is distributed under the terms
#  of the Apache License version 2.0. In applying this license, ECMWF does not
#  waive the privileges and immunities granted to it by virtue of its status as
#  an Intergovernmental Organization or submit itself to any jurisdiction.
# 
#  ***************************** LICENSE END ************************************
# 

# read ENS data 
data = read("ens_prof.grib")       

# define profile location
location = [17.51, -7.04]

# the starting x coordinate of the sidebar on the right.
# Wind and dewpoint depression is plotted there. 
# Do not change it! 
sidebar_x_offset = 1000

# the ensemble size (perturbed members)
ens_num = 50

# filter control (cf) and perturbed (pf) forcasts
g_cf = read(data: data, type: "cf")
g_pf = read(data: data, type: "pf")

# extract thermo profile for cf
nc = thermo_grib(
    data: g_cf,
    point_extraction: "nearest_gridpoint",
    coordinates: location	
   )
    
prof_cf = thermo_data_values(nc, 1)    
 
# extract thermo profile for pf
nc = thermo_grib(
    data: g_pf,
    point_extraction: "nearest_gridpoint",
    coordinates: location	
   )
   
prof_pf = thermo_data_values(nc, 1) 
    
# define colours for shaded areas
t_col_outer = 'RGB(1.0000,0.7922,0.7961)'
t_col_inner = 'RGB(0.8863,0.0000,0.0000)'
td_col_outer = 'RGB(0.8,0.9137,0.8)'
td_col_inner = 'RGB(0.3882,0.7765,0.3843)'
ddep_col_outer = 'RGB(0.8118,0.8902,1)'
ddep_col_inner = 'RGB(0.4353,0.6314,1)'

# define colours for curves
t_col_line = 'RGB(0.8706,0,0)'
td_col_line = 'RGB(0,0.2784,0.007843)'
ddep_col_line = 'RGB(0,0.3725,1)'

# define cf curve data
t_cf = prof_cf.t
td_cf = prof_cf.td
ddep_cf = (t_cf - td_cf) + sidebar_x_offset

# get pressure levels for t and td (from pf)
# and compute ENS mean profiles
lev_num = count(prof_pf.p)/ens_num
p = vector(lev_num)
t_mean = vector(lev_num)
td_mean = vector(lev_num)
ddep_mean = vector(lev_num)

for i=1 to lev_num do
    # get pressure
    p[i] = prof_pf.p[(i-1)*ens_num+1]
    
    # get t and td for all the perturbed members
    idx_start = (i-1)*ens_num+1
    idx_end = i*ens_num
    t_v = prof_pf.t[idx_start, idx_end]
    td_v = prof_pf.td[idx_start, idx_end]
    
    # add t and td from cf
    t_v = merge(t_v, |t_cf[i]|)
    td_v = merge(td_v, |td_cf[i]|)
    
    # compute means
    t_mean[i] = mean(t_v)
    td_mean[i] = mean(td_v)
    ddep_mean[i] = mean(t_v - td_v) + sidebar_x_offset
end for

# compute areas (polygons) for t, td and dew point depression (ddep)
# outer area = full ENS range
# inner area = 25-75 percentile range
p_poly = vector(lev_num*2)
t_poly_inner = vector(lev_num*2)
t_poly_outer = vector(lev_num*2)
td_poly_inner = vector(lev_num*2)
td_poly_outer = vector(lev_num*2)           
ddep_poly_inner = vector(lev_num*2)
ddep_poly_outer = vector(lev_num*2) 

for i=1 to lev_num do
    # collect t and td (pf+cf) for the given level
    t_v = prof_pf.t[(i-1)*ens_num+1, i*ens_num]
    td_v = prof_pf.td[(i-1)*ens_num+1, i*ens_num]
    t_v = merge(t_v, |t_cf[i]|)
    td_v = merge(td_v, |td_cf[i]|)
    
    i_left = i
    i_right = lev_num*2 - i + 1
    
    p_poly[i_left] = p[i]
    p_poly[i_right] = p[i]
    
    t_poly_outer[i_left] = minvalue(t_v)
    t_poly_outer[i_right] = maxvalue(t_v)
    perc = percentile(t_v, |25, 75|)
    t_poly_inner[i_left] = perc[1]
    t_poly_inner[i_right] = perc[2]
    
    td_poly_outer[i_left] = minvalue(td_v)
    td_poly_outer[i_right] = maxvalue(td_v)
    perc = percentile(td_v, |25, 75|)
    td_poly_inner[i_left] = perc[1]
    td_poly_inner[i_right] = perc[2]
    
    ddep_v = t_v - td_v + sidebar_x_offset
    ddep_poly_outer[i_left] = minvalue(ddep_v)
    ddep_poly_outer[i_right] = maxvalue(ddep_v)
    perc = percentile(ddep_v, |25, 75|)
    ddep_poly_inner[i_left] = perc[1]
    ddep_poly_inner[i_right] = perc[2]
    
end for    

# generate graphic objects (areas) for the shaded areas
gr_lst = [
    xy_area(t_poly_outer, p_poly, t_col_outer),
    xy_area(t_poly_inner, p_poly, t_col_inner),            
    xy_area(td_poly_outer, p_poly, td_col_outer),           
    xy_area(td_poly_inner, p_poly, td_col_inner),
    xy_area(ddep_poly_outer, p_poly, ddep_col_outer),           
    xy_area(ddep_poly_inner, p_poly, ddep_col_inner)
    ]
 
# generate graphic objects (curves) for the mean ENS and cf profiles
gr_lst = gr_lst & [
    xy_curve(t_mean, p, t_col_line, "solid", 4),           
    xy_curve(td_mean, p, td_col_line, "solid", 4),           
    xy_curve(ddep_mean, p, ddep_col_line, "solid", 4),               
    xy_curve(t_cf, prof_cf.p, t_col_line, "dash", 3),                      
    xy_curve(td_cf, prof_cf.p, td_col_line, "dash", 3),     
    xy_curve(ddep_cf, prof_cf.p, ddep_col_line, "dash", 3)
    ] 

# generate graphic object for wind profile from cf      
wind_x = vector(count(prof_cf.p_wind))
for i=1 to count(wind_x) do
    wind_x[i] = sidebar_x_offset + 10
end for
    
vis = input_visualiser(
        input_plot_type          : "xy_vectors",
		input_x_values           : wind_x,
		input_y_values           : prof_cf.p_wind,
		input_x_component_values : prof_cf.u,
		input_y_component_values : prof_cf.v
		)

wind_plotting = mwind(
		wind_field_type  : "flags",
		wind_flag_colour : "charcoal"
		)

gr_lst = gr_lst & [vis, wind_plotting]

# define title
title_txt = "ENS Tephigram Date: " & prof_cf.date & " " & prof_cf.time & " UTC " & 
            " Lat/Lon: " & prof_cf.lat & "/" & prof_cf.lon 

title = mtext(
    text_lines: title_txt, 
    text_font_size: 0.5,
    text_colour:  "charcoal"
    )

# define thermodynamic grid
grid = mthermogrid(
    thermo_isotherm_colour               : 'RGB(0.2577,0.6364,0.5039)',
    thermo_isotherm_reference_colour     : "blue",
    thermo_dry_adiabatic_colour          : "grey",
    thermo_dry_adiabatic_label_frequency : 2,
    thermo_mixing_ratio_colour           : 'RGB(0.2577,0.6364,0.5039)',
    thermo_mixing_ratio_label_colour     : 'RGB(0.2577,0.6364,0.5039)',
    thermo_mixing_ratio_label_font_size  : 0.4,
    thermo_grid_layer_mode               : "foreground"
    )

# define thermodynamic view
view = thermoview( type : "tephigram",
                   minimum_temperature : -110,
                   maximum_temperature : 30,
                   subpage_clipping: "on")	


# define the output plot file
setoutput(pdf_output(output_name : 'ens_tephigram'))

# generate the plot
plot(view, gr_lst, grid, title)
ENS Tephigram Example
""" 
ENS Tephigram
"""

#  **************************** LICENSE START ***********************************
# 
#  Copyright 2020 ECMWF. This software is distributed under the terms
#  of the Apache License version 2.0. In applying this license, ECMWF does not
#  waive the privileges and immunities granted to it by virtue of its status as
#  an Intergovernmental Organization or submit itself to any jurisdiction.
# 
#  ***************************** LICENSE END ************************************
# 

import numpy as np
import metview as mv

# read ENS data 
data = mv.read("ens_prof.grib")       

# define profile location
location = [17.51, -7.04]

# the starting x coordinate of the sidebar on the right.
# Wind and dewpoint depression is plotted there. 
# Do not change it! 
sidebar_x_offset = 1000

# the ensemble size (perturbed members)
ens_num = 50

# filter control (cf) and perturbed (pf) forcasts
g_cf = mv.read(data=data, type="cf")
g_pf = mv.read(data=data, type="pf")

# extract thermo profile for cf
nc = mv.thermo_grib(
    data=g_cf,
    point_extraction="nearest_gridpoint",
    coordinates=location	
   )
    
prof_cf = mv.thermo_data_values(nc, 0)    
 
# extract thermo profile for pf
nc = mv.thermo_grib(
    data=g_pf,
    point_extraction="nearest_gridpoint",
    coordinates=location	
   )
   
prof_pf = mv.thermo_data_values(nc, 0) 
    
# define colours for shaded areas
t_col_outer = 'RGB(1.0000,0.7922,0.7961)'
t_col_inner = 'RGB(0.8863,0.0000,0.0000)'
td_col_outer = 'RGB(0.8,0.9137,0.8)'
td_col_inner = 'RGB(0.3882,0.7765,0.3843)'
ddep_col_outer = 'RGB(0.8118,0.8902,1)'
ddep_col_inner = 'RGB(0.4353,0.6314,1)'

# define colours for curves
t_col_line = 'RGB(0.8706,0,0)'
td_col_line = 'RGB(0,0.2784,0.007843)'
ddep_col_line = 'RGB(0,0.3725,1)'

# define cf curve data
t_cf = prof_cf["t"]
td_cf = prof_cf["td"]
ddep_cf = (t_cf - td_cf) + sidebar_x_offset

# get pressure levels for t and td (from pf)
# and compute ENS mean profiles
lev_num = int(len(prof_pf["p"])/ens_num)
p = np.empty(lev_num)
t_mean = np.empty(lev_num)
td_mean = np.empty(lev_num)
ddep_mean = np.empty(lev_num)

for i in range(len(p)):
    # get pressure
    p[i] = prof_pf["p"][i*ens_num]
    
    # get t and td for all the perturbed members
    idx_start = i*ens_num
    idx_end = (i+1)*ens_num - 1
    t_v = prof_pf["t"][idx_start:idx_end]
    td_v = prof_pf["td"][idx_start:idx_end]
    
    # add t and td from cf
    t_v = np.append(t_v, t_cf[i])
    td_v = np.append(td_v, td_cf[i])
    
    # compute means
    t_mean[i] = mv.mean(t_v)
    td_mean[i] = mv.mean(td_v)
    ddep_mean[i] = mv.mean(t_v - td_v) + sidebar_x_offset

# compute areas (polygons) for t, td and dew point depression (ddep)
# outer area = full ENS range
# inner area = 25-75 percentile range
p_poly = np.empty(lev_num*2)
t_poly_inner = np.empty(lev_num*2)
t_poly_outer = np.empty(lev_num*2)
td_poly_inner = np.empty(lev_num*2)
td_poly_outer = np.empty(lev_num*2)           
ddep_poly_inner = np.empty(lev_num*2)
ddep_poly_outer = np.empty(lev_num*2) 

for i in range(lev_num):
    # collect t and td (pf+cf) for the given level
    idx_start = i*ens_num
    idx_end = (i+1)*ens_num - 1
    t_v = prof_pf["t"][idx_start:idx_end]
    td_v = prof_pf["td"][idx_start:idx_end]
    t_v = np.append(t_v, t_cf[i])
    td_v = np.append(td_v, td_cf[i])
    
    i_left = i
    i_right = 2*lev_num - i - 1
    
    p_poly[i_left] = p[i]
    p_poly[i_right] = p[i]
    
    t_poly_outer[i_left] = mv.minvalue(t_v)
    t_poly_outer[i_right] = mv.maxvalue(t_v)
    perc = mv.percentile(t_v, [25, 75])
    t_poly_inner[i_left] = perc[0]
    t_poly_inner[i_right] = perc[1]
    
    td_poly_outer[i_left] = mv.minvalue(td_v)
    td_poly_outer[i_right] = mv.maxvalue(td_v)
    perc = mv.percentile(td_v, [25, 75])
    td_poly_inner[i_left] = perc[0]
    td_poly_inner[i_right] = perc[1]
    
    ddep_v = t_v - td_v + sidebar_x_offset
    ddep_poly_outer[i_left] = mv.minvalue(ddep_v)
    ddep_poly_outer[i_right] = mv.maxvalue(ddep_v)
    perc = mv.percentile(ddep_v, [25, 75])
    ddep_poly_inner[i_left] = perc[0]
    ddep_poly_inner[i_right] = perc[1]
  
# generate graphic objects (areas) for the shaded areas
gr_lst = [
    mv.xy_area(t_poly_outer, p_poly, t_col_outer),
    mv.xy_area(t_poly_inner, p_poly, t_col_inner),            
    mv.xy_area(td_poly_outer, p_poly, td_col_outer),           
    mv.xy_area(td_poly_inner, p_poly, td_col_inner),
    mv.xy_area(ddep_poly_outer, p_poly, ddep_col_outer),           
    mv.xy_area(ddep_poly_inner, p_poly, ddep_col_inner)
    ]

# generate graphic objects (curves) for the mean ENS and cf profiles
gr_lst.extend([
    mv.xy_curve(t_mean, p, t_col_line, "solid", 4),           
    mv.xy_curve(td_mean, p, td_col_line, "solid", 4),           
    mv.xy_curve(ddep_mean, p, ddep_col_line, "solid", 4),               
    mv.xy_curve(t_cf, prof_cf["p"], t_col_line, "dash", 3),                      
    mv.xy_curve(td_cf, prof_cf["p"], td_col_line, "dash", 3),     
    mv.xy_curve(ddep_cf, prof_cf["p"], ddep_col_line, "dash", 3)
    ])

# generate graphic object for wind profile from cf      
vis = mv.input_visualiser(
        input_plot_type          = "xy_vectors",
		input_x_values           = [sidebar_x_offset + 10 for i in prof_cf["p_wind"]],
		input_y_values           = prof_cf["p_wind"],
		input_x_component_values = prof_cf["u"],
		input_y_component_values = prof_cf["v"]
		)

wind_plotting = mv.mwind(
		wind_field_type  = "flags",
		wind_flag_colour = "charcoal"
		)

gr_lst.extend([vis, wind_plotting])

# define title
title_txt = "ENS Tephigram Date: {} {} UTC Lat/Lon: {}/{} ".format(
            prof_cf["date"], prof_cf["time"], prof_cf["lat"], prof_cf["lon"]) 

title = mv.mtext(
    text_lines=title_txt, 
    text_font_size=0.5,
    text_colour="charcoal"
    )

# define thermodynamic grid
grid = mv.mthermogrid(
    thermo_isotherm_colour               = 'RGB(0.2577,0.6364,0.5039)',
    thermo_isotherm_reference_colour     = "blue",
    thermo_dry_adiabatic_colour          = "grey",
    thermo_dry_adiabatic_label_frequency = 2,
    thermo_mixing_ratio_colour           = 'RGB(0.2577,0.6364,0.5039)',
    thermo_mixing_ratio_label_colour     = 'RGB(0.2577,0.6364,0.5039)',
    thermo_mixing_ratio_label_font_size  = 0.4,
    thermo_grid_layer_mode               = "foreground"
    )

# define thermodynamic view
view = mv.thermoview( type = "tephigram",
                   minimum_temperature = -110,
                   maximum_temperature = 30,
                   subpage_clipping= "on")	


# define the output plot file
mv.setoutput(mv.pdf_output(output_name = 'ens_tephigram'))

# generate the plot
mv.plot(view, gr_lst, grid, title)