3
\$\begingroup\$

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'>
    <head>
        <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>

        <link rel='shortcut icon' href='./img/favicon.ico'/>

        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css">
        <link href='./css/bokeh.min.css' rel='stylesheet'>
        <link href='./css/styles.css' rel='stylesheet'>

    </head>
    <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">
            <thead>
                <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>
            </thead>
            <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.

\$\endgroup\$
1
\$\begingroup\$

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).


Add some documentation!

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
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.