Tutorial: How to embed in a web application server?¶
Important
When using Matplotlib in a web server not use pyplot. You can directly create
figures using the Figure
constructor and render with Plots.render_data()
method.
Prerequisites¶
Beginner level understanding of the Flask framework.
Familiarity with the common plotting commands in Matplotlib.
Flask backend setup¶
Create a new directory in your base directory and then navigate into it
$ mkdir mi_project
$ cd my_project
Next, create a virtual environment.
$ pip install virtualenv
$ virtualenv venv
Once we have created our environment, we must tell the terminal that we want to make use of it and not the global Python environment of the system. Therefore:
We will execute the following command if we are on Linux/Mac:
$ source env/bin/activate
For Windows users:
$ env\Scripts\activate.bat
We will know that the environment is active because the prompt begins with the word “(venv)”, as the following image shows:
(venv) $
To install Flask-Plots we will write the following command in the terminal:
(venv) $ pip install Flask-Plots
One way to have the latest developments is by running:
(venv) $ pip install git+https://github.com/juniors90/Flask-Plots.git
Create a app.py
file such tah conatin the followin script:
from flask import Flask, render_template_string
from flask_plots import Plots
from matplotlib.figure import Figure
import numpy as np
app = Flask(__name__)
plots = Plots(app)
# routes
@app.route("/")
def bar():
# make data
countries = ["Argentina", "Brasil", "Colombia", "Chile"]
peoples = [14, 40, 16, 24]
fig = Figure()
ax = fig.subplots()
ax = plots.bar(fig, countries, peoples)
ax.set_title("Bar Chart")
data = plots.get_data(fig)
return render_template_string(
"""
{% from 'plots/utils.html' import render_img %}
{{ render_img(data=data, alt_img='my_img') }}
""",
data=data
)
if __name__ == "__main__":
app.run(port=5000, debug=True)
Assuming that the working directory contains this script:
Linux/Mac system:
(venv) $ FLASK_APP=app
(venv) $ flask run
Windows
(venv) $ set FLASK_APP=app.py
(venv) $ flask run
Then navigate to the url http://127.0.0.1:5000/
.
You should see the bar plot rendered in png
format.
Arrays and Fields¶
Plotting for arrays of data Z(x, y)
and fields U(x, y)
, V(x, y)
using Matplotlib.
@app.route("/contourf")
def contourf():
# make data
x, y = np.meshgrid(np.linspace(-3, 3, 256), np.linspace(-3, 3, 256))
z = (1 - x / 2 + x ** 5 + y ** 3) * np.exp(-(x ** 2) - y ** 2)
levels = np.linspace(z.min(), z.max(), 7)
fig = Figure()
ax = fig.subplots()
ax = plots.contourf(fig=fig, x=x, y=y, z=z, levels=levels)
ax.set_title("Contourf Chart")
data = plots.get_data(fig)
return render_template_string(
"""
{% from 'plots/utils.html' import render_img %}
{{ render_img(data=data, alt_img='my_img') }}
""",
data=data
)
@app.route("/quiver")
def quiver():
# make data
x_data = np.linspace(-4, 4, 6)
y_data = np.linspace(-4, 4, 6)
x, y = np.meshgrid(x_data, y_data)
u = x + y
v = y - x
# plots:
fig = Figure()
ax = fig.subplots()
ax = plots.quiver(fig, x, y, u, v, quiver_kws={
'color':'C0',
'angles':'xy',
'scale_units':'xy',
'scale':5,
'width':.015
}
)
ax.set_title("Quiver Chart")
data = plots.get_data(fig)
return render_template_string(
"""
{% from 'plots/utils.html' import render_img %}
{{ render_img(data=data, alt_img='my_img') }}
""",
data=data
)
@app.route("/streamplot")
def stremplot():
# make a stream function:
x, y = np.meshgrid(np.linspace(-3, 3, 256), np.linspace(-3, 3, 256))
z = (1 - x/2 + x**5 + y**3) * np.exp(-x**2 - y**2)
# make U and V out of the streamfunction:
v = np.diff(z[1:, :], axis=1)
u = -np.diff(z[:, 1:], axis=0)
# plot:
fig = Figure()
ax = fig.subplots()
ax = plots.streamplot(fig, x[1:, 1:], y[1:, 1:], u, v)
ax.set_title("Streamplot Chart")
data = plots.get_data(fig)
return render_template_string(
"""
{% from 'plots/utils.html' import render_img %}
{{ render_img(data=data, alt_img='my_img') }}
""",
data=data,
)
Statistics¶
@app.route("/boxplot")
def boxplot():
# make data:
np.random.seed(10)
d = np.random.normal((3, 5, 4), (1.25, 1.00, 1.25), (100, 3))
# plot
fig = Figure()
ax = fig.subplots()
ax = plots.boxplot(
fig,
d,
boxplot_kws={
"positions": [2, 4, 6],
"widths": 1.5,
"patch_artist": True,
"showmeans": False,
"showfliers": False,
"medianprops": {"color": "white", "linewidth": 0.5},
"boxprops": {
"facecolor": "C0",
"edgecolor": "white",
"linewidth": 0.5,
},
"whiskerprops": {"color": "C0", "linewidth": 1.5},
"capprops": {"color": "C0", "linewidth": 1.5},
},
)
ax.set(
xlim=(0, 8),
xticks=np.arange(1, 8),
ylim=(0, 8),
yticks=np.arange(1, 8),
)
ax.set_title("Boxplot Chart")
data = plots.get_data(fig)
return render_template_string(
"""
{% from 'plots/utils.html' import render_img %}
{{ render_img(data=data, alt_img='my_img') }}
""",
data=data,
)
@app.route("/errorbar")
def errorbar():
# make data
np.random.seed(1)
x = [2, 4, 6]
y = [3.6, 5, 4.2]
yerr = [0.9, 1.2, 0.5]
# Plot
fig = Figure()
ax = fig.subplots()
ax = plots.errorbar(
fig,
x=x,
y=y,
errorbar_kws={
"yerr": yerr,
"fmt": "o",
"linewidth": 2,
"capsize": 6},
)
ax.set(
xlim=(0, 8),
xticks=np.arange(1, 8),
ylim=(0, 8),
yticks=np.arange(1, 8),
)
ax.set_title("Errorbar Chart")
data = plots.get_data(fig)
return render_template_string(
"""
{% from 'plots/utils.html' import render_img %}
{{ render_img(data=data, alt_img='my_img') }}
""",
data=data,
)
@app.route("/violinplot")
def violinplot():
# make data
np.random.seed(10)
dataset = np.random.normal((3, 5, 4), (0.75, 1.00, 0.75), (200, 3))
# plot:
fig = Figure()
ax = fig.subplots()
vp = plots.violinplot(
fig,
dataset=dataset,
positions=[2, 4, 6],
violinplot_kws={
"widths": 2,
"showmeans": False,
"showmedians": False,
"showextrema": False,
},
)
# styling:
for body in vp["bodies"]:
body.set_alpha(0.9)
ax.set(
xlim=(0, 8),
xticks=np.arange(1, 8),
ylim=(0, 8),
yticks=np.arange(1, 8),
)
ax.set_title("Violin Chart")
data = plots.get_data(fig)
return render_template_string(
"""
{% from 'plots/utils.html' import render_img %}
{{ render_img(data=data, alt_img='my_img') }}
""",
data=data,
)
@app.route("/eventplot")
def eventplot():
# make data:
np.random.seed(1)
x = [2, 4, 6]
d = np.random.gamma(4, size=(3, 50))
# plot:
fig = Figure()
ax = fig.subplots()
ax = plots.eventplot(
fig,
d,
eventplot_kws={
"orientation": "vertical",
"lineoffsets": x,
"linewidth": 0.75,
},
)
ax.set(
xlim=(0, 8),
xticks=np.arange(1, 8),
ylim=(0, 8),
yticks=np.arange(1, 8),
)
ax.set_title("Event Chart")
data = plots.get_data(fig)
return render_template_string(
"""
{% from 'plots/utils.html' import render_img %}
{{ render_img(data=data, alt_img='my_img') }}
""",
data=data,
)
@app.route("/hist2d")
def hist2d():
# plots:
fig = Figure()
ax = fig.subplots()
ax = plots.hist2d(
fig,
x=np.random.normal(size=100),
y=np.random.normal(size=100),
hist2d_kws={"cmap": "inferno"},
)
ax.set_title("Hist2d Plot")
ax.set_xlabel("Label for x")
data = plots.get_data(fig)
return render_template_string(
"""
{% from 'plots/utils.html' import render_img %}
{{ render_img(data=data, alt_img='my_img') }}
""",
data=data,
)
@app.route("/hexbin")
def hexbin():
# make data: correlated + noise
np.random.seed(1)
x = np.random.randn(5000)
y = 1.2 * x + np.random.randn(5000) / 3
# plots:
fig = Figure()
ax = fig.subplots()
ax = plots.hexbin(
fig=fig,
x=x,
y=y,
hexbin_kws={"cmap": "inferno", "gridsize": 20},
)
ax.set(xlim=(-2, 2), ylim=(-3, 3))
ax.set_title("Hexbin Chart")
data = plots.get_data(fig)
return render_template_string(
"""
{% from 'plots/utils.html' import render_img %}
{{ render_img(data=data, alt_img='my_img') }}
""",
data=data
)
@app.route("/pie")
def pie():
# plots:
fig = Figure()
ax = fig.subplots()
ax = plots.pie(
fig,
x=[14, 40, 16, 24],
pie_kws={
"labels": ["Argentina", "Brasil", "Colombia", "Chile"],
"radius": 3,
"center": (4, 4),
"wedgeprops": {"linewidth": 1, "edgecolor": "white"},
"frame": True,
},
)
ax.set(
xlim=(0, 8),
xticks=np.arange(1, 8),
ylim=(0, 8),
yticks=np.arange(1, 8),
)
ax.set_title("Pie Chart")
data = plots.get_data(fig)
return render_template_string(
"""
{% from 'plots/utils.html' import render_img %}
{{ render_img(data=data, alt_img='my_img') }}
""",
data=data,
)
Support for two axes¶
@app.route("/two-axes")
def two_axes():
fig = Figure()
fig.set_size_inches(10, 5)
axs = fig.subplots(1, 2)
# Plot 1:
axs[0].plot([-1, 4])
axs[0].set_title("Linear Function")
# Plot 2:
axs[1] = plots.scatter_hist2d(
fig,
x=np.random.normal(size=100),
y=np.random.normal(size=100),
ax=axs[1],
hist2d_kws={"cmap": "inferno"},
scatter_kws={"color": "g"},
)
axs[1].set_title("Scatter Hist")
data = plots.get_data(fig)
return render_template_string(
"""
{% from 'plots/utils.html' import render_img %}
{{ render_img(data=data, alt_img='my_img') }}
""",
data=data,
)