2

I have the following script:

import numpy as np

def f(x):
    return x**2 + 3

def integration(a, b, n):
    dx = (b - a) / n
    integration = 0
    for i in np.arange(1, n + 1):
        integration += f(a + i * dx)
    integration *= dx
    return integration 

print(integration (0, 5, 10000))

Now, I want to plot the curve of the f(x) in the range described by a and b with integration area beneath it, so I can get something like this:

enter image description here

I know how to do the first part, ie plot the f(x) curve in a specific range:

import matplotlib.pylab as pl

x = np.linspace(0, 5, 10000)

def f(x):
    return x**2 + 3

pl.plot(x, f(x))
pl.xlim([-1, 6])
pl.show()

...but I lack the rest. I'll be grateful for help.

Hannes Ovrén
  • 21,229
  • 9
  • 65
  • 75
bluevoxel
  • 4,978
  • 11
  • 45
  • 63
  • 1
    This is why matplotlib has a (show-case gallery](http://matplotlib.org/gallery.html); it appears the [fill demo](http://matplotlib.org/examples/lines_bars_and_markers/fill_demo.html) or [integral demo](http://matplotlib.org/examples/showcase/integral_demo.html) may provide you with the proper example. –  Dec 08 '14 at 15:14
  • 1
    possible duplicate of [How to shade region under the curve in matplotlib](http://stackoverflow.com/questions/10046262/how-to-shade-region-under-the-curve-in-matplotlib) – Carsten Dec 08 '14 at 15:15
  • @Evert perfect solution. Thank you very much. Just started with Python, so I'm lacking some obvious documentation websites. – bluevoxel Dec 08 '14 at 15:18
  • If you solved it yourself, please create an answer and mark that as accepted. – Hannes Ovrén Dec 08 '14 at 16:09

2 Answers2

4

Thanks to @Evert comment here is a working solution:

'''
According to the rectangle rule.
'''
import numpy as np
import matplotlib.pylab as pl
from matplotlib.patches import Polygon

# Function definition.
def f(x):
    return x ** 2 + 3

# Integration calculation.
def integration(a, b, n):
    dx = (b - a) / n
    integration = 0
    for i in np.arange(1, n + 1):
        integration += f(a + i * dx)
    integration *= dx
    return integration

# Define integral limits.
a, b = 0, 5

# Define x and y arrays.
x = np.linspace(0, 10, 10000)
y = f(x)

# Plot x and y.
fig, ax = pl.subplots()
pl.plot(x, y, 'b', linewidth = 2)
pl.xlim(xmin = -1, xmax = 11)
pl.ylim(ymin = 0)

# Shade area of the integration beneath the f(x) curve.
ix = np.linspace(a, b, 10000)
iy = f(ix)
verts = [(a, 0)] + list(zip(ix, iy)) + [(b, 0)]
poly = Polygon(verts, facecolor = '0.9', edgecolor = '0.5')
ax.add_patch(poly)

# Print equation text.
pl.text(0.5 * (a + b), 60, r"$\int_{a}^{b}f(x)dx=%.2f$" %integration(a, b, 10000),
horizontalalignment = 'center', fontsize = 20)

# Add x and y axes labels.
pl.figtext(0.9, 0.05, '$x$')
pl.figtext(0.1, 0.9, '$y$')

# Remove right and top plot delimeter lines.
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.xaxis.set_ticks_position('bottom')

# Add a and b ticks on x axis.
ax.set_xticks((a, b))
ax.set_xticklabels(('$a=%d$' %a, '$b=%d$' %b))
ax.set_yticks([])

# Show the plot.
pl.show()

enter image description here

bluevoxel
  • 4,978
  • 11
  • 45
  • 63
0

First, consider renaming the variable integration to intresult or something. There may come confusion between the function name and variable name.

As for the question at hand, you can use the pl.plot function multiple times on the same set of axes to create extra lines. As such you can plot two vertical lines (the ones represented by thick black lines in your illustration) with something like the following code:

pl.plot([a,a], [0,f(a)], "k-")
pl.plot([b,b], [0,f(b)], "k-")

In this code, "k-" represents that the plot should be a black (k) line (-). This is a function in matplotlib.pyplot, so I'm not sure if it works with matplotlib.pylab.

Similarly, red points can be created with calls like pl.plot([a], [f(a)], "r."). Again, this applies to pyplot, but may also work for pylab.

As for the area, I don't know of any dedicated area-filling functions. However, you could try line-shading the area with multiple blue vertical lines, by repeatedly calling pl.plot([x,x], [0,f(x)], "b-") for different values of x. It's a messy solution, but one you can try.

Experiment with different functionalities, and consider trying pyplot instead of pylab if any of my solutions do not work.

Johan
  • 343
  • 1
  • 4
  • 13
  • 2
    For the vertical lines I think [`axvline`](http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.axvline) is a better choice. – Hannes Ovrén Dec 08 '14 at 16:08