From 2deff19b5c8b04deb896d9bfc1cd5a3facc11c4b Mon Sep 17 00:00:00 2001 From: "James A. Bednar" Date: Fri, 12 Oct 2018 17:59:46 -0500 Subject: [PATCH] Updated instructions (#122) * Updated installation instructions * Player fixes from lancelot1969 * Restored apps from prior to #81 * Updated pins --- doc/installation.rst | 4 +- examples/tutorial/00_Setup.ipynb | 8 +-- .../tutorial/01_Workflow_Introduction.ipynb | 14 ++--- examples/tutorial/apps/nyc_taxi/main.py | 56 ++++++++++--------- examples/tutorial/apps/osm-1billion.py | 43 +++++++------- examples/tutorial/apps/taxi_player/main.py | 8 +-- setup.cfg | 4 +- 7 files changed, 67 insertions(+), 70 deletions(-) diff --git a/doc/installation.rst b/doc/installation.rst index 807444b4..e9b6a0cd 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -46,10 +46,10 @@ Step 4: Launch Jupyter Notebook You can then launch the notebook server and client:: - > cd pyviz-examples/tutorial + > cd pyviz-examples > jupyter notebook -A browser window with a Jupyter Notebook instance should now open, letting you select and execute each notebook. You can start with the ones in the "notebooks" subdirectory, as these show how to use the others in the "exercises" directory along with the applications in the "apps" directory. The first notebook to load is the index page ``index.ipynb``, which makes it simple to load each of the others. +A browser window with a Jupyter Notebook instance should now open, letting you select and execute each notebook. You can start with the ones in the "tutorial" subdirectory, which will point you to various "exercises" directory along with the applications in the "apps" directory. The first notebook to load is the index page ``index.ipynb`` in ``tutorial/``, which makes it simple to load each of the others. If you don't see the notebook appear (e.g. on some OS X versions), you may need to cut and paste the URL from the console output manually. diff --git a/examples/tutorial/00_Setup.ipynb b/examples/tutorial/00_Setup.ipynb index 612bf137..6f74db4c 100644 --- a/examples/tutorial/00_Setup.ipynb +++ b/examples/tutorial/00_Setup.ipynb @@ -30,10 +30,10 @@ "metadata": {}, "source": [ "```\n", - "! conda install -c pyviz/label/dev pyviz\n", - "! pyviz examples\n", - "! cd pyviz-examples/tutorial\n", - "! jupyter notebook\n", + "conda install -c pyviz/label/dev pyviz\n", + "pyviz examples\n", + "cd pyviz-examples\n", + "jupyter notebook\n", "```" ] }, diff --git a/examples/tutorial/01_Workflow_Introduction.ipynb b/examples/tutorial/01_Workflow_Introduction.ipynb index 987dae59..3e026ed5 100644 --- a/examples/tutorial/01_Workflow_Introduction.ipynb +++ b/examples/tutorial/01_Workflow_Introduction.ipynb @@ -552,14 +552,12 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, - "outputs": [], "source": [ "%%output backend='matplotlib'\n", "by_state * hv.VLine(1963).options(color=\"black\") * \\\n", @@ -699,7 +697,7 @@ "source": [ "As you can see, you can specify geo plots easily with GeoViews, and if your HoloViews objects are too big to visualize in a browser directly, you can add `datashade()` to render them into images dynamically on zooming, etc.\n", "\n", - "You can also easily add widgets to control filtering, selection, and other options interactively, either here in the notebook or by putting the same code (plus `panel.server_doc();`) in a separate file and running it as a standalone server:" + "You can also easily add widgets to control filtering, selection, and other options interactively, either here in the notebook, or in a standalone server by marking the servable objects with `.servable()` then running the .ipynb file through Bokeh Server or extracting the code to a separate .py file and doing the same thing:" ] }, { @@ -712,7 +710,7 @@ }, "outputs": [], "source": [ - "import param, panel as pp\n", + "import param, panel as pn\n", "from colorcet import palette\n", "\n", "class NYCTaxi(param.Parameterized):\n", @@ -726,14 +724,14 @@ " return tiles.options(alpha=self.alpha) * trips\n", "\n", "explorer = NYCTaxi(name=\"Taxi explorer\")\n", - "pp.Row(explorer, explorer.make_view)" + "pn.Row(explorer, explorer.make_view).servable()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Note that in this simple app, the method `make_view` is called whenever *any* of the parameters change (alpha, colormap, or location), but you can get a more responsive interface if you take the time to clare which computations depend on which parameters (see the [Deploying Bokeh Apps tutorial](./13_Deploying_Bokeh_Apps.ipynb)).\n", + "Note that in this simple app, the method `make_view` is called whenever *any* of the parameters change (alpha, colormap, or location), but you can get a more responsive interface if you take the time to declare which computations depend on which parameters (see the [Deploying Bokeh Apps tutorial](./13_Deploying_Bokeh_Apps.ipynb)).\n", "\n", "As you can see, the PyViz tools let you integrate visualization into everything you do, using a small amount of code that reveals your data's properties and captures your understanding of it. The rest of these tutorials will break down each of the topics covered above, showing you step by step how to work with your own data using these tools.\n", "\n", @@ -758,7 +756,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.6" } }, "nbformat": 4, diff --git a/examples/tutorial/apps/nyc_taxi/main.py b/examples/tutorial/apps/nyc_taxi/main.py index 186df9b9..fbb74b65 100644 --- a/examples/tutorial/apps/nyc_taxi/main.py +++ b/examples/tutorial/apps/nyc_taxi/main.py @@ -1,38 +1,40 @@ -import os -import holoviews as hv, geoviews as gv, param, parambokeh, dask.dataframe as dd, cartopy.crs as crs +import holoviews as hv, geoviews as gv, param, dask.dataframe as dd, cartopy.crs as crs +import panel as pn -from colorcet import cm_n -from holoviews.operation.datashader import datashade +from colorcet import cm +from holoviews.operation.datashader import rasterize, shade from holoviews.streams import RangeXY hv.extension('bokeh', logo=False) usecols = ['dropoff_x','dropoff_y','pickup_x','pickup_y','dropoff_hour','pickup_hour','passenger_count'] -df = dd.read_parquet(os.path.join(os.path.dirname(__file__),'..','..','..','data','nyc_taxi_wide.parq'))[usecols].persist() - -url='https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{Z}/{Y}/{X}.jpg' -tiles = gv.WMTS(url,crs=crs.GOOGLE_MERCATOR) +df = dd.read_parquet('../../data/nyc_taxi_wide.parq')[usecols].persist() opts = dict(width=1000,height=600,xaxis=None,yaxis=None,bgcolor='black',show_grid=False) -max_pass = int(df.passenger_count.max().compute()+1) +cmaps = ['fire','bgy','bgyw','bmy','gray','kbc'] + -class NYCTaxiExplorer(hv.streams.Stream): +class NYCTaxiExplorer(param.Parameterized): alpha = param.Magnitude(default=0.75, doc="Alpha value for the map opacity") - colormap = param.ObjectSelector(default=cm_n["fire"], objects=cm_n.values()) - hour = param.Integer(default=None, bounds=(0, 23), doc="All hours by default; drag to select one hour") - passengers = param.Range(default=(0,max_pass), bounds=(0,max_pass)) + cmap = param.ObjectSelector(cm['fire'], objects={c:cm[c] for c in cmaps}) + hour = param.Range(default=(0, 24), bounds=(0, 24)) location = param.ObjectSelector(default='dropoff', objects=['dropoff', 'pickup']) - def make_view(self, x_range, y_range, **kwargs): - map_tiles = tiles.options(alpha=self.alpha, **opts) - points = hv.Points(df, [self.location+'_x', self.location+'_y'], self.location+'_hour') - selection = {self.location+"_hour":self.hour if self.hour else (0,24), "passenger_count":self.passengers} - taxi_trips = datashade(points.select(**selection), x_sampling=1, y_sampling=1, cmap=self.colormap, - dynamic=False, x_range=x_range, y_range=y_range, width=1000, height=600) - return map_tiles * taxi_trips - -explorer = NYCTaxiExplorer(name="NYC Taxi Trips") -dmap = hv.DynamicMap(explorer.make_view, streams=[explorer, RangeXY()]) - -plot = hv.renderer('bokeh').instance(mode='server').get_plot(dmap) -parambokeh.Widgets(explorer, view_position='right', callback=explorer.event, plots=[plot.state], - mode='server') + @param.depends('location', 'hour') + def points(self): + points = hv.Points(df, kdims=[self.location+'_x', self.location+'_y'], vdims=['dropoff_hour']) + if self.hour != (0, 24): points = points.select(dropoff_hour=self.hour) + return points + + @param.depends('alpha') + def tiles(self): + return gv.tile_sources.StamenTerrain.options(alpha=self.alpha, **opts) + + def view(self,**kwargs): + points = hv.DynamicMap(self.points) + agg = rasterize(points, x_sampling=1, y_sampling=1, width=600, height=400) + stream = hv.streams.Params(self, ['cmap']) + tiles = hv.DynamicMap(self.tiles) + return tiles * shade(agg, streams=[stream]) + +taxi = NYCTaxiExplorer(name="NYC Taxi Trips") +pn.Row(taxi, taxi.view()).servable() diff --git a/examples/tutorial/apps/osm-1billion.py b/examples/tutorial/apps/osm-1billion.py index 11e07f09..55671274 100644 --- a/examples/tutorial/apps/osm-1billion.py +++ b/examples/tutorial/apps/osm-1billion.py @@ -1,31 +1,28 @@ -import os -import holoviews as hv, geoviews as gv, param, parambokeh, dask.dataframe as dd, cartopy.crs as crs - -from holoviews.operation.datashader import datashade +import holoviews as hv, geoviews as gv, param, dask.dataframe as dd, panel as pn +from holoviews.operation.datashader import datashade, rasterize, shade from holoviews.streams import RangeXY -from colorcet import cm_n +from colorcet import cm hv.extension('bokeh', logo=False) -df = dd.read_parquet(os.path.join(os.path.dirname(__file__),'..','..','data','osm-1billion.snappy.parq')).persist() - -url='https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{Z}/{Y}/{X}.jpg' -map_tiles = gv.WMTS(url,crs=crs.GOOGLE_MERCATOR) - -opts1 = dict(width=1000, height=600, xaxis=None, yaxis=None, bgcolor='black', show_grid=False) -opts2 = dict(width=1000, height=600, x_sampling=1, y_sampling=1, dynamic=False) +df = dd.read_parquet('../../data/osm-1billion.snappy.parq').persist() -class OSMExplorer(hv.streams.Stream): - alpha = param.Magnitude(default=0.75, doc="Map opacity") - colormap = param.ObjectSelector(default=cm_n["fire"], objects=cm_n.values()) +cmaps = ['fire','bgy','bgyw','bmy','gray','kbc'] +topts = dict(width=900,height=600,xaxis=None,yaxis=None,bgcolor='black',show_grid=False) - def make_view(self, x_range, y_range, **kwargs): - tiles = map_tiles.options(alpha=self.alpha, **opts1) - points = hv.Points(df, ['x','y']) - return tiles * datashade(points, cmap=self.colormap, x_range=x_range, y_range=y_range, **opts2) +class OSM(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}) + + @param.depends('alpha') + def tiles(self): + return gv.tile_sources.EsriImagery.options(alpha=self.alpha, **topts) -explorer = OSMExplorer(name="Open Street Map GPS") -dmap = hv.DynamicMap(explorer.make_view, streams=[explorer, RangeXY()]) + @param.depends() + def view(self): + points = hv.DynamicMap(hv.Points(df, kdims=['x', 'y'])) + raster = rasterize(points, x_sampling=1, y_sampling=1, width=900, height=600) + return hv.DynamicMap(self.tiles) * shade(raster, streams=[hv.streams.Params(self, ['cmap'])]) -plot = hv.renderer('bokeh').instance(mode='server').get_plot(dmap) -parambokeh.Widgets(explorer, view_position='right', callback=explorer.event, plots=[plot.state], mode='server') +osm = OSM(name="Open Street Map GPS") +pn.Row(osm, osm.view).servable() diff --git a/examples/tutorial/apps/taxi_player/main.py b/examples/tutorial/apps/taxi_player/main.py index 96e60bbc..3fc16e3a 100644 --- a/examples/tutorial/apps/taxi_player/main.py +++ b/examples/tutorial/apps/taxi_player/main.py @@ -74,14 +74,14 @@ def animate_update(): slider.value = year def animate(): - if button.label == '► Play': - button.label = '❚❚ Pause' + if button.label == '\u25B6 Play': + button.label = '\u23F8 Pause' curdoc().add_periodic_callback(animate_update, 500) else: - button.label = '► Play' + button.label = '\u25B6 Play' curdoc().remove_periodic_callback(animate_update) -button = Button(label='► Play', width=60) +button = Button(label='\u25B6 Play', width=60) button.on_click(animate) widget = parambokeh.Widgets(cmap_picker, mode='raw') diff --git a/setup.cfg b/setup.cfg index cc211b91..389e9896 100644 --- a/setup.cfg +++ b/setup.cfg @@ -36,7 +36,7 @@ install_requires = geoviews >=1.5.4a13 hvplot >=0.2.1 datashader >=0.6.8 - panel >=0.1.0 + panel >=0.1.2 param >=1.8.1 paramnb >=2.0.4 parambokeh >=0.2.3 @@ -110,7 +110,7 @@ pins = hvplot = 0.2.1 geoviews = 1.5.4a13 datashader = 0.6.8 - panel = 0.1.0 + panel = 0.1.2 param = 1.8.1 paramnb = 2.0.4 parambokeh = 0.2.3