diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..0d1e249835 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.vscode/settings.json +.vscode/panel.code-workspace +__pycache__/dodo.cpython-37.pyc +__pycache__/setup.cpython-37.pyc +0.5.0 +panel/.version +.doit.db +.mypy_cache/ diff --git a/examples/reference/other/Param.ipynb b/examples/reference/other/Param.ipynb new file mode 100644 index 0000000000..38184c2c5d --- /dev/null +++ b/examples/reference/other/Param.ipynb @@ -0,0 +1,332 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import panel as pn\n", + "import param\n", + "\n", + "pn.extension()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The ``panel.Param`` pane allows customizing the widgets, layout and style of the parameters of a `param.Parametrized` Class.\n", + "\n", + "#### Parameters:\n", + "\n", + "The basic parameters are\n", + "\n", + "* **`object`** (param.parameterized.Parameters): The `param` attribute of a `param.Parameterized` Class\n", + "* **`parameters`** (None or List[str]): A list identifying the subset of parameters to include in the Pane.\n", + "* **`widgets`** (Dict): A Dictionary specifying which parameters and widgets to use for a given parameter. You can also specify widget attributes.\n", + "\n", + "The more advanced parameters give you more control and they are\n", + " \n", + "* **`default_layout`** (ClassSelector) A layout like Column, Row etc or a Custom GridBox.\n", + "* **`expand`** (bool) Whether or not to expand\n", + "* **`expand_button`** (None or Button) The expand button\n", + "* **`expand_layout`** (ClassSelector) A layout like Column, Row etc. or a Custom GridBox.\n", + "* **`show_labels`** (bool) Whether or not to show labels\n", + "* **`show_name`** (bool) Whether or not to show the name of the Parameterized Class \n", + "\n", + "For more layout and styling related parameters see the [customization user guide](../../user_guide/Customization.ipynb).\n", + "\n", + "For an alternative example of using `panel.Param` see the [parameters user guide](../../user_guide/Param.ipynb).\n", + "\n", + "___" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lets build a model of a cycling Athlete and his PowerCurve. \n", + "\n", + "The PowerCurve is a recording of his maximum power output in Watt per kg for fixed durations of time." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import datetime\n", + "import pandas as pd\n", + "import hvplot.pandas\n", + "\n", + "DATE_BOUNDS = (datetime.date(1900, 1, 1), datetime.datetime.now().date())\n", + "\n", + "class PowerCurve(param.Parameterized):\n", + " ten_sec = param.Number(1079)\n", + " ten_sec_date = param.Date(datetime.date(2018, 8, 21), bounds=DATE_BOUNDS)\n", + " one_min = param.Number(684)\n", + " one_min_date = param.Date(datetime.date(2017, 8, 31), bounds=DATE_BOUNDS)\n", + " ten_min = param.Number(419)\n", + " ten_min_date = param.Date(datetime.date(2017, 9, 22), bounds=DATE_BOUNDS)\n", + " twenty_min = param.Number(398)\n", + " twenty_min_date = param.Date(datetime.date(2017, 9, 22), bounds=DATE_BOUNDS)\n", + " one_hour = param.Number(319)\n", + " one_hour_date = param.Date(datetime.date(2017, 8, 6), bounds=DATE_BOUNDS)\n", + " \n", + " @param.depends(\"ten_sec\", \"one_min\", \"ten_min\", \"twenty_min\", \"one_hour\")\n", + " def plot(self):\n", + " data = {\n", + " \"duration\": [10 / 60, 1, 10, 20, 60],\n", + " \"power\": [self.ten_sec, self.one_min, self.ten_min, self.twenty_min, self.one_hour],\n", + " }\n", + " dataframe = pd.DataFrame(data)\n", + " line_plot = dataframe.hvplot.line(\n", + " x=\"duration\", y=\"power\", width=300, line_color=\"#007BFF\", line_width=3,\n", + " )\n", + " scatter_plot = dataframe.hvplot.scatter(x=\"duration\", y=\"power\", width=300).opts(\n", + " marker=\"o\", size=6, color=\"#007BFF\"\n", + " )\n", + " fig = line_plot * scatter_plot\n", + " gridstyle = {\"grid_line_color\": \"black\", \"grid_line_width\": 0.1}\n", + " fig = fig.opts(\n", + " responsive=True,\n", + " toolbar=None,\n", + " yticks=list(range(0, 1600, 200)),\n", + " ylim=(0, 1500),\n", + " gridstyle=gridstyle,\n", + " show_grid=True,\n", + " )\n", + " return fig\n", + " \n", + " \n", + "\n", + "class Athlete(param.Parameterized):\n", + " name_ = param.String(\"P.A. Nelson\")\n", + " birthday = param.Date(datetime.date(1976, 9, 17), bounds=DATE_BOUNDS)\n", + " weight = param.Number(default=82, bounds=(20,300))\n", + " power_curve = param.ClassSelector(class_=PowerCurve, default=PowerCurve())\n", + " \n", + "athlete = Athlete()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `pn.Param` can be used to view and edit the models.\n", + "\n", + "Try clicking the `...` button. This will expand the PowerCurve if running in an interactive notebook." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.Param(athlete)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The default Name and Birthday widgets are slow to use. So lets change them to a DatePicker and a LiteralInput for ints." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.Param(athlete, widgets={\"birthday\": pn.widgets.DatePicker, \"weight\": pn.widgets.LiteralInput})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lets expand the power curve by default." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.Param(\n", + " athlete, \n", + " widgets={\n", + " \"birthday\": pn.widgets.DatePicker, \n", + " \"weight\": pn.widgets.LiteralInput\n", + " }, expand=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now lets try to display the Name and Birthday only and in a Row." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.Param(\n", + " athlete,\n", + " widgets={\"birthday\": pn.widgets.DatePicker},\n", + " parameters=[\"name_\", \"birthday\"],\n", + " show_name=False,\n", + " default_layout=pn.Row,\n", + " width=400\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lets customize the view of the Athlete some more" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "athlete_view = pn.Param(\n", + " athlete,\n", + " widgets={\n", + " \"birthday\": pn.widgets.DatePicker, \n", + " \"weight\": {\"type\": pn.widgets.LiteralInput, \"width\": 100}\n", + " },\n", + " parameters=[\"name_\", \"birthday\", \"weight\"],\n", + " show_name=False,\n", + " default_layout=pn.Row,\n", + " width=600\n", + ")\n", + "athlete_view" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lets take a look at the PowerCurve" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.Param(athlete.power_curve)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The PowerCurve layout is not that tidy. Lets change the layout to two columns." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class GridBoxWithTwoColumns(pn.GridBox):\n", + " def __init__(self, *objects, **params):\n", + " super().__init__(*objects, **params, ncols=2)\n", + " \n", + "power_curve_columns_view = pn.Param(\n", + " athlete.power_curve, \n", + " default_layout=GridBoxWithTwoColumns, \n", + " show_name=False,\n", + " widgets = {\n", + " \"ten_sec_date\": pn.widgets.DatePicker, \n", + " \"one_min_date\": pn.widgets.DatePicker, \n", + " \"ten_min_date\": pn.widgets.DatePicker, \n", + " \"twenty_min_date\": pn.widgets.DatePicker, \n", + " \"one_hour_date\": pn.widgets.DatePicker, \n", + " }\n", + ")\n", + "power_curve_columns_view\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lets put a plot of the PowerCurve in the mix" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "power_curve_view = pn.Row(\n", + " power_curve_columns_view,\n", + " pn.layout.VSpacer(width=50),\n", + " athlete.power_curve.plot,\n", + ")\n", + "power_curve_view" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And finally. Lets put the things together" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pn.Column(\n", + " pn.pane.Markdown(\"### Athlete\"), \n", + " athlete_view, \n", + " pn.pane.Markdown(\"#### Power Curve\"), \n", + " power_curve_view,\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/panel/pane/pydeck.py b/panel/pane/pydeck.py new file mode 100644 index 0000000000..98299e7263 --- /dev/null +++ b/panel/pane/pydeck.py @@ -0,0 +1,29 @@ +""" +Defines a PyDeck Pane which renders a PyDeck plot using a PyDeckPlot +bokeh model. + +For now I've just experimented a bit. + +There is a simple implementation of an app using PyDeck in the gallery at +[awesome-streamlit.org](https://awesome-streamlit.org). + +See + +- [pydeck implementation](https://github.com/MarcSkovMadsen/awesome-panel/blob/master/package/awesome_panel/express/pane/pydeck.py) +- [test_pydeck app](https://github.com/MarcSkovMadsen/awesome-panel/blob/master/src/pages/gallery/awesome_panel_express_tests/test_pydeck.py) +- [test_pydeck test](https://github.com/MarcSkovMadsen/awesome-panel/blob/master/package/tests/test_pydeck.py) + +It's based on the following resources + +- [PyDeck Github](https://github.com/uber/deck.gl/tree/master/bindings/pydeck) +- [PyDeck Docs](https://deckgl.readthedocs.io/en/latest/) +- [PyDeck Deck Implementation](https://github.com/uber/deck.gl/blob/master/bindings/pydeck/pydeck/bindings/deck.py) +- [PyDeck render_json_to_html Implementation](https://github.com/uber/deck.gl/blob/master/bindings/pydeck/pydeck/io/html.py) + +When I move on I believe I can find inspiration in + +- The Panel implementation of the Plotly Pane and Plotly Bokeh Model +- [Extending Bokeh](https://docs.bokeh.org/en/latest/docs/user_guide/extensions.html) +- [PyDeck Jupyter Implementation](https://github.com/uber/deck.gl/blob/master/bindings/pydeck/pydeck/widget/widget.py) +""" +