2
votes

I'm building my first web application using Flask. The concept of the web app is to manipulate and visualize data using Pandas and Bokeh. All of this has been relatively straight forward.

Now I'm at a point where I'm plotting information on a map of New York using GMapPlot. When I use output_file to show the plot I get the expected result.

expected enter image description here

However when I try to return the plot to my own html template the map is empty.

actual enter image description here Here's my .py file (apologies for the messy code).

import pandas as pd
import datetime
from flask import render_template, request
from web_app.app import app
from bokeh.io import output_file, show
from bokeh.embed import components
from bokeh.models import (
    GMapPlot, GMapOptions, ColumnDataSource, Circle, DataRange1d, PanTool, WheelZoomTool, BoxSelectTool
)

@app.route('/heatmap', methods=['GET', 'POST'])
def generate_heatmap():
    date1 = datetime.datetime.strptime(request.form['startFilter'],"%Y-%m-%d").date()
    date2 = datetime.datetime.strptime(request.form['stopFilter'], "%Y-%m-%d").date()
    date2 += datetime.timedelta(days=1)
    date_start = str(date1)
    date_stop = str(date2)

    df = pd.read_csv("...", sep=",")
    df = df.set_index(['starttime'])
    df = df.loc[date_start:date_stop]

    start_lats = pd.Series(df['start station latitude']).unique()
    stop_lats = pd.Series(df['end station latitude']).unique()
    start_long = pd.Series(df['start station longitude']).unique()
    stop_long = pd.Series(df['end station longitude']).unique()

    lats = start_lats.tolist() + stop_lats.tolist()
    long = start_long.tolist() + stop_long.tolist()

    map_options = GMapOptions(lat=40.741557, lng=-73.990467, map_type="roadmap", zoom=11)
    plot = GMapPlot(
    x_range=DataRange1d(), y_range=DataRange1d(), map_options=map_options, title="NYC"
    )
    source = ColumnDataSource(
        data=dict(
            lat=lats,
            lon=long,
        )
    )

    circle = Circle(x="lon", y="lat", size=8, fill_color="blue", fill_alpha=0.8, line_color=None)
    plot.add_glyph(source, circle)
    plot.add_tools(PanTool(), WheelZoomTool(), BoxSelectTool())
    output_file("gmap_plot.html")
    show(plot)
    script, div = components(plot)
    return render_template('heatmap.html', script = script, div = div)

and my HTML

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Heatmap</title>
        <link rel="stylesheet" href="http://cdn.bokeh.org/bokeh/release/bokeh-0.11.1.min.css"    type="text/css" />
        <script type="text/javascript" src="http://cdn.bokeh.org/bokeh/release/bokeh-0.11.1.min.js"></script>
        {{ script | safe }}
    </head>
        <body>
            <div class='bokeh'>
                {{ div | safe }}
            </div>
        </body>

1
You might be seeing the issue seen here: github.com/bokeh/bokeh/issues/3737 - Alex

1 Answers

0
votes

I'm a beginner with both these tools, but I put them to work by doing:

from web_app.app import app
from flask import render_template
from bokeh.embed import file_html
from bokeh.plotting import figure
from bokeh.resources import CDN

@app.route('/example', methods=['GET'])
def example():

    plot = figure()
    plot.circle([1,2], [3,4])

    html = file_html(plot, CDN)

    return render_template('whatever.html', plot=html)

Then, using Jinja2 in the template:

{{ plot|safe }}