-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathintegrals.py
More file actions
124 lines (93 loc) · 4.61 KB
/
Copy pathintegrals.py
File metadata and controls
124 lines (93 loc) · 4.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import base64
from flask import Blueprint, render_template, jsonify
import scipy as sp
import scipy.integrate
import numpy as np
import cexprtk
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
import io
from flask_wtf import FlaskForm
from wtforms.fields import *
import wtforms.validators as validators
from expression_wrapper import ExpressionWrapper
integral_blueprint = Blueprint('integrals', __name__)
def _get_function_from_math_string(math_str, parameters=None):
if parameters is None:
parameters = ['x']
return ExpressionWrapper(math_str, parameters)
def create_riemman_figure(func, P, T, dt, a, b, n):
fig = Figure()
axis = fig.add_subplot(1, 1, 1)
# Plot the function values at the chosen points, and the rectangles
axis.plot(T, func(T), '.', markersize=10)
axis.bar(P[:-1], func(T), width=dt, alpha=0.2, align='edge', edgecolor='black')
# Now plot the "true" curve of the function
x = np.linspace(a, b, n * 100) # we take finer spacing to get a "smooth" graph
y = func(x)
axis.plot(x, y)
axis.axis('off')
return fig
def create_darboux_figure(func, P, dt, a, b, n):
fig = Figure()
axis = fig.add_subplot(1, 1, 1)
lower_darboux = func.get_minimum_for_partition(P)
upper_darboux = func.get_maximum_for_partition(P)
# Plot the function values at the chosen points, and the rectangles
axis.bar(P[:-1], lower_darboux, width=dt, alpha=0.2, align='edge', linewidth=0.8, color='blue', edgecolor='blue')
axis.bar(P[:-1], upper_darboux, width=dt, alpha=0.2, align='edge', linewidth=0.8, color='red', edgecolor='red')
# Now plot the "true" curve of the function
x = np.linspace(a, b, n * 100) # we take finer spacing to get a "smooth" graph
y = func(x)
axis.plot(x, y)
axis.axis('off')
return fig
def get_encoded_image(fig):
output = io.BytesIO()
FigureCanvas(fig).print_png(output)
encoded_riemann_img = base64.b64encode(output.getvalue()).decode('utf-8').replace('\n', '')
output.close()
return encoded_riemann_img
class PlotForm(FlaskForm):
function_text = StringField(u"Function to plot", [validators.required()])
a = FloatField(u"Start", default=0)
b = FloatField(u"End", default=1)
n = IntegerField(u"Partition count", [validators.number_range(min=1)], default=20)
error_method_text = StringField(u"Error method", [validators.optional()])
submit = SubmitField("Plot")
@integral_blueprint.route("/")
def infi_integral():
return render_template('index.html', form=PlotForm())
@integral_blueprint.route('/get_plot', methods=['POST'])
def get_plot_post():
form = PlotForm()
if form.validate_on_submit():
return get_plot(form.function_text.data, form.error_method_text.data, np.float32(form.a.data),
np.float32(form.b.data), np.int32(form.n.data))
return jsonify(data=form.errors)
def get_plot(function_txt, error_method_txt, a, b, n):
try:
_function = _get_function_from_math_string(function_txt)
except cexprtk.ParseException as e:
return jsonify({'error': "Parse error {}".format(e)})
P, dt = np.linspace(a, b, n+1, retstep=True) # Standard partition constant width
T = [np.random.rand() * dt + p for p in P[:-1]] # Randomly chosen point
riemann_fig = create_riemman_figure(_function, P, T, dt, a, b, n)
darboux_fig = create_darboux_figure(_function, P, dt, a, b, n)
# Run python's numerical integration function
num_int, err = sp.integrate.quad(_function, a, b) # err is an estimate of the error
r_sum = sum([_function(t) * dt for t in T])
diff = r_sum - num_int
result = {
'riemann_title': 'Riemann sum with n = {} points'.format(int(n)),
'riemann_img': '<img src="data:image/png;base64,{}" />'.format(get_encoded_image(riemann_fig)),
'darboux_title': 'Upper and lower Darboux sums with n = {} points'.format(int(n)),
'darboux_img': '<img src="data:image/png;base64,{}" />'.format(get_encoded_image(darboux_fig)),
'int_result': 'Numercial integration gives {} with possible error of {}'.format(num_int, err),
'diff_result': 'The difference between our Riemann sum and the true value is {}'.format(diff)
}
if len(error_method_txt) > 0:
_error_method_function = _get_function_from_math_string(error_method_txt, ['a', 'b', 'n'])
_error_bound = _error_method_function({'a': a, 'b': b, 'n': n})
result['error_bound'] = 'The error absolute bound is evaluated as {}, diff between bound and actual error {}'.format(_error_bound, _error_bound - abs(diff))
return jsonify(result)