Integration of molplotly and Flask for developing chemoinformatics web app #RDKit #molplotly #Flask

Some days ago, @WillMcCorki1 introduced really cool package named molplotly. Thanks for sharing the information. Molplotly is add-on to ploty for rendering molecular image on mouseover like TIBCO Spotfire.

The package(https://github.com/wjm41/molplotly) uses JupyterDash for integrating JupyterNotebook so it’s easy to embed interactive chemoinformatics chart in JupyterNotebook. However, it’s difficult to use the package from outside of jupyternotebook like Flask, Django etc.

I’ve never tried to integrate Dash app to Flask system. So I tried to integrate molplotly and simple dash app to Flask.

Dash use Flask internally, so it’s required little bit tricky way to integrate Dash to Flask.
Here is an example to serve multiple dash app from Flask.

DispatcherMiddleware organizes multiple dash apps. *run_simple is not suitable for production usage only test usage. (I use gunicorn for production ;))

#app.py
from dash import Dash
from werkzeug.middleware.dispatcher import DispatcherMiddleware
from werkzeug.serving import run_simple
import flask

from flask import Flask
from dash import html
server = Flask(__name__)


dash_app1 = Dash(__name__, server = server, url_base_pathname='/dashboard/' )
dash_app2 = Dash(__name__, server = server, url_base_pathname='/reports/')
dash_app1.layout = html.Div([html.H1('Hi there, I am app1 for dashboards')])
dash_app2.layout = html.Div([html.H1('Hi there, I am app2 for reports')])

@server.route('/dashboard/')
def render_dashboard():
    return flask.redirect('/dash1')


@server.route('/reports/')
def render_reports():
    return flask.redirect('/dash2')

app = DispatcherMiddleware(server, {
    '/dash1': dash_app1.server,
    '/dash2': dash_app2.server,
})

run_simple('localhost', 8080, app, use_reloader=True, use_debugger=True)

The app shown above will work ‘python app.py’

OK, lets integrate molploty to Flask.

I changed following line from ‘JupyterDash’ to ‘Dash’ and move outside of code. https://github.com/wjm41/molplotly/blob/bde11c4a4861590e3151a7e5dd481e3c8d84b741/molplotly/main.py#L90

Most of code is borrowed from original molplotly repo. And my changed code is uploaded my repository.

Here is a molploty4flask.py

https://github.com/iwatobipen/molplotly4flask/blob/main/molplotly4flask.py

Next, write chemoinformatics web app with the code.

from dash import Dash
from werkzeug.middleware.dispatcher import DispatcherMiddleware
from werkzeug.serving import run_simple
import flask
from flask import Flask
from flask import render_template
from dash import html
import pandas as pd
import plotly
import plotly.express as px
import json
import molplotly4flask

server = Flask(__name__)

# Following example code is borrowed from molploty repo. Thanks!
# https://github.com/wjm41/molplotly
df_esol = pd.read_csv(
    'https://raw.githubusercontent.com/deepchem/deepchem/master/datasets/delaney-processed.csv')
df_esol['y_pred'] = df_esol['ESOL predicted log solubility in mols per litre']
df_esol['y_true'] = df_esol['measured log solubility in mols per litre']
df_esol['delY'] = df_esol["y_pred"] - df_esol["y_true"]

# This is a simple dash app
dash_app1 = Dash(__name__, server = server, url_base_pathname='/dashboard/' )
dash_app2 = Dash(__name__, server = server, url_base_pathname='/reports/')
dash_app1.layout = html.Div([html.H1('Hi there, I am app1 for dashboards')])
dash_app2.layout = html.Div([html.H1('Hi there, I am app2 for reports')])

# make scatter plot with plotly
fig_scatter = px.scatter(df_esol,
                         x="y_true",
                         y="y_pred",
                         color='delY',
                         title='ESOL Regression (default plotly)',
                         labels={'y_pred': 'Predicted Solubility',
                                 'y_true': 'Measured Solubility',
                                 'delY': 'dY'},
                         width=1200,
                         height=800)

# make chemoinformatics app with molploty ;)
molapp = Dash(__name__, server=server, url_base_pathname='/molplotly_test/')
molapp = app_scatter_with_captions = molplotly4flask.add_molecules(fig=fig_scatter,
                                                    df=df_esol,
                                                    app=molapp,
                                                    smiles_col='smiles',
                                                    title_col='Compound ID',
                                                    caption_cols=['Molecular Weight', 'Number of Rings'],
                                                    caption_transform={'Predicted Solubility': lambda x: f"{x:.2f}",
                                                                       'Measured Solubility': lambda x: f"{x:.2f}",
                                                                       'Molecular Weight': lambda x: f"{x:.2f}"
                                                                       },
                                                    show_coords=True)


@server.route('/plot1/')
def plot1():
    graphJSON = json.dumps(fig_scatter, cls=plotly.utils.PlotlyJSONEncoder)
    return render_template('plot1.html', graphJSON=graphJSON)

@server.route('/molplotly_test/')
def render_molplotly_test():
    print(type(molapp))
    return flask.redirect('/testmol')

@server.route('/dashboard/')
def render_dashboard():
    return flask.redirect('/dash1')


@server.route('/reports/')
def render_reports():
    return flask.redirect('/dash2')

app = DispatcherMiddleware(server, {
    '/dash1': dash_app1.server,
    '/dash2': dash_app2.server,
    '/testmol': molapp.server
})

run_simple('localhost', 8080, app, use_reloader=True, use_debugger=True)

After writing the code, run it.

python app.py

Access http://localhost:8080/plot1/, default plotly chart will be rendered, then access http://localhost:8080/testmol/ will be rendered same chart with tooltip!

Here are gif animation of the web app.

default web app
web app with molplotly

molploty4flask seems work well ;)

By using the approach, it’s easy to integrate rich chemoinformatics graphs to Flask web app I think.

Whole code includes template can be found my repo.

https://github.com/iwatobipen/molplotly4flask

Published by iwatobipen

I'm medicinal chemist in mid size of pharmaceutical company. I love chemoinfo, cording, organic synthesis, my family.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: