Skip to content

Commit 75548ce

Browse files
committed
a much more general script that allows for the number of bins to change
1 parent 4de1fef commit 75548ce

File tree

1 file changed

+124
-97
lines changed

1 file changed

+124
-97
lines changed

figures/intro/integrals.py

Lines changed: 124 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -18,159 +18,186 @@ def f(x):
1818

1919

2020

21-
N_fine = 200
22-
N_bins = 4
21+
def plot_base(xp, fp, xfine, a, b, label_mid=False):
2322

24-
xmin = 0.0
25-
xmax = 2.0
23+
fmax = fp.max()
2624

27-
x = np.linspace(xmin, xmax, N_fine)
25+
for xl in xp:
26+
plt.plot([xl,xl], [0.0, 1.2*fmax], ls="--", color="0.5", zorder=-1)
2827

29-
xp = np.linspace(xmin, xmax, N_bins+1)
30-
fp = f(xp)
28+
plt.scatter(xp, fp, marker="o", color="r", zorder=100)
3129

32-
# integral range
33-
a = 0.5
34-
b = 1.5
30+
plt.figtext(0.9, 0.05, '$x$', fontsize=20)
31+
plt.figtext(0.1, 0.9, '$y$', fontsize=20)
3532

33+
ax = plt.gca()
3634

35+
ax.spines['right'].set_visible(False)
36+
ax.spines['top'].set_visible(False)
37+
ax.xaxis.set_ticks_position('bottom')
3738

39+
if label_mid:
40+
ax.set_xticks((a, (a+b)/2, b))
41+
ax.set_xticklabels(('$a$', r'$\frac{(a+b)}{2}$', '$b$'))
42+
else:
43+
ax.set_xticks((a, b))
44+
ax.set_xticklabels(('$a$', '$b$'))
3845

39-
#---------------------------------------------------------------------
40-
# rectangle method
41-
#---------------------------------------------------------------------
42-
plt.plot(x, f(x), "r", linewidth=2)
43-
plt.ylim(ymin = 0)
46+
ax.set_yticks([])
4447

45-
ax = plt.gca()
48+
plt.plot(xfine, f(xfine), "r", linewidth=2)
4649

50+
plt.xlim(np.min(xfine), 1.05*np.max(xfine))
51+
plt.ylim(ymin = 0)
4752

48-
for x1, x2 in [(a, (a+b)/2), ((a+b)/2, b)]:
4953

50-
# shade region
51-
fl = f(x1)
5254

53-
verts = [(x1, 0), (x1, fl), (x2, fl), (x2, 0)]
54-
ax.add_patch(Polygon(verts, facecolor="0.8", edgecolor="k"))
55+
def rectangle(xp, fp, a, b):
5556

57+
ax = plt.gca()
5658

57-
fmax = fp.max()
59+
for n in range(len(xp)-1):
5860

59-
for xl in xp:
60-
plt.plot([xl,xl], [0.0, 1.2*fmax], ls="--", color="0.5", zorder=-1)
61+
xl = xp[n]
62+
xr = xp[n+1]
6163

62-
plt.scatter(xp, fp, marker="o", color="r", zorder=100)
64+
print(xl)
65+
fl = fp[n]
6366

64-
plt.figtext(0.9, 0.05, '$x$', fontsize=20)
65-
plt.figtext(0.1, 0.9, '$y$', fontsize=20)
67+
# shade region
68+
verts = [(xl, 0), (xl, fl), (xr, fl), (xr, 0)]
69+
ax.add_patch(Polygon(verts, facecolor="0.8", edgecolor="k"))
6670

67-
ax.spines['right'].set_visible(False)
68-
ax.spines['top'].set_visible(False)
69-
ax.xaxis.set_ticks_position('bottom')
71+
def trapezoid(xp, fp, a, b):
7072

71-
ax.set_xticks((a, b))
72-
ax.set_xticklabels(('$a$', '$b$'))
73-
ax.set_yticks([])
73+
ax = plt.gca()
7474

75-
plt.xlim(xmin, 1.05*xmax)
75+
for n in range(len(xp)-1):
7676

77-
plt.savefig("rectangle.pdf", bbox_inches="tight")
77+
xl = xp[n]
78+
xr = xp[n+1]
7879

80+
# shade region
81+
fl = f(xl)
82+
fr = f(xr)
7983

80-
#---------------------------------------------------------------------
81-
# trapezoid method
82-
#---------------------------------------------------------------------
83-
plt.clf()
84+
verts = [(xl, 0), (xl, fl), (xr, fr), (xr, 0)]
85+
ax.add_patch(Polygon(verts, facecolor="0.8", edgecolor="k"))
8486

85-
plt.plot(x, f(x), "r", linewidth=2)
86-
plt.ylim(ymin = 0)
87+
def simpsons(xp, fp, a, b):
8788

88-
ax = plt.gca()
89+
ax = plt.gca()
8990

91+
for n in range(0, len(xp)-1, 2):
9092

91-
for x1, x2 in [(a, (a+b)/2), ((a+b)/2, b)]:
93+
# we need to handle the 1 bin case specially
9294

93-
# shade region
94-
f1 = f(x1)
95-
f2 = f(x2)
95+
if len(xp) == 2:
9696

97-
verts = [(x1, 0), (x1, f1), (x2, f2), (x2, 0)]
98-
ax.add_patch(Polygon(verts, facecolor="0.8", edgecolor="k"))
97+
xl = xp[0]
98+
xr = xp[1]
99+
xm = 0.5 * (xl + xr)
99100

100-
fmax = fp.max()
101+
f0 = f(xl)
102+
f1 = f(xm)
103+
f2 = f(xr)
101104

102-
for xl in xp:
103-
plt.plot([xl,xl], [0.0, 1.2*fmax], ls="--", color="0.5", zorder=-1)
105+
else:
106+
f0 = fp[n]
107+
f1 = fp[n+1]
108+
f2 = fp[n+2]
104109

110+
xl = xp[n]
111+
xr = xp[n+2]
105112

106-
ax.add_patch(Polygon(verts, facecolor="0.8"))
113+
delta = 0.5*(xr - xl)
107114

108-
plt.scatter(xp, fp, marker="o", color="r", zorder=100)
115+
A = (f0 - 2*f1 + f2)/(2*delta**2)
116+
B = -(f2 - 4*f1 + 3*f0)/(2*delta)
117+
C = f0
109118

110-
plt.figtext(0.9, 0.05, '$x$', fontsize=20)
111-
plt.figtext(0.1, 0.9, '$y$', fontsize=20)
119+
xsimp = np.linspace(xl, xr, 100)
120+
fsimp = A * (xsimp - xl)**2 + B * (xsimp - xl) + C
112121

113-
ax.spines['right'].set_visible(False)
114-
ax.spines['top'].set_visible(False)
115-
ax.xaxis.set_ticks_position('bottom')
122+
simpvert = list(zip(xsimp, fsimp))
116123

117-
ax.set_xticks((a, b))
118-
ax.set_xticklabels(('$a$', '$b$'))
119-
ax.set_yticks([])
124+
verts = [(xl, 0)] + simpvert + [(xr, 0)]
125+
ax.add_patch(Polygon(verts, facecolor="0.8", edgecolor="k"))
120126

121-
plt.xlim(xmin, 1.05*xmax)
122127

123-
plt.savefig("trapezoid.pdf", bbox_inches="tight")
128+
def main():
124129

130+
N_fine = 200
125131

126-
#---------------------------------------------------------------------
127-
# simpsons method
128-
#---------------------------------------------------------------------
129-
plt.clf()
132+
# the number of bins to divide [a, b]
133+
N_bins = 1
130134

131-
plt.plot(x, f(x), "r", linewidth=2)
132-
plt.ylim(ymin = 0)
135+
xmin = 0.5
136+
xmax = 1.5
133137

134-
ax = plt.gca()
138+
dx_extra = 0.5
135139

140+
# add a bin on each end of the domain outside of the integral
141+
xmin_plot = xmin - dx_extra
142+
xmax_plot = xmax + dx_extra
136143

137-
# shade region -- get the coefficients of the parabola
138-
f0 = f(a)
139-
f1 = f((a+b)/2)
140-
f2 = f(b)
144+
xfine = np.linspace(xmin_plot, xmax_plot, N_fine+2)
141145

142-
delta = 0.5*(b-a)
146+
xp = np.linspace(xmin, xmax, N_bins+1)
143147

144-
A = (f0 - 2*f1 + f2)/(2*delta**2)
145-
B = -(f2 - 4*f1 + 3*f0)/(2*delta)
146-
C = f0
148+
# integral range
149+
a = xmin
150+
b = xmax
147151

148-
xsimp = np.linspace(a,b,100)
149-
fsimp = A*(xsimp-a)**2 + B*(xsimp-a) + C
152+
# function points
153+
fp = f(xp)
150154

151-
simpvert = list(zip(xsimp, fsimp))
152155

153-
verts = [(a, 0)] + simpvert + [(b, 0)]
154-
ax.add_patch(Polygon(verts, facecolor="0.8", edgecolor="k"))
156+
# rectangle method
155157

156-
fmax = fp.max()
158+
plt.clf()
157159

158-
for xl in xp:
159-
plt.plot([xl,xl], [0.0, 1.2*fmax], ls="--", color="0.5", zorder=-1)
160+
plot_base(xp, fp, xfine, a, b)
161+
rectangle(xp, fp, a, b)
160162

161-
plt.scatter(xp, fp, marker="o", color="r", zorder=100)
163+
plt.savefig("rectangle.pdf", bbox_inches="tight")
162164

163-
plt.figtext(0.9, 0.05, '$x$', fontsize=20)
164-
plt.figtext(0.1, 0.9, '$y$', fontsize=20)
165+
# trapezoid method
165166

166-
ax.spines['right'].set_visible(False)
167-
ax.spines['top'].set_visible(False)
168-
ax.xaxis.set_ticks_position('bottom')
167+
plt.clf()
168+
169+
plot_base(xp, fp, xfine, a, b)
170+
trapezoid(xp, fp, a, b)
171+
172+
plt.savefig("trapezoid.pdf", bbox_inches="tight")
173+
174+
175+
# simpsons method
176+
177+
plt.clf()
178+
179+
xp_tmp = list(xp)
180+
fp_tmp = list(fp)
181+
label_mid = False
182+
183+
# if N_bins is 1, we need an extra point for Simpsons
184+
if N_bins == 1:
185+
xp_tmp.append((a + b)/2)
186+
fp_tmp.append(f((a + b)/2))
187+
label_mid = True
188+
189+
plot_base(np.array(xp_tmp), np.array(fp_tmp), xfine, a, b,
190+
label_mid=label_mid)
191+
192+
193+
simpsons(xp, fp, a, b)
194+
195+
plt.savefig("simpsons.pdf", bbox_inches="tight")
196+
197+
198+
199+
if __name__ == "__main__":
200+
main()
169201

170-
ax.set_xticks((a, b))
171-
ax.set_xticklabels(('$a$', '$b$'))
172-
ax.set_yticks([])
173202

174-
plt.xlim(xmin, 1.05*xmax)
175203

176-
plt.savefig("simpsons.pdf",bbox_inches="tight")

0 commit comments

Comments
 (0)