# (C) British Crown Copyright 2017, Met Office
#
# This code is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# Plot reanalysis pressure and DWR comparisons - scatter and error plots.
import iris
import iris.analysis
import DWR
import matplotlib
import matplotlib.cm
import numpy
import pandas
import collections
[docs]def plot_rotated_scatter(ax,field,obs,dte,**kwargs):
"""Make a scatter plot rotated so 1:1 is horizontal
Args:
ax (:`cartopy.axes`): Axes to hold the plot
field (:obj:`iris.Cube.cube`): Reanalysis ensemble
obs (:obj:`pandas.DataFrame`): DWR observations.
dte (:obj:`datetime.datetime`): Time of plot
Kwargs:
x_range (:obj:`list`): x range in scatterplot, default is (945.0,1045.0).
x_label (:obj:`str`): x label, default is 'Observed MSLP (hPa)'.
y_range (:obj:`list`): y range in scatterplot, default is (-20.0,20.0).
y_label (:obj:`str`): y label, default is 'Ensemble-Observed MSLP (hPa)'.
point_size (:obj:`float`): Plot plot size, default 10.0.
point_size (:obj:`str`): Plot plot color, default 'blue'.
|
"""
# Set keyword argument defaults
kwargs.setdefault('x_range',(945.0,1045.0))
kwargs.setdefault('x_label','Observed MSLP (hPa)')
kwargs.setdefault('y_range',(-20.0,20.0))
kwargs.setdefault('y_label','Ensemble-Observed MSLP (hPa)')
kwargs.setdefault('point_size',10.0)
kwargs.setdefault('point_color','blue')
# x & y-axis
ax.set_xlim(kwargs.get('x_range'))
ax.set_xlabel(kwargs.get('x_label'))
ax.set_ylim(kwargs.get('y_range'))
ax.set_ylabel(kwargs.get('y_label'))
stations=list(collections.OrderedDict.fromkeys(obs.loc[:,'name']).keys())
# Get a pressure interpolated to the selected time for each station
interpolated={}
for station in stations:
try:
interpolated[station]=DWR.at_station_and_time(
obs,station,dte)
except Exception:
interpolated[station]=None
# Get the reanalysis ensemble at the station locations
ensemble={}
interpolator = iris.analysis.Linear().interpolator(field,
['latitude', 'longitude'])
for station in stations:
latlon=DWR.get_station_location(obs,station)
ensemble[station]=interpolator([latlon['latitude'],
latlon['longitude']]).data
# Background 1-to-1 line
ax.add_line(matplotlib.lines.Line2D(
xdata=kwargs.get('x_range'),
ydata=(0,0),
linestyle='solid',
linewidth=1,
color=(0.5,0.5,0.5,1),
zorder=1))
# Plot the ensembles
for station in stations:
if interpolated[station] is None: continue
obs_ens=[interpolated[station]]*len(ensemble[station])
ens_dif=[ensemble[station][i]-obs_ens[i]
for i in range(len(obs_ens))]
ax.scatter(obs_ens,
ens_dif,
s=kwargs.get('point_size'),
marker='o',
c=kwargs.get('point_color'),
linewidths=0.1,
edgecolors=kwargs.get('point_color'))
[docs]def plot_deviation_spread(ax,field,obs,dte,**kwargs):
"""Make a plot comparing ensemble spread with expectation
Args:
ax (:`cartopy.axes`): Axes to hold the plot
field (:obj:`iris.Cube.cube`): Reanalysis ensemble
obs (:obj:`pandas.DataFrame`): DWR observations.
dte (:obj:`datetime.datetime`): Time of plot
Kwargs:
x_range (:obj:`list`): x range in plot, default is (-20,20.0).
x_label (:obj:`str`): x label, default is 'Observation-ensemble mean (hPa)'.
y_range (:obj:`list`): y range in scatterplot, default is (0.0,10.0).
y_label (:obj:`str`): y label, default is 'Ensemble standard deviation (hPa)'.
point_size (:obj:`float`): Plot plot size, default 10.0.
point_size (:obj:`str`): Plot plot color, default 'blue'.
obs_error (:obj:`float`): Assumed observation error (hPa), default 2.0.
|
"""
# Set keyword argument defaults
kwargs.setdefault('x_range',(-20.0,20.0))
kwargs.setdefault('x_label','Observation-ensemble mean (hPa)')
kwargs.setdefault('y_range',(0.0,10.0))
kwargs.setdefault('y_label','Ensemble standard deviation (hPa)')
kwargs.setdefault('point_size',30.0)
kwargs.setdefault('point_color','blue')
kwargs.setdefault('obs_error',2.0)
# x & y-axis
ax.set_xlim(kwargs.get('x_range'))
ax.set_xlabel(kwargs.get('x_label'))
ax.set_ylim(kwargs.get('y_range'))
ax.set_ylabel(kwargs.get('y_label'))
stations=list(collections.OrderedDict.fromkeys(obs.loc[:,'name']).keys())
# Get a pressure interpolated to the selected time for each station
interpolated={}
for station in stations:
try:
interpolated[station]=DWR.at_station_and_time(
obs,station,dte)
except Exception:
interpolated[station]=None
# Get the reanalysis ensemble at the station locations
ensemble={}
interpolator = iris.analysis.Linear().interpolator(field,
['latitude', 'longitude'])
for station in stations:
latlon=DWR.get_station_location(obs,station)
ensemble[station]=interpolator([latlon['latitude'],
latlon['longitude']]).data
# Expected ensemble sd
exp_x=numpy.arange(kwargs.get('x_range')[0],
kwargs.get('x_range')[1],0.01)
exp_y=numpy.sqrt(numpy.maximum(exp_x**2-kwargs.get('obs_error')**2,0))
ax.add_line(matplotlib.lines.Line2D(
xdata=exp_x, ydata=exp_y,
linestyle='solid',
linewidth=1,
color=(0.5,0.5,0.5,1),
zorder=1))
# Plot the ensembles
for station in stations:
if interpolated[station] is None: continue
ax.scatter(numpy.mean(ensemble[station])-interpolated[station],
numpy.std(ensemble[station]),
s=kwargs.get('point_size'),
marker='o',
c=kwargs.get('point_color'),
linewidths=0.1,
edgecolors='black')