Plotly View

Last Updated: August 2023

Important

This gizmo requires the plotly library to be installed. Starting with Tethys 5.0 or if you are using micro-tethys-platform, you will need to install plotly using conda or pip as follows:

bash
# conda: conda-forge channel strongly recommended
conda install -c conda-forge plotly

# pip
pip install plotly

Don't Forget: If you end up using this gizmo in your app, add plotly as a requirement to your install.yml.

Python

class tethys_sdk.gizmos.PlotlyView(plot_input, height=None, width='100%', attributes='', classes='', divid='', hidden=False, show_link=False)

Simple options object for plotly view.

Note

Information about the Plotly API can be found at https://plot.ly/python.

plot_input

A plotly graph_objs to be plotted.

Type:

plotly graph_objs

height

Height of the plot element. Any valid css unit of length.

Type:

Optional[str]

width

Width of the plot element. Any valid css unit of length.

Type:

Optional[str]

attributes

Dictionary of attributed to add to the outer div.

Type:

Optional[dict]

classes

Space separated string of classes to add to the outer div.

Type:

Optional[str]

hidden

If True, the plot will be hidden. Default is False.

Type:

Optional[bool]

If True, the link to export plot to view in plotly is shown. Default is False.

Type:

Optional[bool]

Controller Code Basic Example:

python
from datetime import datetime
import plotly.graph_objs as go
from tethys_sdk.gizmos import PlotlyView

x = [datetime(year=2013, month=10, day=04),
     datetime(year=2013, month=11, day=05),
     datetime(year=2013, month=12, day=06)]

my_plotly_view = PlotlyView([go.Scatter(x=x, y=[1, 3, 6])])

context = {'plotly_view_input': my_plotly_view}

Controller Code Pandas Example:

python
import numpy as np
import pandas as pd
from tethys_sdk.gizmos import PlotlyView

df = pd.DataFrame(np.random.randn(1000, 2), columns=['A', 'B']).cumsum()

my_plotly_view = PlotlyView(df.iplot(asFigure=True))

context = {'plotly_view_input': my_plotly_view}

Template Code:

python
{% load tethys_gizmos %}

{% gizmo plotly_view_input %}

More examples:

python
import numpy as np
import pandas as pd

np.random.seed(1)

# Scatter
scatter_plot = PlotlyView([
    go.Scatter(
        y=np.random.randn(500),
        mode='markers',
        marker=dict(
            size=16,
            color=np.random.randn(500), #set color equal to a variable
            colorscale='Viridis', # one of plotly colorscales
            showscale=True
        )
    )
])

# Line
N = 100
random_x = np.linspace(0, 1, N)
random_y0 = np.random.randn(N) + 5
random_y1 = np.random.randn(N)
random_y2 = np.random.randn(N) - 5

line_plot = PlotlyView([
    go.Scatter(
        x=random_x, y=random_y0,
        mode='markers',
        name='markers'
    ),
    go.Scatter(
        x=random_x, y=random_y1,
        mode='lines+markers',
        name='lines+markers'
    ),
    go.Scatter(
        x=random_x, y=random_y2,
        mode='lines',
        name='lines'
    )
])

# Pie
pie_plot = PlotlyView([
    go.Pie(
        labels=['Oxygen','Hydrogen','Carbon_Dioxide','Nitrogen'],
        values=[4500, 2500, 1053, 500]
    )
])

# Bar
years = [1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
         2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012]

fig = go.Figure()
fig.add_trace(go.Bar(
    x=years,
    y=[219, 146, 112, 127, 124, 180, 236, 207, 236, 263,
        350, 430, 474, 526, 488, 537, 500, 439],
    name='Rest of world',
    marker_color='rgb(55, 83, 109)'
))
fig.add_trace(go.Bar(
    x=years,
    y=[16, 13, 10, 11, 28, 37, 43, 55, 56, 88, 105, 156, 270,
        299, 340, 403, 549, 499],
    name='China',
    marker_color='rgb(26, 118, 255)'
))
fig.update_layout(
    title='US Export of Plastic Scrap',
    xaxis_tickfont_size=14,
    yaxis=dict(
        title='USD (millions)',
        titlefont_size=16,
        tickfont_size=14,
    ),
    legend=dict(
        x=0,
        y=1.0,
        bgcolor='rgba(255, 255, 255, 0)',
        bordercolor='rgba(255, 255, 255, 0)'
    ),
    barmode='group',
    bargap=0.15, # gap between bars of adjacent location coordinates.
    bargroupgap=0.1 # gap between bars of the same location coordinate.
)
bar_chart = PlotlyView(fig)

# Time series
timeseries_df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
timeseries_fig = px.line(
    timeseries_df,
    x='Date',
    y='AAPL.High',
    title='Time Series with Range Slider and Selectors'
)

timeseries_fig.update_xaxes(
    rangeslider_visible=True,
    rangeselector=dict(
        buttons=list([
            dict(count=1, label="1m", step="month", stepmode="backward"),
            dict(count=6, label="6m", step="month", stepmode="backward"),
            dict(count=1, label="YTD", step="year", stepmode="todate"),
            dict(count=1, label="1y", step="year", stepmode="backward"),
            dict(step="all")
        ])
    )
)
time_series_plot = PlotlyView(timeseries_fig)

# Heat map
heat_x = np.random.randn(500)
heat_y = np.random.randn(500)+1

heat_fig = go.Figure(go.Histogram2d(
    x=heat_x,
    y=heat_y
))
heat_map = PlotlyView(heat_fig)

context = {
    'scatter_plot': scatter_plot,
    'line_plot': line_plot,
    'pie_plot': pie_plot,
    'bar_chart': bar_chart,
    'time_series_plot': time_series_plot,
    'heat_map': heat_map,
}

Template Code:

python
{% load tethys_gizmos %}

{% gizmo scatter_plot %}
{% gizmo line_plot %}
{% gizmo pie_plot %}
{% gizmo bar_chart %}
{% gizmo time_series_plot %}
{% gizmo heat_map %}

AJAX

Often dynamically loading in plots can be useful. Here is a description of how to do so with PlotlyView.

Note

In order to use this, you will either need to use a PlotlyView gizmo on the main page or register the dependencies in the main html template page using the import_gizmo_dependency tag with the plotly_view name in the import_gizmos block.

For example:

python
{% block import_gizmos %}
    {% import_gizmo_dependency plotly_view %}
{% endblock %}

Three elements are required:

  1. A controller for the AJAX call with a PlotlyView gizmo.

python
from datetime import datetime
import plotly.graph_objs as go
from tethys_sdk.gizmos import PlotlyView
from tethys_sdk.routing import controller


@controller(name='plotly_ajax', url='app-name/plotly')
def plotly_ajax(request):
    """
    Controller for the plotly ajax request.
    """
    x = [datetime(year=2013, month=10, day=04),
         datetime(year=2013, month=11, day=05),
         datetime(year=2013, month=12, day=06)]

    my_plotly_view = PlotlyView([go.Scatter(x=x, y=[1, 3, 6])])

    context = {'plotly_view_input': my_plotly_view}

    return render(request, 'app_name/plotly_ajax.html', context)
  1. A template for with the tethys gizmo (e.g. plotly_ajax.html)

html+django
{% load tethys_gizmos %}

{% gizmo plotly_view_input %}
  1. The AJAX call in the javascript

javascript
$(function() { //wait for page to load

    $.ajax({
        url: 'plotly',
        method: 'GET',
        data: {
            'plot_height': 500, //example data to pass to the controller
        },
        success: function(data) {
            // add plot to page
            $("#plotly_plot_div").html(data);

            //NOTE: IF USING MODAL/MESSAGE BOX NEED A TIMEOUT BEFORE DISPLAY
            //$('#modal_div').modal('show');
            //setTimeout(function(){
            //    $("#modal_div").find('.modal-body').html(data);
            //}, 100);

        }
    });

});