uwdata / mosaic

An extensible framework for linking databases and interactive views.
https://idl.uw.edu/mosaic/
Other
860 stars 56 forks source link

Add Panel example #217

Open MarcSkovMadsen opened 12 months ago

MarcSkovMadsen commented 12 months ago

HoloViz Panel is a powerful framework for data exploration and web apps. Bokeh, Panel and IpyWidgets integrate with each other, i.e. they can use each others widgets. This includes AnyWidget and MosaicWidget.

Please document the integration to Panel. If you are interested, I would be willing to make a PR. Let me know.

Example

https://github.com/uwdata/mosaic/assets/42288570/0cad9472-53c3-4618-8f1d-4db3e6951c72


# pip install panel pandas ipywidgets_bokeh mosaic-widget
import pandas as pd
from mosaic_widget import MosaicWidget

weather = pd.read_csv(
    "https://uwdata.github.io/mosaic-datasets/data/seattle-weather.csv",
    parse_dates=["date"],
)

specification = {
    "meta": {
        "title": "Seattle Weather",
        "description": "An interactive view of Seattle’s weather, including maximum temperature, amount of precipitation, and type of weather. By dragging on the scatter plot, you can see the proportion of days in that range that have sun, fog, drizzle, rain, or snow.\n",
        "credit": "Based on a [Vega-Lite/Altair example](https://vega.github.io/vega-lite/examples/interactive_seattle_weather.html) by Jake Vanderplas.",
    },
    "params": {
        "click": {"select": "single"},
        "domain": ["sun", "fog", "drizzle", "rain", "snow"],
        "colors": ["#e7ba52", "#a7a7a7", "#aec7e8", "#1f77b4", "#9467bd"],
    },
    "vconcat": [
        {
            "hconcat": [
                {
                    "plot": [
                        {
                            "mark": "dot",
                            "data": {"from": "weather", "filterBy": "$click"},
                            "x": {"dateMonthDay": "date"},
                            "y": "temp_max",
                            "fill": "weather",
                            "r": "precipitation",
                            "fillOpacity": 0.7,
                        },
                        {
                            "select": "intervalX",
                            "as": "$range",
                            "brush": {"fill": "none", "stroke": "#888"},
                        },
                        {
                            "select": "highlight",
                            "by": "$range",
                            "fill": "#ccc",
                            "fillOpacity": 0.2,
                        },
                        {"legend": "color", "as": "$click", "columns": 1},
                    ],
                    "xyDomain": "Fixed",
                    "xTickFormat": "%b",
                    "colorDomain": "$domain",
                    "colorRange": "$colors",
                    "rDomain": "Fixed",
                    "rRange": [2, 10],
                    "width": 680,
                    "height": 300,
                }
            ]
        },
        {
            "plot": [
                {
                    "mark": "barX",
                    "data": {"from": "weather"},
                    "x": {"count": None},
                    "y": "weather",
                    "fill": "#ccc",
                    "fillOpacity": 0.2,
                },
                {
                    "mark": "barX",
                    "data": {"from": "weather", "filterBy": "$range"},
                    "x": {"count": None},
                    "y": "weather",
                    "fill": "weather",
                    "order": "weather",
                },
                {"select": "toggleY", "as": "$click"},
                {"select": "highlight", "by": "$click"},
            ],
            "xDomain": "Fixed",
            "yDomain": "$domain",
            "yLabel": None,
            "colorDomain": "$domain",
            "colorRange": "$colors",
            "width": 680,
        },
    ],
}
mosaic = MosaicWidget(specification, data={"weather": weather})

# THE PANEL APP

import panel as pn

pn.extension("ipywidgets")

component = pn.panel(mosaic, sizing_mode="stretch_width")

pn.template.FastListTemplate(
    logo="https://panel.holoviz.org/_static/logo_horizontal_dark_theme.png",
    title="Works with MosaicWidget",
    main=[component],
).servable()
MarcSkovMadsen commented 5 months ago

Would you be interested in a PR to the docs?

I think a section called Ecosystem similar to https://developmentseed.org/lonboard/latest/ecosystem/panel/ would make a lot of sense.

image

MarcSkovMadsen commented 5 months ago

From Panel 1.5.0 it will be possible to build Panel native components using the AnyWidget esm javascript with no changes.

I.e. it would be possible to to reuse the javascript and css of the Jupyter Widget and then implement a Panel Widget similarly to https://discord.com/channels/@me/1085958445326405653/1249347162010030111 but using Param instead of Traitlets.

Let me know if you are interested in a Mosaic Panel component. The benefit of a native component is 1) The way the Panel users can interact with it 2) performance.

domoritz commented 5 months ago

I think a panel component (similar to the Jupiter widget in this repo already) would be great. Depending on the complexity, it could be in this repo or a separate repo.