- 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
Last active
September 16, 2020 06:31
-
-
Save anderl80/f2e7f5d4075704ee84a88ffb2578e30a to your computer and use it in GitHub Desktop.
How to setup a Bokeh server in a Cloud Foundry environment
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
web: python app.py |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
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
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! :-)