diff --git a/notebooks/Dashboard_Demo.ipynb b/notebooks/Dashboard_Demo.ipynb index eb57352..ccba70b 100644 --- a/notebooks/Dashboard_Demo.ipynb +++ b/notebooks/Dashboard_Demo.ipynb @@ -18,8 +18,7 @@ "import numpy as np\n", "import holoviews as hv\n", "import holocube as hc\n", - "from matplotlib.cm import cmap_d\n", - "from cartopy import crs as ccrs\n", + "\n", "from cartopy import feature as cf\n", "from paramnb import NbParams, FileSelector\n", "\n", @@ -30,7 +29,13 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "urth": { + "dashboard": { + "hidden": true + } + } + }, "source": [ "Declaring a set of widgets using paramNB is as simply as declaring a Parameterized class. Here we declare a ``CubeLoader`` class with a ``FileSelector`` parameter, a cache and a load method, which will load cubes from a file on disk. The ``NbParams`` function accepts the ``CubeLoader`` instance and generates a dropdown widget for the ``cube_path`` from it. By declaring a callback we can tell it to load the file from disk (or the cache) whenever the user executes the widget. Finally we can declare the ``execute`` mode, which allows declaring no execution with ``execute=None`` or adds a button to execute the 'next' cell or all cells 'below'." ] @@ -56,26 +61,24 @@ "class CubeLoader(param.Parameterized):\n", " \n", " cube_path = FileSelector(default='files/*.pp')\n", + "\n", + " cache = {}\n", + " cubes = None\n", " \n", - " def __init__(self, **params):\n", - " super(CubeLoader, self).__init__(**params)\n", - " self.cache = {}\n", - " self.cubes = None\n", - " \n", - " def load(self, cube_loader):\n", - " if self.cube_path not in self.cache:\n", - " cubelist = iris.load(self.cube_path)\n", + " @classmethod\n", + " def load(cls, cube_loader):\n", + " if cls.cube_path not in cls.cache:\n", + " cubelist = iris.load(cls.cube_path)\n", " for c in cubelist:\n", " c.coord('grid_longitude').guess_bounds()\n", " c.coord('grid_latitude').guess_bounds()\n", - " self.cache[self.cube_path] = cubelist\n", + " cls.cache[cls.cube_path] = cubelist\n", " else:\n", - " cubelist = self.cache[self.cube_path]\n", + " cubelist = cls.cache[cls.cube_path]\n", " cubes = {cb.vdims[0].name:cb for cb in [hc.HoloCube(c) for c in cubelist]} # Load cubes into dictionary\n", - " self.cubes = {k:v for k,v in cubes.items() if k!='unknown'} # Filter as desired\n", + " cls.cubes = {k:v for k,v in cubes.items() if k!='unknown'} # Filter as desired\n", "\n", - "cube_loader = CubeLoader()\n", - "NbParams(cube_loader, execute='next', callback=cube_loader.load)" + "NbParams(CubeLoader, execute='next', callback=CubeLoader.load)" ] }, { @@ -96,28 +99,49 @@ }, "outputs": [], "source": [ - "# Next we declare a more complex ``CubeBrowser`` class, which will define the various options on what to display and how to display it.\n", - "# We add parameters to control the cmap, quantity, element and projection and populate these with useful options.\n", - "\n", - "def all_subclasses(cls):\n", - " return cls.__subclasses__() + [g for s in cls.__subclasses__()\n", - " for g in all_subclasses(s)]\n", + "from cartopy import crs as ccrs\n", + "from matplotlib.cm import cmap_d\n", "\n", - "projections = {crs.__name__: crs for crs in all_subclasses(ccrs.CRS)\n", - " if hasattr(crs, '_as_mpl_axes') and not crs.__name__[0] == '_'}\n", + "projections = {k: crs for k, crs in param.concrete_descendents(ccrs.CRS).items()\n", + " if hasattr(crs, '_as_mpl_axes') and not k[0] == '_'}\n", "\n", "class CubeBrowser(param.Parameterized):\n", + " \"\"\"\n", + " CubeBrowser defines a small example GUI to demonstrate\n", + " how to define a small set of widgets to control plotting\n", + " of an iris Cube. It exposes control over the colormap,\n", + " the quantity to be plotted, the element to plot it with\n", + " and the projection to plot it on.\n", + " \"\"\"\n", "\n", - " cmap = param.ObjectSelector(default='viridis', objects=list(cmap_d.keys()))\n", + " cmap = param.ObjectSelector(default='viridis',\n", + " objects=list(cmap_d.keys()))\n", "\n", - " quantity = param.ObjectSelector(default=cube_loader.cubes.keys()[0], objects=list(cube_loader.cubes.keys()))\n", + " quantity = param.ObjectSelector(default=CubeLoader.cubes.keys()[0],\n", + " objects=list(CubeLoader.cubes.keys()))\n", "\n", - " element = param.ObjectSelector(default=hc.Image, objects=[hc.Image, hc.Contours])\n", + " element = param.ObjectSelector(default=hc.Image,\n", + " objects=[hc.Image, hc.Contours])\n", "\n", - " projection = param.ObjectSelector(default='PlateCarree', objects=list(projections.keys()))\n", + " projection = param.ObjectSelector(default='default',\n", + " objects=['default']+sorted(projections.keys()))\n", " \n", " cache = {}\n", "\n", + " @classmethod\n", + " def view(cls):\n", + " key = (cls.quantity, cls.element)\n", + " if key in CubeBrowser.cache:\n", + " converted = cls.cache[key]\n", + " else:\n", + " holocube = CubeLoader.cubes[cls.quantity]\n", + " converted = holocube.to(cls.element, ['grid_longitude', 'grid_latitude'], dynamic=True)\n", + " cls.cache[key] = converted\n", + " styled = converted(style={cls.element.name: dict(cmap=cls.cmap)})\n", + " projection = projections[cls.projection]() if cls.projection != 'default' else None\n", + " projected = styled({'Image': dict(plot=dict(projection=projection))}) if projection else styled\n", + " return (projected * hc.GeoFeature(cf.COASTLINE)(plot=dict(scale='50m')))\n", + "\n", "NbParams(CubeBrowser, execute='next')" ] }, @@ -130,9 +154,9 @@ "dashboard": { "layout": { "col": 0, - "height": 33, + "height": 36, "row": 7, - "width": 11 + "width": 12 } } } @@ -141,21 +165,128 @@ "source": [ "# Finally we can declare a cell which uses the settings defined via the widgets to render the requested plot.\n", "# We simply look up the correct cube, convert it to the desired Element type and then display it with the requested options.\n", - "\n", - "key = (CubeBrowser.quantity, CubeBrowser.element)\n", - "if key in CubeBrowser.cache:\n", - " converted = CubeBrowser.cache[key]\n", - "else:\n", - " holocube = cube_loader.cubes[cube_browser.quantity]\n", - " converted = holocube.to(cube_browser.element, ['grid_longitude', 'grid_latitude'], dynamic=True)\n", - " CubeBrowser.cache[key] = converted\n", - "styled = converted(style={cube_browser.element.name: dict(cmap=cube_browser.cmap)})\n", - "projection = projections[cube_browser.projection]()\n", - "(styled * hc.GeoFeature(cf.COASTLINE)(plot=dict(scale='50m'))(plot=dict(projection=projection)))" + "CubeBrowser.view()" ] } ], "metadata": { + "environment": { + "dependencies": [ + "appnope=0.1.0=py27_0", + "backports=1.0=py27_0", + "backports_abc=0.4=py27_0", + "biggus=0.13.0=py27_0", + "cartopy=0.13.1=np110py27_0", + "cf_units=1.1=py27_0", + "configparser=3.5.0b2=py27_1", + "curl=7.45.0=0", + "cycler=0.10.0=py27_0", + "cython=0.24=py27_0", + "decorator=4.0.9=py27_0", + "ecmwf_grib=1.14.2=np110py27_0", + "entrypoints=0.2=py27_1", + "freetype=2.5.5=0", + "funcsigs=1.0.0=py27_0", + "geos=3.4.2=4", + "hdf5=1.8.15.1=2", + "ipykernel=4.3.1=py27_0", + "ipython=4.1.2=py27_2", + "ipython_genutils=0.1.0=py27_0", + "ipywidgets=4.1.1=py27_0", + "iris=1.9.2=np110_0", + "jasper=1.900.1=5", + "jbig=2.1=0", + "jinja2=2.8=py27_0", + "jpeg=8d=1", + "jsonschema=2.4.0=py27_0", + "jupyter=1.0.0=py27_2", + "jupyter_client=4.2.2=py27_0", + "jupyter_console=4.1.1=py27_0", + "jupyter_core=4.1.0=py27_0", + "libmo_unpack=3.0=3", + "libnetcdf=4.3.3.1=3", + "libpng=1.6.17=0", + "libtiff=4.0.6=1", + "libxml2=2.9.2=0", + "libxslt=1.1.28=2", + "lxml=3.6.0=py27_0", + "markupsafe=0.23=py27_0", + "matplotlib=1.5.1=np110py27_0", + "mistune=0.7.2=py27_1", + "mkl=11.3.1=0", + "mo_pack=0.2.0=np110py27_1", + "mock=2.0.0=py27_0", + "nbconvert=4.2.0=py27_0", + "nbformat=4.0.1=py27_0", + "netcdf4=1.2.2=np110py27_0", + "nose=1.3.7=py27_0", + "notebook=4.1.0=py27_2", + "numpy=1.10.4=py27_0", + "openssl=1.0.2g=0", + "owslib=0.10.3=py27_0", + "pandas=0.18.0=np111py27_0", + "path.py=8.2=py27_0", + "pbr=1.8.0=py27_0", + "pexpect=4.0.1=py27_0", + "pickleshare=0.5=py27_0", + "pillow=3.2.0=py27_0", + "pip=8.1.1=py27_1", + "proj.4=4.9.1=1", + "ptyprocess=0.5=py27_0", + "pyepsg=0.2.0=py27_0", + "pygments=2.1.3=py27_0", + "pyke=1.1.1=py27_2", + "pyparsing=2.0.3=py27_0", + "pyproj=1.9.4=py27_1", + "pyqt=4.11.4=py27_1", + "pyshp=1.2.3=py27_0", + "python=2.7.11=0", + "python-dateutil=2.5.2=py27_0", + "pytz=2016.3=py27_0", + "pyzmq=15.2.0=py27_0", + "qt=4.8.7=1", + "qtconsole=4.2.1=py27_0", + "readline=6.2=2", + "requests=2.9.1=py27_0", + "scipy=0.17.0=np110py27_0", + "setuptools=20.6.7=py27_0", + "shapely=1.5.13=np110py27_1", + "simplegeneric=0.8.1=py27_0", + "singledispatch=3.4.0.3=py27_0", + "sip=4.16.9=py27_0", + "six=1.10.0=py27_0", + "sqlite=3.9.2=0", + "ssl_match_hostname=3.4.0.2=py27_1", + "terminado=0.5=py27_1", + "tk=8.5.18=0", + "tornado=4.3=py27_0", + "traitlets=4.2.1=py27_0", + "udunits2=2.2.20=0", + "wheel=0.29.0=py27_0", + "xz=5.0.5=1", + "zlib=1.2.8=0", + { + "pip": [ + "backports-abc==0.4", + "backports.ssl-match-hostname==3.4.0.2", + "cartopy (/Users/philippjfr/cartopy/lib)==0.14.0", + "cf-units==1.1", + "holocube (/Users/philippjfr/cube-explorer)==0.0.1", + "holoviews==1.4.3", + "ipython-genutils==0.1.0", + "iris (/Users/philippjfr/iris/lib)==1.10.0.dev0", + "jupyter-client==4.2.2", + "jupyter-console==4.1.1", + "jupyter-core==4.1.0", + "lancet-ioam==0.9.0", + "mo-pack==0.2.0", + "param==1.3.2", + "paramnb (/Users/philippjfr/paramnb)==0.0.1" + ] + } + ], + "name": "metoffice" + }, "hide_input": false, "kernelspec": { "display_name": "Python 2",