crash.py
python
last edit: Aug, 11th 2011 | jump to bottom
__author__ = 'brycehendrix@gmail.com' import urllib2, urllib import json import math import os import numpy from enthought.chaco.api import Plot, ArrayPlotData, ImageData from enthought.chaco.tools.api import PanTool, ZoomTool, LineInspector from enthought.enable.api import ComponentEditor from enthought.traits.api import HasTraits, Array, Int, Instance, Property, \ cached_property, Any, Float, Tuple, on_trait_change from enthought.traits.ui.api import View, Item, VGroup class Route(HasTraits): latitudes = Array longitudes = Array positions = Property(Array, depends_on='latitudes, longitudes') data_bounds = Property(Tuple, depends_on='latitudes, longitudes') distances = Array speeds = Array altitudes = Array center = Array zoom = Int map_image = Property(Any, depends_on='latitudes, longitudes') map_padding = Float(0.2) map_plot = Instance(Plot) alt_plot = Instance(Plot) speed_plot = Instance(Plot) traits_view = View(VGroup(Item('map_plot', editor=ComponentEditor(width=640, height=480), show_label=False, width=640, height=0.6), Item('alt_plot', editor=ComponentEditor(width=640, height=100), show_label=False, width=640, height=0.2), Item('speed_plot', editor=ComponentEditor(width=640, height=100), show_label=False, width=640, height=0.2)), title='Route Data', height=800) def __init__(self, *args, **kw): super(Route, self).__init__(*args, **kw) # tie the alt plot and speed plot's horizontal range so # panning left and right is synchronized self.alt_plot.index_range = self.speed_plot.index_range def _alt_plot_default(self): plot_data = ArrayPlotData() plot_data.set_data('alt', self.altitudes/1.609) plot_data.set_data('dist', self.distances/1.609) plot = Plot(plot_data) renderer = plot.plot(('dist', 'alt'), color='red')[0] index_inspector = LineInspector(renderer, axis='index', write_metadata=True) value_inspector = LineInspector(renderer, axis='value', write_metadata=True) renderer.tools += [index_inspector, value_inspector] renderer.overlays += [index_inspector, value_inspector] plot.tools.append(ZoomTool(plot)) plot.tools.append(PanTool(plot)) plot.padding=[40,10,0,0] return plot def _speed_plot_default(self): plot_data = ArrayPlotData() plot_data.set_data('speed', self.speeds * (3600.0/1000)/1.609) plot_data.set_data('dist', self.distances/1.609) plot = Plot(plot_data) renderer = plot.plot(('dist', 'speed'), color='red')[0] index_inspector = LineInspector(renderer, axis='index', write_metadata=True) value_inspector = LineInspector(renderer, axis='value', write_metadata=True) renderer.tools += [index_inspector, value_inspector] renderer.overlays += [index_inspector, value_inspector] plot.tools.append(ZoomTool(plot)) plot.tools.append(PanTool(plot)) plot.padding=[40,10,0,20] return plot def _map_plot_default(self): lat, lon = self._lat_lon_to_screen(self.latitudes, self.longitudes) plot_data = ArrayPlotData() plot_data.set_data('image', self.map_image) plot_data.set_data('lon', lon) plot_data.set_data('lat', lat) plot_data.set_data('sel_lon', numpy.array([])) plot_data.set_data('sel_lat', numpy.array([])) plot = Plot(plot_data, default_origin='bottom left') plot.img_plot('image') plot.plot(('lon', 'lat'), type='scatter', marker='circle', marker_size=6, color='blue', outline_color='blue') plot.plot(('sel_lon', 'sel_lat'), type='scatter', marker='circle', marker_size=10, color='transparent', outline_color='black') zoom = ZoomTool(component=plot) pan = PanTool(component=plot) plot.tools += [zoom, pan] plot.padding=[40,10,0,0] return plot @cached_property def _get_positions(self): return numpy.vstack((self.latitudes, self.longitudes)).T @cached_property def _get_data_bounds(self): min_lat = self.latitudes.min() max_lat = self.latitudes.max() min_lon = self.longitudes.min() max_lon = self.longitudes.max() # lower left and upper right return min_lat, min_lon, max_lat, max_lon @cached_property def _get_map_image(self): map_filename = os.path.join(os.path.dirname(__file__), 'osm_map.png') if os.path.exists(map_filename): img_data = ImageData.fromfile(map_filename) img_data._data = img_data._data[::-1] return img_data min_lat, min_lon, max_lat, max_lon = self.data_bounds padding = (max_lat-min_lat)*self.map_padding, (max_lon-min_lon)*self.map_padding min_lat -= padding[0] max_lat += padding[0] min_lon -= padding[1] max_lon += padding[1] link = 'http://tile.openstreetmap.org/cgi-bin/export?bbox=' link += '%f,%f,%f,%f' % (min_lon, min_lat, max_lon, max_lat) link += '&scale=3500&format=png' print link urllib.urlretrieve(link, map_filename) img_data = ImageData.fromfile(map_filename) img_data._data = img_data._data[::-1] return img_data def _lat_lon_to_screen(self, lat, lon): height, width, depth = self.map_image._data.shape lon_scale = width/((max(self.longitudes)-min(self.longitudes))*(1+2*self.map_padding)) lat_scale = height/((max(self.latitudes)-min(self.latitudes))*(1+2*self.map_padding)) min_lat, min_lon, max_lat, max_lon = self.data_bounds padding = (max_lat-min_lat)*self.map_padding, (max_lon-min_lon)*self.map_padding lon = (lon - min(self.longitudes) + padding[1])*lon_scale lat = (lat - min(self.latitudes) + padding[0])*lat_scale return lat, lon @on_trait_change('speed_plot.datasources.metadata, alt_plot.datasources.metadata') def _update_scatter(self, obj, name, event): if 'selections' in obj.metadata: # set the selected map point if the object which changed is one of the # index ranges (not the value ranges) if obj in [comp.index for comp in self.speed_plot.components + self.alt_plot.components]: d = obj.metadata['selections'] # the index is sorted, so find the point before indices = numpy.where(obj._data < d)[0 ] if len(indices) == 0: index = 0 else: index = indices[-1] if index >= (len(obj._data) - 1): lat, lon = self._lat_lon_to_screen(numpy.array([self.latitudes[-1]]), numpy.array([self.longitudes[-1]])) else: d1 = d - obj._data[index] d2 = obj._data[index + 1] - d if d2 < d1: index += 1 lat, lon = self._lat_lon_to_screen(numpy.array([self.latitudes[index]]), numpy.array([self.longitudes[index]])) self.map_plot.data['sel_lat'] = lat self.map_plot.data['sel_lon'] = lon else: # clear the selected map point self.map_plot.data['sel_lat'] = numpy.array([]) self.map_plot.data['sel_lon'] = numpy.array([]) self.map_plot.request_redraw() def get_route(): headers = {'Accept' : 'application/json'} req = urllib2.Request('http://bikko.net/route/572', headers=headers) response = urllib2.urlopen(req) json_obj = json.loads(response.read()) return Route(latitudes=json_obj['latitudes'], longitudes=json_obj['longitudes'], distances=json_obj['distances'], speeds=json_obj['speed'], altitudes=json_obj['altitudes'], center=json_obj['center'], zoom=json_obj['zoom'], map_type='gmap') route = get_route() route.configure_traits()
83 views




