Skip to content

Instantly share code, notes, and snippets.

@anderl80
Last active September 16, 2020 06:31
Show Gist options
  • Save anderl80/f2e7f5d4075704ee84a88ffb2578e30a to your computer and use it in GitHub Desktop.
Save anderl80/f2e7f5d4075704ee84a88ffb2578e30a to your computer and use it in GitHub Desktop.
How to setup a Bokeh server in a Cloud Foundry environment
# Bokeh Server on CF: https://github.com/snowch/bokeh-cloud-foundry
from tornado.ioloop import IOLoop
import yaml
from bokeh.application.handlers import FunctionHandler
from bokeh.application import Application
from bokeh.server.server import Server
from bokeh.themes import Theme
import pandas as pd
import os
# if running locally, listen on port 5000
PORT = int(os.getenv('PORT', '5000'))
HOST = "0.0.0.0"
# this is set in the manifest
try:
ALLOW_WEBSOCKET_ORIGIN = os.getenv("ALLOW_WEBSOCKET_ORIGIN").split(',')
except:
ALLOW_WEBSOCKET_ORIGIN = ['localhost:{0}'.format(PORT)]
io_loop = IOLoop.current()
def get_db_connection():
"""write your DB conn here"""
return conn
def get_data(conn):
data = pd.read_sql("select * from table", conn)
return data
# Create the main plot
def create_map_figure(data):
from colorcet import bgy
from holoviews.operation.datashader import datashade
import geoviews.tile_sources as gts
import holoviews as hv
renderer = hv.renderer('bokeh')
from datashader.geo import lnglat_to_meters
shade_pd = data[["localtime", "from_lon", "from_lat", "to_lon", "to_lat"]]
# datashader and bokeh work with mercator proj
shade_pd.loc[:, 'from_lon'], shade_pd.loc[:, 'from_lat'] = lnglat_to_meters(shade_pd["from_lon"],
shade_pd["from_lat"])
shade_pd.loc[:, 'to_lon'], shade_pd.loc[:, 'to_lat'] = lnglat_to_meters(shade_pd["to_lon"], shade_pd["to_lat"])
plot_width = 800
plot_height = 400
tile_opts = dict(width=plot_width, height=plot_height, xaxis=None, yaxis=None, show_grid=False)
map_tiles = gts.CartoLight.opts(style=dict(alpha=1), plot=tile_opts)
lines = hv.Curve(shade_pd[["from_lon", "from_lat", "to_lon", "to_lat"]], ["from_lon", "from_lat"],
["to_lon", "to_lat"])
routes = datashade(lines, x_sampling=2, y_sampling=2, cmap=bgy, alpha=50)
return map_tiles*routes
def modify_doc(doc):
import holoviews as hv
conn = get_db_connection()
df = get_data(conn)
plot_map = create_map_figure(df)
renderer = hv.renderer('bokeh').instance(mode='server')
plot_map_rendered = renderer.get_plot(plot_map, doc)
doc.add_root(plot_map_rendered.state)
doc.theme = Theme(json=yaml.load("""
attrs:
Figure:
background_fill_color: "#DDDDDD"
outline_line_color: white
toolbar_location: above
height: 500
width: 800
Grid:
grid_line_dash: [6, 4]
grid_line_color: white
"""))
bokeh_app = Application(FunctionHandler(modify_doc))
server = Server(
{'/': bokeh_app},
io_loop=io_loop,
allow_websocket_origin=ALLOW_WEBSOCKET_ORIGIN,
**{'port': PORT, 'address': HOST}
)
server.start()
if __name__ == '__main__':
io_loop.add_callback(server.show, "/")
io_loop.start()
  • Execute cf push in directory where manifest.yml is
  • Of course you can use pip install with the buildpack, then you need a requiremens.txt instead of environment.yml see cf python buildpack docs
name: appname
channels:
- your_channels_here
- nodefaults
dependencies:
- python=3.6.7
- bokeh=1.2.0
- holoviews=1.12.3
- geoviews=1.6.2
- datashader=0.7.0
- pandas=0.24.2
- tornado=6.0.2
applications:
- name: appname
memory: 2G
disk_quota: 3G
buildpacks:
- python_buildpack
routes:
- route: yourroute.domain.de
env:
CONDA_SSL_VERIFY: /etc/ssl/certs/ca-certificates.crt
ALLOW_WEBSOCKET_ORIGIN: "yourroute.domain.de:80,yourroute.domain.de:443"
web: python app.py
attrs:
Figure:
background_fill_color: "#DDDDDD"
outline_line_color: white
toolbar_location: above
height: 500
width: 800
Grid:
grid_line_dash: [6, 4]
grid_line_color: white
@anderl80
Copy link
Author

Building the geo packages with pip is always a bit of a struggle.. This SO-post suggessts that you first install a few Ubuntu packages in order that pip can build the geo-packages. That's why I used conda here (pre-built packages available), when I remember correctly you just need to provide that environment.yml, then the build-pack automatically switches to conda.

Good luck! :-)

@sameerCoder
Copy link

Hi Anderl80,
I too facing the same issue,
I want to make my bokeh plot dynamic after embedding with flask,
I have used the component, as we know component is not used for making dynamic in nature.
Can you please look into below link minimal example, how i can convert this component code to IO torando code format.
Kindly guide me little bit , I will really appreciate your this help,

https://github.com/sameerCoder/component_static_PanelPlot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment