Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Time-height displays. #453

Merged
merged 5 commits into from
Jan 19, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyart/core/radar.py
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,7 @@ def join_radar(radar1, radar2):
r2num = date2num(r2dt, estring)
new_radar.time['data'] = np.append(r1num, r2num)
new_radar.time['units'] = estring
### TODO Use new updated datetime_utils if accepted

for var in new_radar.fields.keys():
sh1 = radar1.fields[var]['data'].shape
Expand Down
58 changes: 54 additions & 4 deletions pyart/graph/radardisplay.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@
import matplotlib.pyplot as plt
import numpy as np
import netCDF4
from matplotlib.dates import (
DateFormatter, SecondLocator, MinuteLocator,
HourLocator, DayLocator)

from . import common
from ..core.transforms import antenna_to_cartesian
from ..core.transforms import antenna_vectors_to_cartesian
from ..core.transforms import corner_to_point
from ..util.datetime_utils import datetimes_from_radar


class RadarDisplay(object):
Expand Down Expand Up @@ -486,7 +490,10 @@ def plot_vpt(self, field, mask_tuple=None, vmin=None, vmax=None,
axislabels=(None, None), axislabels_flag=True,
colorbar_flag=True, colorbar_label=None,
colorbar_orient='vertical', edges=True,
filter_transitions=True, ax=None, fig=None):
filter_transitions=True,
time_axis_flag=False,
date_time_form=None, tz=None,
ax=None, fig=None):
"""
Plot a VPT scan.

Expand Down Expand Up @@ -542,6 +549,15 @@ def plot_vpt(self, field, mask_tuple=None, vmin=None, vmax=None,
sweeps from the plot. False will include these rays in the plot.
No rays are filtered when the antenna_transition attribute of the
underlying radar is not present.
time_axis_flag : bool
True to plot the x-axis as time. False uses the index number.
Default is False - index-based.
date_time_form : str, optional
Format of the time string for x-axis labels. Parameter is
ignored if time_axis_flag is set to False.
tz : str, optional
Time zone info to use when creating axis labels (see datetime).
Parameter is ignored if time_axis_flag is set to False.
ax : Axis
Axis to plot on. None will use the current axis.
fig : Figure
Expand All @@ -567,6 +583,11 @@ def plot_vpt(self, field, mask_tuple=None, vmin=None, vmax=None,
x = np.arange(data.shape[1])
y = self.ranges / 1000.

# set up the time axis
if time_axis_flag:
self._set_vpt_time_axis(ax, date_time_form=date_time_form, tz=tz)
x = datetimes_from_radar(radar)

# mask the data where outside the limits
if mask_outside:
data = np.ma.masked_invalid(data)
Expand All @@ -579,7 +600,7 @@ def plot_vpt(self, field, mask_tuple=None, vmin=None, vmax=None,
self._set_vpt_title(field, title, ax)

if axislabels_flag:
self._label_axes_vpt(axislabels, ax)
self._label_axes_vpt(axislabels, time_axis_flag, ax)

# add plot and field to lists
self.plots.append(pm)
Expand Down Expand Up @@ -933,6 +954,11 @@ def label_xaxis_rays(self, ax=None):
ax = common.parse_ax(ax)
ax.set_xlabel('Ray number (unitless)')

def label_xaxis_time(self, ax=None):
""" Label the yaxis with the default label for rays. """
ax = common.parse_ax(ax)
ax.set_xlabel('Time (HH:MM)')

def label_yaxis_field(self, field, ax=None):
""" Label the yaxis with the default label for a field units. """
ax = common.parse_ax(ax)
Expand Down Expand Up @@ -1007,18 +1033,42 @@ def _label_axes_ray(self, axis_labels, field, ax):
else:
ax.set_ylabel(y_label)

def _label_axes_vpt(self, axis_labels, ax):
def _label_axes_vpt(self, axis_labels, time_axis_flag, ax):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'test_radardisplay_user_specified_labels' test in test_radar_display.py assumes this method takes 3 parameters. It should be updates with the new call signature (add False before the ax parameter).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

""" Set the x and y axis labels for a PPI plot. """
x_label, y_label = axis_labels
if x_label is None:
self.label_xaxis_rays(ax)
if time_axis_flag:
self.label_xaxis_time(ax)
else:
self.label_xaxis_rays(ax)
else:
ax.set_xlabel(x_label)
if y_label is None:
self.label_yaxis_z(ax)
else:
ax.set_ylabel(y_label)

def _set_vpt_time_axis(self, ax, date_time_form=None, tz=None):
""" Set the x axis as a time formatted axis.

Parameters
----------
ax : Matplotlib axis instance
Axis to plot. None will use the current axis.
date_time_form : str
Format of the time string for x-axis labels.
tz : str
Time zone info to use when creating axis labels (see datetime).
"""
if date_time_form is None:
date_time_form = '%H:%M'

# Set the date format
date_Fmt = DateFormatter(date_time_form, tz=tz)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this used anywhere?


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not seeing any minor ticks in my plot, might have something incorrect but it would be good to tests this. I'm also not apposed to not adding minor ticks and leaving this customization to the users.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be too much customization to include. I'll remove it.

# Turn the tick marks outward
ax.tick_params(which='both', direction='out')

##########################
# name generator methods #
##########################
Expand Down
2 changes: 1 addition & 1 deletion pyart/graph/tests/test_radar_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def test_radardisplay_user_specified_labels():
assert ax.get_xlabel() == 'baz'
assert ax.get_ylabel() == 'qux'

display._label_axes_vpt(('nick', 'nock'), ax)
display._label_axes_vpt(('nick', 'nock'), False, ax)
assert ax.get_xlabel() == 'nick'
assert ax.get_ylabel() == 'nock'
plt.close()
Expand Down
55 changes: 42 additions & 13 deletions pyart/util/datetime_utils.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,59 @@
""" Functions for converting date and time between various forms """

from netCDF4 import num2date
from netCDF4 import num2date, date2num

EPOCH_UNITS = "seconds since 1970-01-01T00:00:00Z"

def datetime_from_radar(radar):

def datetime_from_radar(radar, epoch=False):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There needs to be two blank lines before this function to meet PEP8 conventions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't know that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pep8 tool is really helpful to find these. I tend to run in on all Python files I work on before checking the files into git.

""" Return a datetime for the first ray in a Radar. """
return num2date(radar.time['data'][0], radar.time['units'])
if epoch:
dtrad = num2date(radar.time['data'][0], radar.time['units'])
epnum = date2num(dtrad, EPOCH_UNITS)
return num2date(epnum, EPOCH_UNITS)
else:
return num2date(radar.time['data'][0], radar.time['units'])


def datetimes_from_radar(radar):
def datetimes_from_radar(radar, epoch=False):
""" Return an array of datetimes for the rays in a Radar. """
return num2date(radar.time['data'][:], radar.time['units'])
if epoch:
dtrad = num2date(radar.time['data'][:], radar.time['units'])
epnum = date2num(dtrad, EPOCH_UNITS)
return num2date(epnum, EPOCH_UNITS)
else:
return num2date(radar.time['data'][:], radar.time['units'])


def datetime_from_dataset(dataset):
def datetime_from_dataset(dataset, epoch=False):
""" Return a datetime for the first time in a netCDF Dataset. """
return num2date(dataset.variables['time'][0],
dataset.variables['time'].units)
if epoch:
dtdata = num2date(dataset.variables['time'][0],
dataset.variables['time'].units)
epnum = date2num(dtdata, EPOCH_UNITS)
return num2date(epnum, EPOCH_UNITS)
else:
return num2date(dataset.variables['time'][0],
dataset.variables['time'].units)


def datetimes_from_dataset(dataset):
def datetimes_from_dataset(dataset, epoch=False):
""" Return an array of datetimes for the times in a netCDF Dataset. """
return num2date(dataset.variables['time'][:],
dataset.variables['time'].units)
if epoch:
dtdata = num2date(dataset.variables['time'][:],
dataset.variables['time'].units)
epnum = date2num(dtdata, EPOCH_UNITS)
return num2date(epnum, EPOCH_UNITS)
else:
return num2date(dataset.variables['time'][:],
dataset.variables['time'].units)


def datetime_from_grid(grid):
def datetime_from_grid(grid, epoch=False):
""" Return a datetime for the volume start in a Grid. """
return num2date(grid.time['data'][0], grid.time['units'])
if epoch:
dtrad = num2date(grid.time['data'][0], grid.time['units'])
epnum = date2num(dtrad, EPOCH_UNITS)
return num2date(epnum, EPOCH_UNITS)
else:
return num2date(grid.time['data'][0], grid.time['units'])