2.3.4. Visualising complex functions
2.3.4.1. One-dimensional functions
Consider a “normal” plot of \(\sin(t)\):
[1]:
import sympy
sympy.init_printing()
%matplotlib inline
[2]:
t = sympy.Symbol('t')
[3]:
sympy.plot(sympy.sin(t))
[3]:
<sympy.plotting.backends.matplotlibbackend.matplotlib.MatplotlibBackend at 0x113843620>
This allows us to see exactly what the of \(\sin(t)\) is for every value of \(t\). To do this, we need two dimensions: one for the value of \(t\) and one for \(\sin(t)\).
If we want to plot a function of two variables we start needing three dimensions. The following plot shows a “fake” 3d plot. It’s fake because in fact there are only two dimensions available on your computer screen. So we’re already in a bit of trouble when trying to visualise the relationships represented by higher dimensional functions.
[4]:
x, y = sympy.symbols('x, y')
[5]:
f2 = sympy.sin(x) + sympy.cos(y)
[6]:
sympy.plotting.plot3d(f2)
[6]:
<sympy.plotting.backends.matplotlibbackend.matplotlib.MatplotlibBackend at 0x114c0ead0>
We can make up for some of this lack by using colors to represent another axis.
[7]:
import numpy
import matplotlib.pyplot as plt
[8]:
f2numeric = sympy.lambdify((x, y), f2, 'numpy')
[9]:
xx, yy = numpy.mgrid[-10:10:0.1, -10:10:0.1]
[10]:
zz = f2numeric(xx, yy)
[11]:
plt.pcolor(xx, yy, zz)
[11]:
<matplotlib.collections.PolyQuadMesh at 0x11399dfd0>
For transfer functions, we have an even bigger challenge, because we have two input variables (the real and imaginary part of \(s\)) and two output variables (the real and imaginary part of \(G(s)\)). One solution to the problem is to use colors for \(\angle G(s)\) and brightness for \(|G(s)|\). This is known as domain colouring and is supplied by mpmath.cplot.
[12]:
try:
import mpmath
except:
from sympy import mpmath
[13]:
s = sympy.Symbol('s')
G = 1/(s**2 + s + 1)
Gnumeric = sympy.lambdify(s, G)
mpmath.cplot(Gnumeric)
We can get a smoother result by plotting with more points
[14]:
mpmath.cplot(Gnumeric, points=10000)
The roots of the denominator appear as two bright regions.
Another solution is to plot the image of \(G(s)\) as \(s\) goes through a particular path. We will speak more of this when we cover the frequency domain, but have a look at this example. We generate values of \(s\) in a circle of diameter 1 (radius 0.5) around the origin, then plot \(G(s)\) for all these \(s\) values. This is known as the image of \(G(s)\) for these values of \(s\).
[15]:
theta = numpy.linspace(0, 2*numpy.pi) # angles around the circle
s = 0.5*(numpy.cos(theta) + numpy.sin(theta)*1j) # The circle with radius 0.5
Gs = Gnumeric(s)
[16]:
plt.plot(s.real, s.imag)
plt.plot(Gs.real, Gs.imag)
plt.axis('equal');
[ ]: