'
57 | text = text.replace(before, after)
58 | return dict(properties, text=escape(text))
59 |
60 |
61 | # A Hack to be able to get responsive Folium plots
62 | pn.pane.plot.Folium._get_properties = _get_properties
63 |
64 | pn.pane.plot.Folium(plot, min_height=700, sizing_mode="stretch_both").servable()
65 |
--------------------------------------------------------------------------------
/src/dataviz_in_python/presentation/lib_holoviews.py:
--------------------------------------------------------------------------------
1 | import holoviews as hv
2 | import numpy as np
3 | import panel as pn
4 | from holoviews import opts, streams
5 | from holoviews.plotting.links import DataLink
6 |
7 | from dataviz_in_python import config
8 |
9 | config.configure(url="lib_holoviews", title="HoloViews")
10 |
11 | TEXT = """
12 | # HoloViews: Stop plotting your data - annotate your data and let it visualize itself.
13 |
14 | [HoloViews](http://holoviews.org/index.html) is an open-source Python library designed to make data analysis and visualization seamless and simple. With HoloViews, you can usually express what you want to do in very few lines of code, letting you focus on what you are trying to explore and convey, not on the process of plotting.
15 |
16 | You can use any of the backends [Bokeh](lib_bokeh), [Matplotlib](lib_matplotlib) and
17 | [Plotly](lib_plotly). Please note that Bokeh has the most comprehensive and robust support.
18 |
19 | HoloViews is much harder to learn than and less robust than Plotly.
20 | But it provides a lot of features for specialized use cases and a mental
21 | model for data visualiation.
22 |
23 | [Source Code](https://github.com/MarcSkovMadsen/dataviz-in-python/blob/main/src/dataviz_in_python/presentation/lib_holoviews.py)
24 | """
25 | pn.panel(TEXT, css_classes=[config.TEXT_CLASS]).servable()
26 |
27 |
28 | def get_plot(theme="default", accent_base_color="blue"):
29 | curve = hv.Curve(np.random.randn(10).cumsum()).opts(
30 | min_height=600,
31 | responsive=True,
32 | line_width=6,
33 | color=accent_base_color,
34 | # https://github.com/holoviz/holoviews/issues/5058
35 | # active_tools=["point_draw"]
36 | )
37 | if theme == "default":
38 | point_color = "black"
39 | else:
40 | point_color = "#E5E5E5"
41 |
42 | streams.CurveEdit(data=curve.columns(), source=curve, style={"color": point_color, "size": 10})
43 |
44 | table = hv.Table(curve).opts(editable=True)
45 | DataLink(curve, table)
46 |
47 | return (curve + table).opts(
48 | opts.Table(editable=True),
49 | )
50 |
51 |
52 | plot = get_plot(theme=config.get_theme(), accent_base_color=config.ACCENT_BASE_COLOR)
53 | pn.pane.HoloViews(plot, height=600, sizing_mode="stretch_both").servable()
54 |
--------------------------------------------------------------------------------
/src/dataviz_in_python/presentation/lib_hvplot.py:
--------------------------------------------------------------------------------
1 | import hvplot.pandas # noqa
2 | import panel as pn
3 | from bokeh.sampledata.sprint import sprint
4 |
5 | from dataviz_in_python import config
6 |
7 | config.configure(url="lib_hvplot", title="hvplot")
8 |
9 | TEXT = """
10 | # hvplot: A high-level plotting API for the PyData ecosystem built on HoloViews.
11 |
12 | [hvplot](https://hvplot.holoviz.org/) extends the [Pandas](https://pandas.pydata.org/) `.plot` api to other data frameworks like
13 | [Dask](https://docs.rapids.ai/api/cudf/stable/),
14 | [GeoPandas](https://geopandas.org/),
15 | [Intake](https://github.com/ContinuumIO/intake),
16 | [NetworkX](https://networkx.github.io/documentation/stable/).
17 | [Rapids cuDF](https://docs.rapids.ai/api/cudf/stable/),
18 | [Streamz](https://streamz.readthedocs.io/) and
19 | [XArray](https://xarray.pydata.org/),
20 |
21 | Currently the backend is [Bokeh](lib_bokeh). But that will soon be extended to
22 | [Matplotlib](lib_matplotlib) and [Plotly](lib_plotly).
23 |
24 | Personally I use `.hvplot` for simple data exploration and data apps. I like the simple api and the
25 | ability to combine plots with simple `*`, `+` and `/` operations.
26 |
27 | [Source Code](https://github.com/MarcSkovMadsen/dataviz-in-python/blob/main/src/dataviz_in_python/presentation/lib_hvplot.py)
28 | """
29 | pn.panel(TEXT, css_classes=[config.TEXT_CLASS]).servable()
30 |
31 |
32 | def get_plot():
33 | return sprint.hvplot.violin(
34 | y="Time",
35 | by="Medal",
36 | c="Medal",
37 | ylabel="Sprint Time",
38 | cmap=["gold", "silver", "brown"],
39 | legend=False,
40 | responsive=True,
41 | padding=0.4,
42 | )
43 |
44 |
45 | plot = get_plot()
46 | pn.pane.HoloViews(plot, height=500, sizing_mode="stretch_both").servable()
47 |
--------------------------------------------------------------------------------
/src/dataviz_in_python/presentation/lib_ipywidgets.py:
--------------------------------------------------------------------------------
1 | import panel as pn
2 | import ipywidgets as ipw
3 | import ipysheet
4 |
5 | from dataviz_in_python import config
6 |
7 | config.configure("ipywidgets", title="ipywidgets", url="lib_ipywidgets")
8 |
9 | TEXT = """
10 | # Ipywidgets: Interactive Visualization in the Browser
11 |
12 | [Ipywidgets](https://ipywidgets.readthedocs.io/en/latest/) ipywidgets, also
13 | known as jupyter-widgets or simply widgets, are interactive HTML widgets for
14 | Jupyter notebooks, the IPython kernel and your
15 | [Panel](https://panel.holoviz.org) data app.
16 |
17 | A lot of data visualization widgets are built on top of ipywidgets.
18 |
19 | Here we are displaying [Ipysheet](https://github.com/QuantStack/ipysheet)
20 |
21 | [Source Code](https://github.com/MarcSkovMadsen/dataviz-in-python/blob/main/src/dataviz_in_python/presentation/lib_ipywidgets.py)
22 | """
23 | pn.panel(TEXT, css_classes=[config.TEXT_CLASS]).servable()
24 |
25 |
26 | def get_widget(accent_base_color="blue"):
27 | slider = pn.widgets.FloatSlider(value=10, start=0, end=100)
28 | sheet = ipysheet.sheet()
29 |
30 | ipysheet.cell(1, 1, "Input")
31 | cell3 = ipysheet.cell(1, 2, 42.0)
32 | ipysheet.cell(2, 1, "Output")
33 | cell_sum = ipysheet.cell(2, 2, 52.0, read_only=True, background_color=accent_base_color)
34 |
35 | @pn.depends(slider, cell3, watch=True)
36 | def calculate(a, b):
37 | cell_sum.value = a + b
38 |
39 | return pn.Column(slider, sheet)
40 |
41 |
42 | widget = get_widget(accent_base_color=config.ACCENT_BASE_COLOR)
43 | pn.panel(widget, height=700, sizing_mode="stretch_both").servable()
44 |
--------------------------------------------------------------------------------
/src/dataviz_in_python/presentation/lib_leaflet.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import panel as pn
3 | import holoviews as hv
4 | import xarray as xr
5 | import hvplot.xarray
6 | import param
7 |
8 | from dataviz_in_python import config
9 |
10 | config.configure(title="Leaflet", url="lib_leaflet")
11 |
12 | TEXT = """
13 | # Leaflet: Mobile-friendly interactive maps
14 |
15 | [Leaflet](https://leafletjs.com/) is the leading open-source JavaScript library for mobile-friendly interactive maps. It has all the mapping features most developers ever need.
16 |
17 | You can use leaflet in Python via for example [IPyleaflet](https://ipyleaflet.readthedocs.io/en/latest/), Dash or as here via Panel. See also [Panel Ipyleaflet](https://discourse.holoviz.org/t/works-with-ipyleaflet/2755)
18 |
19 | [Source Code](https://github.com/MarcSkovMadsen/dataviz-in-python/blob/main/src/dataviz_in_python/presentation/lib_leaflet.py)
20 | """
21 | pn.panel(TEXT, css_classes=[config.TEXT_CLASS]).servable()
22 |
23 |
24 | class LeafletMap(pn.reactive.ReactiveHTML):
25 | marker1_clicks = param.Integer()
26 | marker2_clicks = param.Integer()
27 | marker3_clicks = param.Integer()
28 |
29 | _template = """
"""
30 |
31 | __css__ = ["https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"]
32 | __javascript__ = ["https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"]
33 |
34 | _scripts = {
35 | "render": """
36 | var mymap = L.map(mapid).setView([50, 0], 6);
37 | state.map=mymap
38 |
39 | var tileLayer = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
40 | attribution: 'Map data ©
OpenStreetMap contributors, Imagery ©
Mapbox',
41 | maxZoom: 18,
42 | id: 'mapbox/streets-v11',
43 | tileSize: 512,
44 | zoomOffset: -1,
45 | accessToken: 'pk.eyJ1IjoibWFyY3Nrb3ZtYWRzZW4iLCJhIjoiY2s1anMzcG5rMDYzazNvcm10NTFybTE4cSJ9.TV1XBgaMfR-iTLvAXM_Iew'
46 | }).addTo(mymap)
47 |
48 | var marker1 = L.marker([48, -2], name='marker1');
49 | marker1.on('click', (e) => { data.marker1_clicks = data.marker1_clicks + 1 })
50 |
51 | var marker2 = L.marker([50, 0], name='marker2');
52 | marker2.on('click', (e) => { data.marker2_clicks = data.marker2_clicks + 1 })
53 |
54 | var marker3 = L.marker([52, 2], name='marker3');
55 | marker3.on('click', (e) => { data.marker3_clicks = data.marker3_clicks + 1 })
56 |
57 | var layer1 = L.layerGroup([marker1, marker2, marker3]);
58 | layer1.addTo(mymap)
59 | L.control.layers({"tile1": tileLayer},{"layer1": layer1}).addTo(mymap);
60 | """,
61 | # Need to resize leaflet map to size of outer container
62 | "after_layout": """
63 | state.map.invalidateSize();console.log("invalidated");
64 | """,
65 | }
66 |
67 |
68 | map = LeafletMap(height=700)
69 | clicks = pn.Param(
70 | map, parameters=["marker1_clicks", "marker2_clicks", "marker3_clicks"], sizing_mode="fixed"
71 | )
72 |
73 | pn.Row(map, clicks, sizing_mode="stretch_both").servable()
74 |
--------------------------------------------------------------------------------
/src/dataviz_in_python/presentation/lib_matplotlib.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import numpy as np
3 | from matplotlib import cm
4 | from matplotlib.backends.backend_agg import FigureCanvas # not needed for mpl >= 3.1
5 | from matplotlib.figure import Figure
6 | import panel as pn
7 |
8 | from dataviz_in_python import config
9 |
10 | config.configure("vega", url="lib_matplotlib", title="Matplotlib")
11 |
12 | TEXT = """
13 | # Matplotlib: Static plots in Python without limits
14 |
15 | [Matplotlib](https://matplotlib.org/) is a comprehensive library for creating static, animated, and interactive visualizations in Python. Matplotlib makes easy things easy and hard things possible. Matplotlib is the most used plotting library in Python.
16 |
17 | Matplotlib only supports interactivity to a limited extent compared to Altair, Bokeh, HoloViews and Plotly. So personally I normally don't use it.
18 |
19 | [Source Code](https://github.com/MarcSkovMadsen/dataviz-in-python/blob/main/src/dataviz_in_python/presentation/lib_matplotlib.py)
20 | """
21 | pn.panel(TEXT, css_classes=[config.TEXT_CLASS]).servable()
22 |
23 |
24 | def get_plot(theme="default"):
25 | plt.style.use("default")
26 | if theme == "dark":
27 | plt.style.use("dark_background")
28 | Y, X = np.mgrid[-3:3:100j, -3:3:100j]
29 | U = -1 - X**2 + Y
30 | V = 1 + X - Y**2
31 | speed = np.sqrt(U * U + V * V)
32 |
33 | fig0 = Figure(figsize=(12, 6))
34 | ax0 = fig0.subplots()
35 | FigureCanvas(fig0) # not needed for mpl >= 3.1
36 |
37 | strm = ax0.streamplot(X, Y, U, V, color=U, linewidth=2, cmap=cm.autumn)
38 | fig0.colorbar(strm.lines)
39 | return fig0
40 |
41 |
42 | plot = get_plot(theme=config.get_theme())
43 | pn.pane.Matplotlib(plot, height=600, sizing_mode="scale_height").servable()
44 |
--------------------------------------------------------------------------------
/src/dataviz_in_python/presentation/lib_plotly.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | import panel as pn
3 |
4 | import plotly.express as px
5 |
6 | from dataviz_in_python import config
7 |
8 | config.configure("plotly", url="lib_plotly", title="Plotly")
9 |
10 | TEXT = """
11 | # Plotly: High Quality, Interactive Plots in Python
12 |
13 | [Plotly](https://plotly.com/python/)'s Python graphing library makes interactive, publication-quality graph.
14 |
15 | Plotly is one of the most popular plotting libraries in Python. It has high quality documentation and produces very appealing plots.
16 |
17 | One thing to note is that Plotly is a also a company that has a hard time finding funding for developing Plotly.
18 | Increasingly they focus on and market Dash the data app framework because there is a business case.
19 |
20 | [Source Code](https://github.com/MarcSkovMadsen/dataviz-in-python/blob/main/src/dataviz_in_python/presentation/lib_plotly.py)
21 | """
22 | pn.panel(TEXT, css_classes=[config.TEXT_CLASS]).servable()
23 |
24 |
25 | def get_plot(theme="default", accent_base_color="blue"):
26 | data = pd.DataFrame(
27 | [
28 | ("Monday", 7),
29 | ("Tuesday", 4),
30 | ("Wednesday", 9),
31 | ("Thursday", 4),
32 | ("Friday", 4),
33 | ("Saturday", 4),
34 | ("Sunay", 4),
35 | ],
36 | columns=["Day", "Orders"],
37 | )
38 |
39 | if theme == "dark":
40 | plotly_template = "plotly_dark"
41 | else:
42 | plotly_template = "plotly"
43 |
44 | fig = px.line(
45 | data,
46 | x="Day",
47 | y="Orders",
48 | template=plotly_template,
49 | color_discrete_sequence=(accent_base_color,),
50 | )
51 | fig.update_traces(mode="lines+markers", marker=dict(size=10), line=dict(width=4))
52 | fig.layout.autosize = True
53 | return fig
54 |
55 |
56 | plot = get_plot(theme=config.get_theme(), accent_base_color=config.ACCENT_BASE_COLOR)
57 | pn.pane.Plotly(plot, config={"responsive": True}, sizing_mode="stretch_both", height=700).servable()
58 |
--------------------------------------------------------------------------------
/src/dataviz_in_python/presentation/lib_plotnine.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import panel as pn
3 |
4 | from plotnine import aes, element_rect, facet_wrap, geom_point, ggplot, stat_smooth, themes
5 | from plotnine.data import mtcars
6 | from dataviz_in_python import config
7 |
8 | config.configure(url="lib_plotnine", title="Plotnine")
9 |
10 | TEXT = """
11 | # Plotnine: A Grammar of Graphics for Python
12 |
13 | [Plotnine](https://plotnine.readthedocs.io/en/stable/) is an implementation of a grammar of graphics in Python, it is based on [ggplot2](https://ggplot2.tidyverse.org/). The grammar allows users to compose plots by explicitly mapping data to the visual objects that make up the plot. Its based on Matplotlib.
14 |
15 | [Source Code](https://github.com/MarcSkovMadsen/dataviz-in-python/blob/main/src/dataviz_in_python/presentation/lib_plotnine.py)
16 | """
17 | pn.panel(TEXT, css_classes=[config.TEXT_CLASS]).servable()
18 |
19 |
20 | def get_plot(theme="default"):
21 | plt.style.use("default")
22 | if theme == "dark":
23 | plotnine_theme = themes.theme_dark() + themes.theme(
24 | plot_background=element_rect(fill="black", alpha=0)
25 | )
26 | else:
27 | plotnine_theme = themes.theme_xkcd()
28 |
29 | plot = (
30 | (
31 | ggplot(mtcars, aes("wt", "mpg", color="factor(gear)"))
32 | + geom_point()
33 | + stat_smooth(method="lm")
34 | + facet_wrap("~gear")
35 | )
36 | + plotnine_theme
37 | + themes.theme(figure_size=(16, 8))
38 | )
39 | return plot.draw()
40 |
41 |
42 | plot = get_plot(theme=config.get_theme())
43 |
44 | pn.pane.Matplotlib(plot, height=700, sizing_mode="stretch_both").servable()
45 |
--------------------------------------------------------------------------------
/src/dataviz_in_python/presentation/lib_pydeck.py:
--------------------------------------------------------------------------------
1 | import pydeck
2 | import panel as pn
3 |
4 | from dataviz_in_python import config
5 |
6 | config.configure("deckgl", url="lib_pydeck", title="PyDeck")
7 |
8 | TEXT = """
9 | # PyDeck: High-scale spatial rendering in Python, powered by deck.gl.
10 |
11 | [PyDeck](https://deckgl.readthedocs.io/en/latest/) is a Python wrapper for [deck.gl](lib_deckgl).
12 |
13 | [Source Code](https://github.com/MarcSkovMadsen/dataviz-in-python/blob/main/src/dataviz_in_python/presentation/lib_deckgl.py)
14 | """
15 | pn.panel(TEXT, css_classes=[config.TEXT_CLASS]).servable()
16 |
17 |
18 | def get_plot(theme="default", accent_base_color="blue"):
19 | LAND_COVER = [[[-123.0, 49.196], [-123.0, 49.324], [-123.306, 49.324], [-123.306, 49.196]]]
20 | polygon = pydeck.Layer(
21 | "PolygonLayer",
22 | LAND_COVER,
23 | stroked=False,
24 | # processes the data as a flat longitude-latitude pair
25 | get_polygon="-",
26 | get_fill_color=[0, 0, 0, 20],
27 | )
28 |
29 | DATA_URL = "https://raw.githubusercontent.com/uber-common/deck.gl-data/master/examples/geojson/vancouver-blocks.json"
30 | geojson = pydeck.Layer(
31 | "GeoJsonLayer",
32 | DATA_URL,
33 | opacity=0.8,
34 | stroked=False,
35 | filled=True,
36 | extruded=True,
37 | wireframe=True,
38 | get_elevation="properties.valuePerSqm / 20",
39 | get_fill_color="[255, 255, properties.growth * 255]",
40 | get_line_color=[255, 255, 255],
41 | pickable=True,
42 | )
43 |
44 | if theme == "dark":
45 | deckgl_map_style = "mapbox://styles/mapbox/dark-v9"
46 | else:
47 | deckgl_map_style = "mapbox://styles/mapbox/light-v9"
48 | MAPBOX_KEY = (
49 | "pk.eyJ1IjoicGFuZWxvcmciLCJhIjoiY2s1enA3ejhyMWhmZjNobjM1NXhtbWRrMyJ9.B_frQsAVepGIe-HiOJeqvQ"
50 | )
51 | INITIAL_VIEW_STATE = pydeck.ViewState(
52 | latitude=49.254, longitude=-123.13, zoom=11, max_zoom=16, pitch=45, bearing=0
53 | )
54 |
55 | r = pydeck.Deck(
56 | api_keys={"mapbox": MAPBOX_KEY},
57 | layers=[polygon, geojson],
58 | initial_view_state=INITIAL_VIEW_STATE,
59 | map_style=deckgl_map_style,
60 | )
61 |
62 | # Tooltip (you can get the id directly from the layer object)
63 | geojson_tooltip = {
64 | "html": """
65 |
Value per Square meter: {properties.valuePerSqm}
66 |
Growth: {properties.growth}
67 | """,
68 | "style": {"backgroundColor": accent_base_color, "color": "white"},
69 | }
70 | tooltips = {geojson.id: geojson_tooltip}
71 | return r, tooltips
72 |
73 |
74 | plot, tooltips = get_plot()
75 |
76 | pn.pane.DeckGL(plot, tooltips=tooltips, height=800, sizing_mode="stretch_both").servable()
77 |
--------------------------------------------------------------------------------
/src/dataviz_in_python/presentation/lib_pyecharts.py:
--------------------------------------------------------------------------------
1 | import json
2 | import panel as pn
3 |
4 | from pyecharts.charts import Bar
5 |
6 | from dataviz_in_python import config
7 |
8 | config.configure("echarts", url="lib_pyecharts", title="PyECharts")
9 |
10 | TEXT = """
11 | # PyEcharts: A Python wrapper for ECharts
12 |
13 | [PyEcharts](https://pyecharts.org/#/) is a Python wrapper for [ECharts](lib_echarts).
14 |
15 | Please note **currently I cannot recommend PyEcharts** as the documentation often seems out of date
16 | and the examples not working. But Echarts and thus PyEcharts is an Apache project and produces
17 | business plots of a higher quality than Plotly. So it worth monitoring.
18 |
19 | [Source Code](https://github.com/MarcSkovMadsen/dataviz-in-python/blob/main/src/dataviz_in_python/presentation/lib_pyecharts.py)
20 | """
21 | pn.panel(TEXT, css_classes=[config.TEXT_CLASS]).servable()
22 |
23 |
24 | def get_plot(accent_base_color="blue"):
25 | plot = (
26 | Bar()
27 | .add_xaxis(["Helicoptors", "Planes", "Air Ballons"])
28 | .add_yaxis("Total In Flight", [50, 75, 25], color=accent_base_color)
29 | )
30 |
31 | # Workaround to make plot responsive
32 | plot = json.loads(plot.dump_options())
33 | plot["responsive"] = True
34 | return plot
35 |
36 |
37 | theme = config.get_theme()
38 | plot = get_plot(accent_base_color=config.ACCENT_BASE_COLOR)
39 | pn.pane.ECharts(plot, min_height=500, sizing_mode="stretch_both", theme=theme).servable()
40 |
--------------------------------------------------------------------------------
/src/dataviz_in_python/presentation/lib_pyvista.py:
--------------------------------------------------------------------------------
1 | import json
2 | import panel as pn
3 | import pyvista as pv
4 |
5 | from dataviz_in_python import config
6 |
7 | config.configure("vtk", url="lib_vista", title="PyVista")
8 |
9 | TEXT = """
10 | # PyVista: 3D plotting and mesh analysis through a streamlined interface for the Visualization Toolkit (VTK)
11 |
12 | [PyVista](https://docs.pyvista.org/) PyVista is a helper module for the Visualization Toolkit (VTK)
13 | that takes a different approach on interfacing with VTK through NumPy and direct array access
14 |
15 | [Source Code](https://github.com/MarcSkovMadsen/dataviz-in-python/blob/main/src/dataviz_in_python/presentation/lib_pyvista.py)
16 | """
17 | pn.panel(TEXT, css_classes=[config.TEXT_CLASS]).servable()
18 |
19 |
20 | def get_plot(theme="default", accent_base_color="blue"):
21 | plotter = pv.Plotter() # we define a pyvista plotter
22 | if theme == "dark":
23 | plotter.background_color = (0.13, 0.13, 0.13)
24 | else:
25 | plotter.background_color = (0.97, 0.97, 0.97)
26 |
27 | # we create a `VTK` panel around the render window
28 | pvcylinder = pv.Cylinder(resolution=8, direction=(0, 1, 0))
29 | cylinder_actor = plotter.add_mesh(pvcylinder, color=accent_base_color, smooth_shading=True)
30 | cylinder_actor.RotateX(30.0)
31 | cylinder_actor.RotateY(-45.0)
32 | plotter.add_mesh(
33 | pv.Sphere(theta_resolution=8, phi_resolution=8, center=(0.5, 0.5, 0.5)),
34 | color=accent_base_color,
35 | smooth_shading=True,
36 | )
37 | return plotter.ren_win
38 |
39 |
40 | plot = get_plot(theme=config.get_theme(), accent_base_color=config.ACCENT_BASE_COLOR)
41 | pn.panel(plot, height=700, sizing_mode="stretch_both").servable()
42 |
--------------------------------------------------------------------------------
/src/dataviz_in_python/presentation/lib_seaborn.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 |
3 | import panel as pn
4 | import seaborn as sns
5 |
6 | penguins = sns.load_dataset("penguins")
7 |
8 | from dataviz_in_python import config
9 |
10 | config.configure(url="lib_seaborn", title="Seaborn")
11 |
12 | TEXT = """
13 | # Seaborn: Statistical data visualization
14 |
15 | [Seaborn](https://seaborn.pydata.org/) Seaborn is a Python data visualization
16 | library based on [matplotlib](lib_matplotlib). It provides a high-level
17 | interface for drawing attractive and informative statistical graphics.
18 |
19 | Please note the lead developer is tweeting about upcoming, major changes to
20 | the api.
21 |
22 | [Source Code](https://github.com/MarcSkovMadsen/dataviz-in-python/blob/main/src/dataviz_in_python/presentation/lib_seaborn.py)
23 | """
24 | pn.panel(TEXT, css_classes=[config.TEXT_CLASS]).servable()
25 |
26 |
27 | def get_plot(theme="default", accent_base_color="blue"):
28 | if theme == "dark":
29 | sns.set_style("darkgrid")
30 | plt.style.use("dark_background")
31 | else:
32 | plt.style.use("default")
33 | sns.set_style("whitegrid")
34 |
35 | plot = sns.displot(penguins, x="flipper_length_mm", color=accent_base_color)
36 | fig0 = plot.fig
37 | fig0.set_size_inches(16, 8)
38 | return fig0
39 |
40 |
41 | plot = get_plot(theme=config.get_theme(), accent_base_color=config.ACCENT_BASE_COLOR)
42 | pn.pane.Matplotlib(plot, height=700, sizing_mode="stretch_both").servable()
43 |
--------------------------------------------------------------------------------
/src/dataviz_in_python/presentation/lib_vega.py:
--------------------------------------------------------------------------------
1 | import panel as pn
2 |
3 | from dataviz_in_python import config
4 |
5 | config.configure(url="lib_vega", title="Vega & Vega-Lite")
6 |
7 | TEXT = """
8 | # Vega: A Grammar of Graphics for Python
9 |
10 | [Vega](https://vega.github.io/) is a declarative format for creating, saving, and sharing
11 | visualization designs. With Vega, visualizations are described in JSON, and
12 | generate interactive views using either HTML5 Canvas or SVG.
13 |
14 | Please note that **you should be using the higher level Vega-Lite format.**
15 |
16 | [Source Code](https://github.com/MarcSkovMadsen/dataviz-in-python/blob/main/src/dataviz_in_python/presentation/lib_vega.py)
17 | """
18 | pn.panel(TEXT, css_classes=[config.TEXT_CLASS]).servable()
19 |
20 |
21 | def get_plot(theme="default"):
22 | vegalite = {
23 | "$schema": "https://vega.github.io/schema/vega-lite/v3.json",
24 | "data": {"url": "https://raw.githubusercontent.com/vega/vega/master/docs/data/barley.json"},
25 | "mark": {"type": "bar", "tooltip": True},
26 | "width": "container",
27 | "height": "container",
28 | "encoding": {
29 | "x": {"aggregate": "sum", "field": "yield", "type": "quantitative"},
30 | "y": {"field": "variety", "type": "nominal"},
31 | "color": {"field": "site", "type": "nominal"},
32 | },
33 | }
34 |
35 | if theme == "dark":
36 | vegalite["config"] = {
37 | "background": "#333",
38 | "title": {"color": "#fff"},
39 | "style": {"guide-label": {"fill": "#fff"}, "guide-title": {"fill": "#fff"}},
40 | "axis": {"domainColor": "#fff", "gridColor": "#888", "tickColor": "#fff"},
41 | }
42 | return vegalite
43 |
44 |
45 | plot = get_plot(theme=config.get_theme())
46 | pn.pane.Vega(plot, height=700, sizing_mode="stretch_both").servable()
47 |
--------------------------------------------------------------------------------
/src/dataviz_in_python/presentation/lib_vtk.py:
--------------------------------------------------------------------------------
1 | import panel as pn
2 | import vtk
3 |
4 | from vtk.util.colors import tomato
5 |
6 | from dataviz_in_python import config
7 |
8 | config.configure("vtk", url="lib_vtk", title="VTK")
9 |
10 | TEXT = """
11 | # VTK: Process images and create 3D computer graphics with the Visualization Toolkit.
12 |
13 | [VTK](https://vtk.org/) is open source software for manipulating and
14 | displaying scientific data. It comes with state-of-the-art tools for 3D
15 | rendering, a suite of widgets for 3D interaction, and extensive 2D
16 | plotting capability.
17 |
18 | [Source Code](https://github.com/MarcSkovMadsen/dataviz-in-python/blob/main/src/dataviz_in_python/presentation/lib_vtk.py)
19 | """
20 | pn.panel(TEXT, css_classes=[config.TEXT_CLASS]).servable()
21 |
22 |
23 | def get_plot(theme="default", accent_base_color="red"):
24 | # This creates a polygonal cylinder model with eight circumferential
25 | # facets.
26 | cylinder = vtk.vtkCylinderSource()
27 | cylinder.SetResolution(8)
28 |
29 | # The mapper is responsible for pushing the geometry into the graphics
30 | # library. It may also do color mapping, if scalars or other
31 | # attributes are defined.
32 | cylinderMapper = vtk.vtkPolyDataMapper()
33 | cylinderMapper.SetInputConnection(cylinder.GetOutputPort())
34 |
35 | # The actor is a grouping mechanism: besides the geometry (mapper), it
36 | # also has a property, transformation matrix, and/or texture map.
37 | # Here we set its color and rotate it -22.5 degrees.
38 | cylinderActor = vtk.vtkActor()
39 | cylinderActor.SetMapper(cylinderMapper)
40 | cylinderActor.GetProperty().SetColor(tomato)
41 | # We must set ScalarVisibilty to 0 to use tomato Color
42 | cylinderMapper.SetScalarVisibility(0)
43 | cylinderActor.RotateX(30.0)
44 | cylinderActor.RotateY(-45.0)
45 |
46 | # Create the graphics structure. The renderer renders into the render
47 | # window.
48 | ren = vtk.vtkRenderer()
49 | renWin = vtk.vtkRenderWindow()
50 | renWin.AddRenderer(ren)
51 |
52 | # Add the actors to the renderer, set the background and size
53 | ren.AddActor(cylinderActor)
54 | if theme == "dark":
55 | ren.SetBackground(0.13, 0.13, 0.13)
56 | else:
57 | ren.SetBackground(0.97, 0.97, 0.97)
58 | return renWin
59 |
60 |
61 | plot = get_plot(theme=config.get_theme())
62 | component = pn.pane.VTK(plot, height=700, sizing_mode="stretch_both").servable()
63 |
--------------------------------------------------------------------------------
/src/dataviz_in_python/presentation/streaming.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | import panel as pn
4 |
5 | from dataviz_in_python import config
6 |
7 | config.configure(title="Streaming")
8 |
9 | TEXT = """
10 | # Streaming: Live data or story telling with a time dimension
11 |
12 | [Source Code](https://github.com/MarcSkovMadsen/dataviz-in-python/blob/main/src/dataviz_in_python/presentation/streaming.py)
13 | """
14 | pn.panel(TEXT, css_classes=[config.TEXT_CLASS]).servable()
15 |
16 | layout = pn.layout.FlexBox(
17 | *(
18 | pn.indicators.Trend(
19 | data={"x": list(range(10)), "y": np.random.randn(10).cumsum()},
20 | width=200,
21 | height=150,
22 | plot_type=pn.indicators.Trend.param.plot_type.objects[i % 4],
23 | )
24 | for i in range(36)
25 | )
26 | ).servable()
27 |
28 |
29 | def stream():
30 | for trend in layout:
31 | trend.stream(
32 | {"x": [trend.data["x"][-1] + 1], "y": [trend.data["y"][-1] + np.random.randn()]},
33 | rollover=20,
34 | )
35 |
36 |
37 | cb = pn.state.add_periodic_callback(stream, 500)
38 |
--------------------------------------------------------------------------------