# Plotting non continuous functions and a real scatter example with Bokeh

I've written a python 3 code using Bokeh. With this code you can learn howto to plot math functions and a scatter plot with regression linear functions in a webpage. The target is how to plot discontinuous functions, linear regression problems in a webpage, and how to separates the different plots in a webpage using Bokeh. A good looking for the webpage is not the target. Another important target is how to plot linear regression using NumPy and SciPy.

Defining my own bokeh configurations with some functions in a Python file:

# -*- coding: utf-8 -*-

"""
Created on Sat May 30 08:57:38 2015

@author: Tobal
"""

__author__ = 'Tobal'
__email__ = 'lopeztobal@gmail.com'
__version__ = '1.0'

from bokeh.embed import components

regression_line = lambda x, slope, intercept: slope * x + intercept

def plot_settings(my_figure, title, xlabel, ylabel, pwidth, pheight, xrange, yrange, legend_space):
my_figure.title = title
my_figure.xaxis.axis_label = xlabel
my_figure.yaxis.axis_label = ylabel
my_figure.plot_width = pwidth
my_figure.plot_height = pheight
my_figure.x_range = xrange
my_figure.y_range = yrange
my_figure.legend.legend_spacing = legend_space

def my_function_plot(my_figure, x, y, legend, line_width, color, alpha):
my_figure.line(
x, y, legend=legend, line_width=line_width, color=color, alpha=alpha)

def asymptote(my_figure, x, y, legend, line_width, line_dash, color, alpha):
my_figure.line(x, y, legend=legend, line_width=line_width,
line_dash=line_dash, color=color, alpha=alpha)

def scatter_plot(my_figure, x, y, legend, line_width, color, alpha):
my_figure.circle(
x, y, legend=legend, line_width=line_width, color=color, alpha=alpha)

def circles_plot(my_figure, x, y, legend, line_width, color, fill_color, alpha):
my_figure.circle(
x, y, legend=legend, line_width=line_width, color=color, fill_color=fill_color, alpha=alpha)

def regr_segment(my_figure, x0, y0, x1, y1, legend, line_width, color, alpha):
my_figure.segment(
x0, y0, x1, y1, legend=legend, line_width=line_width, color=color, alpha=alpha)

def plot_html(myfigure, myfilejs, myclass):
script, div = components(myfigure)
with open(myfilejs, 'wt') as myfile:
script = script.replace('</script>', '')
script = script.replace('<script type="text/javascript">', '')
div = div.replace(
div, 'document.querySelector(".' + myclass + '").innerHTML = ' + "'" + div + "'")
print(script + div, file=myfile)


Now in a different python file I define how to plot an equilateral function, the floor function and the linear regression example using the code above.

# -*- coding: utf-8 -*-
"""
Created on Sat May 30 08:57:38 2015

@author: Tobal
"""

__author__ = 'Tobal'
__email__ = 'lopeztobal@gmail.com'
__version__ = '1.0'

from bokeh.plotting import figure
from bokeh.models import Range1d
from mybokeh import *
import numpy as np
from scipy import stats

f = lambda x: 1. / x

x = np.linspace(-5.0, 5.0, 200)
pos = np.where(np.abs(np.diff(f(x))) >= 10.0)[0]
x = np.insert(x, pos, np.nan)

TOOLS = 'pan, wheel_zoom, box_zoom, reset, save, help'

p = figure(tools=TOOLS)
plot_settings(p, 'Rational Function', 'x', 'f(x)', 500, 500, Range1d(-5, 5), Range1d(-5, 5), 10)

my_function_plot(p, x, f(x), 'f(x)=1/x', 2, 'firebrick', 0.75)
asymptote(p, np.arange(-5, 6), 0, 'y=0', 2, [6, 4], 'navy', 0.75)
asymptote(p, 0, np.arange(-5, 6), 'x=0', 2, [6, 4], 'red', 0.75)

samplex = np.array([2, 2, 3, 3, 4, 4, 4, 5, 5, 5])
sampley = np.array([1, 2, 2, 3, 3, 4, 5, 4, 5, 6])

slope, intercept, r_value, p_value, std_err = stats.linregress(
samplex, sampley)
r_squared = r_value ** 2
slopex, interceptx, r_valuex, p_valuex, std_errx = stats.linregress(
sampley, samplex)
r_squaredx = r_valuex ** 2

p1 = figure(tools=TOOLS)
plot_settings(p1, 'Linear Regression', 'Number Of Rooms', 'Number Of Persons', 500, 500, Range1d(0, 7), Range1d(0, 8), 10)

scatter_plot(p1, samplex, sampley, 'Rooms / People', 2, 'firebrick', 0.75)
legend1 = 'y = {0:2.1f} + {1:2.3f}(x-{2:2.1f})'.format(
np.mean(sampley), slope, np.mean(samplex))
legend2 = 'x = {0:2.1f} + {1:2.3f}(y-{2:2.1f})'.format(
np.mean(samplex), slopex, np.mean(sampley))
regr_segment(p1, samplex[0], regression_line(samplex[0], slope, intercept), samplex[-1], regression_line(samplex[-1], slope, intercept), legend1, 2, 'navy', 0.75)
regr_segment(p1, sampley[0], regression_line(sampley[0], slopex, interceptx), sampley[-1], regression_line(sampley[-1], slopex, interceptx), legend2, 2, 'green', 0.75)

p2 = figure(tools=TOOLS)
abcisa = np.linspace(-7.0, 7.0, 1000)
pos = np.where(np.abs(np.diff(np.floor(abcisa))) >= 1.0)[0] + 1
abcisa = np.insert(abcisa, pos, np.nan)
igual = np.arange(-7, 7, 1)
igual_mas_uno = igual + np.ones(7 - (-7), np.int)
plot_settings(p2, 'Floor Function', 'x', 'y', 500, 500, Range1d(-7, 7), Range1d(-7, 8), 10)
my_function_plot(p2, abcisa, np.floor(abcisa), 'f(x)', 2, 'blue', 0.75)
circles_plot(p2, igual, igual, '', 2, 'blue', 'blue', 0.75)
circles_plot(p2, igual_mas_uno, igual, '', 2, 'blue', 'white', 0.75)

plot_html(p, './js/figures.js', 'myplot')
plot_html(p1, './js/figures1.js', 'myplot1')
plot_html(p2, './js/figures2.js', 'myplot2')


The code creates 3 independent javascripts files, one file for each plot. Finally the html5 code, using Mathjax

<!DOCTYPE html>
<html lang='es'>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'>
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1'>
<meta name='apple-mobile-web-app-capable' content='yes'>
<title>Tests With Bokeh</title>

<body>
<h1> Equilateral Hyperbola And Linear Regression</h1>
<section class='myplot'></section>
<p class='latex_figure_caption'>
The function is $f(x)=\frac{1}{x}$
</p>
<section class='myplot1'></section>
<div class="table-responsive">
<table class="table table-hover table-bordered table-condensed">
<th class="text-center"> Flats Problem</th>
<th class="text-center">$\mu$</th>
<th class="text-center">Slope</th>
<th class="text-center">$R^2\, ( \% )$</th>
<th class="text-center">CorrCoef ( % )</th>
<th class="text-center">p-value</th>
<tbody>
<tr class="text-center">
<th class="text-center">Number Of Rooms</th>
<td>3.7</td>
<td>$m_{xy}=0.644$</td>
<td>77.23 %</td>
<td>87.87 %</td>
<td>0.00081</td>
</tr>
<tr class="text-center">
<th class="text-center">Number Of Persons</th>
<td>3.5</td>
<td>$m_{yx}=1.198$</td>
<td>77.23 %</td>
<td>87.87 %</td>
<td>0.00081</td>
</tr>
</tbody>
</table>
</div>
<h2>Plotting The Floor Function</h2>
<section class='myplot2'></section>
<p class="latex_figure_caption">
$f(x)=\lfloor x \rfloor$
</p>

<script src='./js/jquery.js'></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script src='./js/bokeh.min.js'></script>
<script src='./js/figures.js'></script>
<script src='./js/figures1.js'></script>
<script src='./js/figures2.js'></script>

<script type='text/x-mathjax-config'>
MathJax.Hub.Config({
tex2jax: {inlineMath: [['$','$'],['\$$','\$$']]}
});
</script>
<script type='text/javascript' src='https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML-full'></script>
</body>
</html>


I've used Anaconda for Bokeh, and Mathjax for LateX expressions. All the code is available in my own GitHub repository, including the CSS file.

This will just be a short review, as I had trouble following along with your code (I think it's just me; your code looks perfectly organized).

Especially with complicated math operations, you want to add documentation to each of your functions/methods so that, as someone is reading your function, if they have any questions, they can just check the documentation.

In your documentation, you should give a summary of what the function does (maybe include some mathematical formula in there if the function is using one), and should tell the type and purpose of each argument being passed into the function.

Also, you should include the type of the return value, and what the return value means.

And, if there are any error return values, you should write in the documentation what each return value means.

Here is an example:

def add(a, b):
"""
* Adds two numbers together and returns the sum
* @param(number) a -- one number to add
* @param(number) b -- another number to add
* @return(number) -- a + b
* @error -- N/A
"""

return a + b