with open('apps/server_app.py', 'r') as f: print(f.read()) # Exercise: Modify the app to display the pickup locations and add a tilesource, then run the app with bokeh serve # Tip: Refer to the previous notebook import holoviews as hv, geoviews as gv, param, dask.dataframe as dd, panel as pn from colorcet import cm from bokeh.document import Document from holoviews.operation.datashader import rasterize, shade from holoviews.streams import RangeXY from cartopy import crs hv.extension('bokeh', logo=False) usecols = ['dropoff_x', 'dropoff_y', 'pickup_x', 'pickup_y', 'dropoff_hour'] df = dd.read_parquet('../data/nyc_taxi_wide.parq') df = df[usecols].persist() cmaps = ['fire','bgy','bgyw','bmy','gray','kbc'] topts = dict(width=600,height=400,xaxis=None,yaxis=None,bgcolor='black',show_grid=False) class NYCTaxi(param.Parameterized): alpha = param.Magnitude(default=0.75, doc="Map tile opacity") cmap = param.ObjectSelector(cm['fire'], objects={c:cm[c] for c in cmaps}) location = param.ObjectSelector(default='dropoff', objects=['dropoff', 'pickup']) @param.depends('alpha') def tiles(self): return gv.tile_sources.EsriImagery.options(alpha=self.alpha, **topts) @param.depends('location') def view(self): points = hv.Points(df, kdims=[self.location+'_x', self.location+'_y']) points = hv.DynamicMap(points) raster = rasterize(points, x_sampling=1, y_sampling=1, width=700, height=400) tiles = hv.DynamicMap(self.tiles) return tiles * shade(raster, streams=[hv.streams.Params(self, ['cmap'])]) explorer = NYCTaxi(name="More responsive trip explorer") panel = pn.Row(explorer, explorer.view) panel panel.server_doc(); # Exercise: Note the differences between the server app and the app defined above # then add an additional parameter and plot # Exercise: Click the link below and edit the Jinja2 template to customize the app # Advanced Exercise: Add a histogram to the bokeh layout next to the datashaded plot # Hint: Declare the histogram like this: hv.operation.histogram(aggregated, bin_range=(0, 20)) # then use renderer.get_plot and hist_plot.state and add it to the layout