pydata

Keep Looking, Don't Settle

plot with online web show: plot in bokeh

It is very easy and convenient to plot in matplotlib which is very powerful for plotting. however, if it is mainly for plotting on the local machine. if want to plot online, then other tools should be utilized.

If you want to show your graph online, you need to do these things:

  1. build your server to let others browse your page
  2. edit the html page to get the input(parameters) and the output(plots)
  3. show the html page on your server

Flask is microframework for python that enables you to build your web pages.

bokeh is used to plot on the webpage

Here an example of drawing the damping vibration is shown. It needs four input values: amplitude, damping factor, frequency and time interval. On the webpage these will be forms for the user to input from keyboard. After input, submit is needed to submit the input value and plot the graphs.

1. build the web frame with falsk

The structure of the folder for this project is like

--app
    --templates
        --view.html
    --static
    --bokeh_in_flask.py

The sample code of bokeh_in_flask.py is

from flask import Flask, render_template, request
from wtforms import Form, FloatField, validators
from math import pi


from numpy import exp, cos, linspace
import bokeh.plotting as plt
import os, re

class InputForm(Form):
    A = FloatField(
        label='amplitude (m)', default=1.0,
        validators=[validators.InputRequired()])
    b = FloatField(
        label='damping factor (kg/s)', default=0,
        validators=[validators.InputRequired()])
    w = FloatField(
        label='frequency (1/s)', default=2*pi,
        validators=[validators.InputRequired()])
    T = FloatField(
        label='time interval (s)', default=18,
        validators=[validators.InputRequired()])


def damped_vibrations(t, A, b, w):
    return A*exp(-b*t)*cos(w*t)

def compute(A, b, w, T, resolution=500):
    """Return filename of plot of the damped_vibration function."""
    t = linspace(0, T, resolution+1)
    u = damped_vibrations(t, A, b, w)

    # create a new plot with a title and axis labels
    TOOLS = "pan,wheel_zoom,box_zoom,reset,save,box_select,lasso_select"
    p = plt.figure(title="simple line example", tools=TOOLS,
                   x_axis_label='t', y_axis_label='y')

    # add a line renderer with legend and line thickness
    p.line(t, u, legend="u(t)", line_width=2)

    from bokeh.resources import CDN
    from bokeh.embed import components
    script, div = components(p)
    head = """
        <link rel="stylesheet"
         href="http://cdn.pydata.org/bokeh/release/bokeh-0.9.0.min.css"
         type="text/css" />
        <script type="text/javascript"
         src="http://cdn.pydata.org/bokeh/release/bokeh-0.9.0.min.js">
        </script>
        <script type="text/javascript">
        Bokeh.set_log_level("info");
        </script>
        """
    return head, script, div


app = Flask(__name__)

@app.route('/vib3', methods=['GET', 'POST'])
def index():
    form = InputForm(request.form)
    if request.method == 'POST' and form.validate():
        for field in form:
            # Make local variable (name field.name)
            exec('%s = %s' % (field.name, field.data))
        result = compute(A, b, w, T)
    else:
        result = None

    return render_template('view.html', form=form,
                           result=result)

if __name__ == '__main__':
    app.run(debug=True)

2. the html page for input and showing plto

this is the sample code of view.html. it will get the input and submit(post method) to the compute funciton and then plot the graph.

<!DOCTYPE html>
<html lang="en">
   <head>
    {{ result[0]|safe }}
</head>
<body>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
  TeX: {
     equationNumbers: {  autoNumber: "AMS"  },
     extensions: ["AMSmath.js", "AMSsymbols.js", "autobold.js"]
  }
});
</script>
<script type="text/javascript" src=
"http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>

This web page visualizes the function \(
u(t) = Ae^{-bt}\sin (w t), \hbox{ for } t\in [0,T]
\).

<form method=post action="">
<table>
  {% for field in form %}
    <tr>
    <td class="name">\( {{ field.name }} \) &nbsp;&nbsp;</td>
    <td>{{ field(size=12) }}</td>
    <td>{{ field.label }}</td>
    {% if field.errors %}
      <td><ul class=errors>
      {% for error in field.errors %}
        <li><font color="red">{{ error }}</font></li>
      {% endfor %}</ul></td>
    {% endif %}
    </tr>
  {% endfor %}
</table>
<p><input type="submit" value="Compute"></form></p>

<p>
{% if result != None %}
<!-- script and div elements for Bokeh plot -->
{{ result[1]|safe }}
{{ result[2]|safe }}
{% endif %}
</p>
</body>
</html>

Reference

  1. Scientific Python in the Browser: it's coming!

  2. Using Flask for Scientific Web Applications