In [13]:
%%bash
# ls -lh /data/KTAL/Ka2/20150629/raw/
In [2]:
import pyart
import numpy as np
In [4]:
radar=pyart.io.read_sigmet('/data/KTAL/Ka2/20150629/raw/Ka2150629221426.RAW7A3V')
# print radar.latitude, radar.longitude, radar.altitude
In [5]:
from IPython.html import widgets
from IPython.display import display
In [6]:
import netCDF4
def diagnose_sweep_time_range(radar):
units = radar.time['units']
calendar = radar.time['calendar']
times = [radar.time['data'][sl] for sl in radar.iter_slice()]
swp_start_times = [netCDF4.num2date(t.min(), units, calendar) for t in times]
swp_end_times = [netCDF4.num2date(t.max(), units, calendar) for t in times]
return swp_start_times, swp_end_times
def diagnose_vcp(radar):
# swp_start = radar.sweep_start_ray_index['data']
# swp_end = radar.sweep_end_ray_index['data']+1
if 'ppi' in radar.scan_type.lower():
angles = [np.median(el) for el in radar.iter_elevation()]
else:
angles = [np.median(az) for az in radar.iter_azimuth()]
return angles
In [7]:
import matplotlib.pyplot as plt
field_range_defaults_ka = {
'reflectivity':[-32,32],
'velocity':[-12.9,12.9],
'spectrum_width':[0.0,1.0],
'total_power':[-30, 40]
}
field_range_defaults = field_range_defaults_ka
class RadarSelection(object):
def __init__(self, radar, sweep_id=0, field_id='reflectivity'):
""" This class is used by the RadarWidget, which has an interface for
selecting a sweep, to maintain the current selected radar data.
It decouples the radar widget view from the data selection operation
so that radar data can be selected programmatically as well.
"""
self.radar=radar
self._field_range_history = field_range_defaults.copy()
self.sweep_id = sweep_id
self.field_id = field_id
self.field_range = self._field_range_history[field_id]
def __str__(self):
rep = "{0}, {1}, {2}".format(self.field_id, self.field_range, self.sweep_id)
return rep
@property
def sweep_id(self):
return self._sweep_id
@sweep_id.setter
def sweep_id(self, value):
self._sweep_id = int(value)
@property
def field_id(self):
return self._field_id
@field_id.setter
def field_id(self, value):
self._field_id = value
try:
self.field_range = self._field_range_history[self._field_id]
except KeyError:
print "No default range for field {0}. Setting to a wide range.".format(value)
self.field_range = [-100.0, 100.0]
@property
def field_range(self):
return self._field_range
@field_range.setter
def field_range(self, value):
if len(value) <> 2:
raise ValueError, "Must be two values in range."
self._field_range = value
self._field_range_history[self.field_id] = self._field_range
class RadarWidget(object):
def __init__(self, radar, on_scan_changed=None):
""" Expects a PyART radar object"""
self.on_scan_changed = on_scan_changed
self.radar=radar
self.radar_selection = RadarSelection(self.radar)
self.__make_location_widget()
self.__make_sweep_stats_widget()
self.__make_scan_select_widget()
self.__make_master_widget()
self.update()
self.scan_changed()
def __make_master_widget(self):
row0 = (self.w_location,
self.w_stats,
)
row1 = (self.w_scan_select,
)
self.w_location.width = '50%'
self.w_stats.width = '50%'
self.w_scan_select.width = '50%'
w_row0 = widgets.HBox(children=row0)
w_row1 = widgets.HBox(children=row1)
children = (w_row0, w_row1)
self.master_widget = widgets.VBox(children = children)
def scan_changed(self, defer=False):
if defer == False:
if self.on_scan_changed is not None:
self.on_scan_changed()
def update(self):
""" Refresh data in boxes from radar object """
self._update_location_widget()
self._update_sweep_stats_widget()
self._update_scan_select_widget()
self.radar_selection.field_id = self.w_field_choice.value
self.w_field_min.value, self.w_field_max.value = self.radar_selection.field_range
# self.radar_selection.field_range = [self.w_field_min.value, self.w_field_max.value]
# ----- Location -----
def _update_location_widget(self):
self.w_ctrlon.value = self.radar.longitude['data'][0]
self.w_ctrlat.value = self.radar.latitude['data'][0]
self.w_ctralt.value = self.radar.altitude['data'][0]
def _radar_location_changed(self):
self.radar.longitude['data'][0] = self.w_ctrlon.value
self.radar.latitude['data'][0] = self.w_ctrlat.value
self.radar.altitude['data'][0] = self.w_ctralt.value
def __make_location_widget(self):
self.w_ctrlon = widgets.FloatText(description='Lon')
self.w_ctrlat = widgets.FloatText(description='Lat')
self.w_ctralt = widgets.FloatText(description='Alt')
children = (self.w_ctrlon, self.w_ctrlat, self.w_ctralt)
self.w_location = widgets.VBox(children = children)
# ----- Info box / stats readout -----
def _update_sweep_stats_widget(self):
metadata = "Gates: {0}, Rays: {1}, Sweeps: {2} \nScan Type: {3}, {4}\nBeamwidth: {5}"
stats = metadata.format(
self.radar.ngates, self.radar.nrays, self.radar.nsweeps,
self.radar.scan_type, self.radar.sweep_mode['data'][0],
self.radar.instrument_parameters['radar_beam_width_h']['data'][0])
self.w_sweep_stats.value = stats
def __make_sweep_stats_widget(self):
self.w_sweep_stats = widgets.Textarea()
children = (self.w_sweep_stats,)
self.w_stats = widgets.Box(children = children)
# ----- Scan Selection Parameters -----
def _update_scan_select_widget(self, time_format = '%H%M:%S'):
self.w_field_choice.options = self.radar.fields.keys()
vcp = diagnose_vcp(self.radar)
starts, ends = diagnose_sweep_time_range(self.radar)
angles = [u'{0}: {1:6.2f}°, {2} - {3}'.format(ai, ang,
t0.strftime(time_format),
t1.strftime(time_format))
for ai, (ang, t0, t1) in enumerate(zip(vcp, starts, ends))]
# angles = [str(ang) for ang in diagnose_vcp(ka1)]
self.w_angle_choice.options = angles
def _scan_selected(self, name, value):
swp_id = int(value.split(':')[0])
self.radar_selection.sweep_id = swp_id
self.scan_changed()
def _field_selected(self, name, value):
self.radar_selection.field_id = value
self.w_field_min.value = self.radar_selection.field_range[0]
self.w_field_max.value = self.radar_selection.field_range[1]
self.scan_changed()
def _range_min_changed(self, name, value):
self.radar_selection.field_range[0] = value
self.scan_changed(defer=True)
def _range_max_changed(self, name, value):
self.radar_selection.field_range[1] = value
self.scan_changed(defer=True)
def __make_scan_select_widget(self):
self.w_field_choice = widgets.Select(description='Field')
self.w_field_min = widgets.FloatText(description = 'Range')
self.w_field_max = widgets.FloatText()
self.w_field_range_box = widgets.HBox(children=(self.w_field_min, self.w_field_max))
self.w_angle_choice = widgets.Select(description='Angle')
self.w_angle_choice.on_trait_change(self._scan_selected, 'value')
self.w_field_choice.on_trait_change(self._field_selected, 'value')
self.w_field_min.on_trait_change(self._range_min_changed, 'value')
self.w_field_max.on_trait_change(self._range_max_changed, 'value')
children = (widgets.VBox(children=(self.w_field_choice,
self.w_field_range_box)),
self.w_angle_choice)
self.w_scan_select = widgets.HBox(children = children)
In [8]:
class RadarSweepView(object):
def __init__(self, radar_selection):
self.radar_selection = radar_selection
self.fig = plt.figure()
self.display = pyart.graph.RadarDisplay(self.radar_selection.radar)
plt.show(block=False)
def update(self):
self.fig.clf()
field_range = self.radar_selection.field_range
field_id = self.radar_selection.field_id
sweep_id = self.radar_selection.sweep_id
self.display.plot(field_id, sweep=sweep_id,
vmin=field_range[0], vmax=field_range[1],
fig = self.fig)
self.fig.canvas.draw()
class RadarSweepViewWidget(object):
def __init__(self, radar_sweep_view):
self.radar_sweep_view = radar_sweep_view
self.w_draw_widget = widgets.Button(description='Draw')
self.w_draw_widget.on_click(self.update)
children = (self.w_draw_widget,)
self.master_widget = widgets.HBox(children=children)
def update(self, value):
self.radar_sweep_view.update()
radar_widget = RadarWidget(radar)
view = RadarSweepView(radar_widget.radar_selection)
view_widget = RadarSweepViewWidget(view)
radar_widget.on_scan_changed = view.update
display(radar_widget.master_widget)
display(view_widget.master_widget)
view.update()
In [16]:
view.update()
In [ ]:
In [ ]: