"""
defaults
===============
This module fills the plots with values specified in defaults
and fills the remaining options with placeholders so that
existence checks will not be needed later.
..moduleauthor:: David Fallis
"""
import numpy as np
from . import constants
from matplotlib.colors import LogNorm
DEFAULTS = {'plotprojection': 'mercator',
'data_type': 'climatology',
'set_yscale': 'log',
'frequency': 'mon',
'realization': 1,
'scale': 1,
'shift': 0,
'pdf': True,
'png': False,
'comp_flag': None,
'remap': 'remapdis',
'remap_grid': 'r360x180',
'alpha': 0.05,
'sigma': 0.05,
'cdostring': None,
'units': None,
'divergent': False,
'yearmean': False,
'extra_variables': [],
'extra_obs': [],
'external_function': None,
'external_function_args': {},
'use_common_levels': False,
}
MODELS = ['bcc-csm1-1',
'CanAM4',
'CanESM2',
'CMCC-CESM',
'CMCC-CM',
'CMCC-CMS',
'CNRM-CM5',
'CNRM-CM5-2',
'CFSv2-2011',
'ACCESS1-0',
'ACCESS1-3',
'CSIRO-Mk3.6.0',
'EC-EARTH',
'FIO-ESM',
'BNU-ESM',
'INM-CM4',
'IPSL-CM5a-LR',
'IPSL-CM5A-MR',
'IPSL-CM5B-LR',
'FGOALS-g2',
'FGOALS-gl',
'FGOALS-s2',
'MIROC4h',
'MIROC5',
'MIROC-ESM',
'MIROC-ESM-CHEM',
'HadCM3',
'HadCM3Q',
'HadGEM2-A'
'HadGEM2-CC',
'HadGEM2-ES',
'MPI-ESM-LR',
'MPI-ESM-MR',
'MPI-ESM-P',
'MRI-AGCM3.2H',
'MRI-AGCM3.2S',
'MRI-CGCM3',
'MRI-ESM1',
'GISS-E2-H',
'GISS-E2-H-CC',
'GISS-E2-R',
'GISS-E2-R-CC',
'GEOS-5',
'CCSM4',
'NorESM1-M',
'NorESM-ME',
'NICAM.09',
'HadGEM2-AO',
'GFDL-CM2p1',
'GFDL-CM3',
'GFDL-ESM2G',
'GFDL-ESM2M',
'GFDL-HIRAM-C180',
'GFDL-HIRAM-C360',
'CESM1',
]
piControl = {'dates': {'start_date': '2900-01',
'end_date': '3000-01'},
}
historical = {'dates': {'start_date': '1986-01',
'end_date': '2005-01'},
}
rcp = {'dates': {'start_date': '2081-01',
'end_date': '2100-01'},
}
norms = {'lognorm': LogNorm()}
[docs]def fill(plots, run, experiment, cmip6_verification=False, defaults={}):
"""
Fills the blank spaces in plots with default values.
Parameters
----------
plots : list of dictionaries
model_run : string
run ID
experiment : string
experiment name
defaults : dictionary
values to fill plots
Returns
-------
list of dictionaries
"""
if not defaults:
defaults = {}
for p in plots:
# remove plot from list if no variable is provided
if 'variable' not in p:
plots.remove(p)
print(p)
print('deleted: no variable provided')
#For CanESM5 runs remove plot from list if no table_id is provided
if 'table_id' not in p:
if run == 'CanESM5':
plots.remove(p)
print(p)
print('deleted: no table_id provided')
else:
p['table_id'] = None
if plots == []:
print('Aborted: there are no variables to plot')
exit()
for p in plots:
# fill plots with the defaults given in conf.yaml
for key in defaults:
if key not in p:
p[key] = defaults[key]
# fill plots with immutable global DEFAULTS
for key in DEFAULTS:
if key not in p:
p[key] = DEFAULTS[key]
# fill plots with mutable global defaults
if 'comp_models' not in p:
p['comp_models'] = []
if 'comp_cmips' not in p:
p['comp_cmips'] = []
if p['comp_cmips'] == None:
p['comp_cmips'] = []
if 'comp_ids' not in p:
p['comp_ids'] = []
if p['comp_ids'] == None:
p['comp_ids'] = []
if 'comp_obs' not in p:
p['comp_obs'] = []
if p['comp_obs'] == None:
p['comp_obs'] = []
if 'data1' not in p:
p['data1'] = {}
if 'data2' not in p:
p['data2'] = {}
if 'comp' not in p:
p['comp'] = {}
if 'comp_ensembles' not in p:
p['comp_ensembles'] = []
else:
for ensemble_type in list(p['comp_ensembles'].keys()):
if p['comp_ensembles'][ensemble_type] == ['all']:
p['comp_ensembles'][ensemble_type] = np.arange(0,1000,1)
p['comp_ensembles'][ensemble_type] = [str(ens_member) for ens_member in p['comp_ensembles'][ensemble_type]]
for ensemble_type in ['realizations', 'initializations', 'physics', 'forcings']:
if ensemble_type not in p['comp_ensembles']:
p['comp_ensembles'][ensemble_type] = ['1']
if 'depths' not in p:
p['depths'] = [""]
if 'seasons' not in p:
p['is_season'] = False
p['seasons'] = ['DJF', 'MAM', 'JJA', 'SON']
else:
p['is_season'] = True
if 'comp_seasons' not in p:
p['comp_seasons'] = p['seasons']
if 'cmip5_file' not in p:
p['cmip5_file'] = None
if 'cmip5_files' not in p:
p['cmip5_files'] = []
if p['comp_models'] == 'all':
p['comp_models'] = list(MODELS)
if p['comp_cmips'] == 'all':
p['comp_cmips'] = list(MODELS)
if 'comp_scale' not in p:
p['comp_scale'] = p['scale']
if 'comp_shift' not in p:
p['comp_shift'] = p['shift']
if 'extra_scales' not in p:
p['extra_scales'] = [1] * len(p['extra_variables'])
if 'extra_comp_scales' not in p:
p['extra_comp_scales'] = p['extra_scales']
if 'extra_shifts' not in p:
p['extra_shifts'] = [0] * len(p['extra_variables'])
if 'extra_comp_shifts' not in p:
p['extra_comp_shifts'] = p['extra_shifts']
# add dates based on experiment
if 'piControl' in experiment:
for key in piControl:
if key not in p:
p[key] = piControl[key]
elif 'rcp' in experiment:
for key in piControl:
if key not in p:
p[key] = rcp[key]
else:
for key in piControl:
if key not in p:
p[key] = historical[key]
if 'plot_args' not in p:
p['plot_args'] = {}
if 'comp_dates' not in p:
p['comp_dates'] = p['dates']
p['model_ID'] = run
p['experiment'] = experiment
p['plot_depth'] = 0
p['cmip6_verification'] = cmip6_verification
def _default_plot_args(projection):
if projection == 'global_map':
return {'latmin': 50, 'latmax': 50, 'lonmin': 0, 'lonmax': 360}
if projection == 'mercator':
return {'latmin': -80, 'latmax': 80, 'lonmin': 0, 'lonmax': 360}
if projection == 'polar_map':
return {'latmin': 45, 'latmax': 80, 'lonmin': 0, 'lonmax': 360, 'lon_0': 180}
if projection == 'polar_map_south':
return {'latmin': -80, 'latmax': -45, 'lonmin': 0, 'lonmax': 360, 'lon_0': 180}
return {}
default_pargs = _default_plot_args(p['plot_projection'])
for key in default_pargs:
if key not in p['plot_args']:
p['plot_args'][key] = default_pargs[key]
def _fill_args(data):
if 'ax_args' not in p[data]:
p[data]['ax_args'] = {}
if 'pcolor_args' not in p[data]:
p[data]['pcolor_args'] = {}
if 'title' not in p[data]['ax_args']:
p[data]['title_flag'] = False
else:
p[data]['title_flag'] = True
if 'vmin' not in p[data]['pcolor_args']:
p[data]['pcolor_flag'] = False
else:
p[data]['pcolor_flag'] = True
if 'norm' in p[data]['pcolor_args']:
try:
p[data]['pcolor_args']['norm'] = norms[p[data]['pcolor_args']['norm']]
except:
pass
if 'discrete_colorbar' not in p[data]:
p[data]['discrete_colorbar'] = True
if 'show_stats' not in p[data]:
p[data]['show_stats'] = False
_fill_args('data1')
_fill_args('data2')
_fill_args('comp')
def _section_labels(datanumber, pl):
""" Gives the axes of a section appropriate labels
Parameters
----------
datanumber : string
name of the data
plot : dictionary
Returns
-------
dictionary
"""
pl[datanumber]['ax_args']['xlabel'] = 'Latitude'
pl[datanumber]['ax_args']['xticks'] = np.arange(-80, 81, 20)
if pl['realm'] == 'atmos':
pl[datanumber]['ax_args']['ylabel'] = 'Pressure'
else:
pl[datanumber]['ax_args']['ylabel'] = 'Depth'
def _zonal_labels(datanumber, pl):
pl[datanumber]['ax_args']['xlabel'] = 'Latitude'
pl[datanumber]['ax_args']['xticks'] = np.arange(-80, 81, 20)
[docs]def filltitle(p):
def fill(comp):
if not p['data1']['title_flag']:
# set main title
if p['cmip6_verification']:
p['data1']['ax_args']['title'] = "{} ({})\nunits:{}, freq:{}, ann {}, {}, r{}\n{} to {}".format(
p['long_name'],p['variable'],p['units'],p['frequency'],p['data_type'],p['model_ID'],p['realization'],p['dates']['start_date'],p['dates']['end_date'])
p['data1']['footnote'] = None
else:
if p['comp_ensembles']:
p['data1']['ax_args']['title'] = "{} {} {}, ensemble comparison, freq:{}, {} to {}".format(
p['variable'],p['data_type'],p['model_ID'],p['frequency'],p['dates']['start_date'],p['dates']['end_date'])
p['data1']['footnote'] = str(p['model_ID']) + ' ensemble members plotted:\n ' + ', '.join(sorted(p['ensemble_files']))
else:
p['data1']['ax_args']['title'] = "{} {} {}, r{}, freq:{}, {} to {}".format(
p['variable'],p['data_type'],p['model_ID'],p['realization'],p['frequency'],p['dates']['start_date'],p['dates']['end_date'])
p['data1']['footnote'] = None
if not p['data2']['title_flag']:
# set title for plot of comparison data
p['data2']['ax_args']['title'] = comp
if not p['comp']['title_flag']:
# set title for results of comparison plot
p['comp']['ax_args']['title'] = "{} - {}".format(p['model_ID'],comp)
if p['is_depth'] or p['is_season']:
# add season/depth info to main title
tmp_str = '\n'
if p['is_depth']: tmp_str += " Depth: {}".format(p['plot_depth'])
if p['is_season']: tmp_str += " Seasons: {}".format(" ".join(p['seasons']))
p['data1']['ax_args']['title'] += tmp_str
if p['comp_flag'] == 'model':
fill(p['comp_model'])
elif p['comp_flag'] == 'runid':
fill(p['comp_model'])
elif p['comp_flag'] == 'obs':
fill(p['comp_model'])
else:
if p['comp_flag']:
fill(p['comp_flag'])
else:
fill("")
if p['plot_projection'] == 'section':
_section_labels('data1', p)
_section_labels('data2', p)
_section_labels('comp', p)
if p['plot_projection'] == 'zonal_mean':
_zonal_labels('data1', p)
_zonal_labels('data2', p)
_zonal_labels('comp', p)