# invisible
lines = open("img_resolution.txt").readlines()
resolution = lines[0].strip()
if resolution != "default":
import matplotlib as mpl
mpl.rcParams['figure.dpi'] = int(resolution)
WEBOFF
Eine Konturlinie oder Isolinie einer Funktion aus zwei Variablen ist eine Kurve entlang des konstanten Wertes der Funktion. Es ist ein Querschnitt des dreidimensionalen Graphen der Funktion f(x,y) parallel zur x,y-Ebene.
Konturlinien werden beispielsweise in der Geographie oder Meteorologie benutzt. In der Kartographie verbindet eine Konturlinie die Punkte gleicher Höhe über einem bestimmten Level, wie z.B. der mittlere Meeresspiegel
Allgemeiner können wir also sagen, dass eine Konturlinie einer Funktion mit zwei Variablen eine Kurve ist, die Punkte mit gleichen Werten verbindet.
Erstellen eines Maschengitters
Ein Maschengitter (Meshgrid) ist ein rechteckiges Gitter (Datengitter), was aus zwei eindimensionalen Arrays erzeugt wird, d.h. den x-Werten und den y-Werten. Im weiteren Verlauf dieses Kapitels werden wir nochmals auf die Funktion meshgrid
und ihre Alternativen zurückkommen.
WEBOFF
import numpy as np
xlist = np.linspace(-3.0, 3.0, 3)
ylist = np.linspace(-3.0, 3.0, 4)
X, Y = np.meshgrid(xlist, ylist)
print(xlist)
print(ylist)
print(X)
print(Y)
WEBOFF
import numpy as np
xlist = np.linspace(-3.0, 3.0, 3)
ylist = np.linspace(-3.0, 3.0, 4)
X, Y = np.meshgrid(xlist, ylist)
Z = np.sqrt(X**2 + Y**2)
print(Z)
Aus den Daten erzeugen wir nun den Konturplot:
import matplotlib.pyplot as plt
plt.figure()
cp = plt.contour(X, Y, Z)
plt.clabel(cp, inline=True,
fontsize=10)
plt.title('Konturplot')
plt.xlabel('x (cm)')
plt.ylabel('y (cm)')
plt.show()
Unser Konturplot sieht sehr kantig aus, weil unser Maschengitter nur aus 12 Punkten besteht. Im Folgenden verfeinern wir unser Maschengitter:
import numpy as np
import matplotlib.pyplot as plt
xlist = np.linspace(-3.0, 3.0, 100)
ylist = np.linspace(-3.0, 3.0, 100)
X, Y = np.meshgrid(xlist, ylist)
Z = np.sqrt(X**2 + Y**2)
plt.figure()
cp = plt.contour(X, Y, Z)
plt.clabel(cp, inline=True,
fontsize=10)
plt.title('Konturplot')
plt.xlabel('x (cm)')
plt.ylabel('y (cm)')
plt.show()
import matplotlib.pyplot as plt
plt.figure()
cp = plt.contour(X, Y, Z, colors='black', linestyles='dashed')
plt.clabel(cp, inline=True,
fontsize=10)
plt.title('Konturplot')
plt.xlabel('x (cm)')
plt.ylabel('y (cm)')
plt.show()
import numpy as np
import matplotlib.pyplot as plt
xlist = np.linspace(-3.0, 3.0, 100)
ylist = np.linspace(-3.0, 3.0, 100)
X, Y = np.meshgrid(xlist, ylist)
Z = np.sqrt(X**2 + Y**2)
plt.figure()
cp = plt.contourf(X, Y, Z)
plt.colorbar(cp)
plt.title('Gefüllter Konturplot')
plt.xlabel('x (cm)')
plt.ylabel('y (cm)')
plt.show()
import numpy as np
import matplotlib.pyplot as plt
xlist = np.linspace(-3.0, 3.0, 100)
ylist = np.linspace(-3.0, 3.0, 100)
X, Y = np.meshgrid(xlist, ylist)
Z = np.sqrt(X**2 + Y**2)
plt.figure()
contour = plt.contour(X, Y, Z)
plt.clabel(contour, colors = 'k', fmt = '%2.1f', fontsize=12)
c = ('#ff0000', '#ffff00', '#0000FF', '0.6', 'c', 'm')
contour_filled = plt.contourf(X, Y, Z, colors=c)
plt.colorbar(contour_filled)
plt.title('Gefüllter Konturplot')
plt.xlabel('x (cm)')
plt.ylabel('y (cm)')
plt.show()
Die Schwellen für die Konturlinien und die Flächen werden automatisch durch contour
und contourf
gesetzt. Diese können auch manuell definiert werden, indem als viertes Argument eine Liste mit Levels übergeben wird.
Konturlinien werden für jeden Wert in der Liste gezeichnet, wenn wir contour
benutzen. Wenn contourf
benutzt wird, so werden die Zwischenräume zwischen den Werten der Liste gefüllt.
import numpy as np
import matplotlib.pyplot as plt
xlist = np.linspace(-3.0, 3.0, 100)
ylist = np.linspace(-3.0, 3.0, 100)
X, Y = np.meshgrid(xlist, ylist)
Z = np.sqrt(X ** 2 + Y ** 2 )
plt.figure()
levels = [0.0, 0.2, 0.5, 0.9, 1.5, 2.5, 3.5]
contour = plt.contour(X, Y, Z, levels, colors='k')
plt.clabel(contour, colors = 'k', fmt = '%2.1f', fontsize=12)
contour_filled = plt.contourf(X, Y, Z, levels)
plt.colorbar(contour_filled)
plt.title('Plot mit individuellen Schwellen')
plt.xlabel('x (cm)')
plt.ylabel('y (cm)')
plt.show()
Andere Grids
Wir hatten bereits die NumPy-Funktion meshgrid
kennengelernt. NumPy enthält aber noch zwei weitere wichtige Funktionen zur Erzeugung von gitterähnlichen Strukturen:
ogrid
mgrid
Meshgrid genauer
Die Aufgabe von meshgrid
besteht darin, wie wir gesehen hatten, aus zwei eindimensionalen Koordinatenvektoren eine zweidimensionale Koordinatenmatrix zu erzeugen. Im allgemeinen Fall kann man aus n
eindimensionalen Array-ähnlichen Strukturen ein n
-dimensionales Array zur vektorisierten Auswertung von n
-dimensionalen Vektorfeldern über einem n
-Gitter erzeugen.
Man könnte eine Gitterstruktur (englisch "grid") auch ohne meshgrid
erzeugen. Im folgenden Beispiel erzeugen wir ein Gitter G mit den Werten 0, 1, 2 als x- und als y-Werte:
n = 3
X, Y = np.zeros((n, n), np.int8), np.zeros((n, n), np.int8)
for row in range(0, n):
for col in range(0, n):
X[row, col] = col
Y[row, col] = row
print(X)
print(Y)
Das $(3, 3)$-Gitter entspricht den Paarungen der entsprechenden Komponenten aus den Arrays $X$ und $Y$, also $X[i, j]$ gepaart mit $Y[i, j]$ mit $0 <= i <= 2$ und $0 <= j <= 2$. Mit einem Plot können wir dieses Gitter sichtbar machen:
import matplotlib.pyplot as plt
import numpy as np
plt.plot(X, Y, marker='o', color='k', linestyle='none')
plt.xticks(range(-1, n+1))
plt.yticks(range(-1, n+1))
plt.show()
Dies war der umständliche direkte Weg, und mit meshgrid
geht es deutlich schneller und leichter:
import matplotlib.pyplot as plt
import numpy as np
n = 3
x_values = np.arange(0, n)
y_values = np.arange(0, n)
X, Y = np.meshgrid(x_values, y_values)
plt.plot(X, Y, marker='o', color='k', linestyle='none')
plt.xticks(range(-1, n+1))
plt.yticks(range(-1, n+1))
plt.show()
Im gewissen Sinne ist meshgrid
überflüssig, da man das gleiche Resultat auch mittels Broadcasting erreichen kann:
import matplotlib.pyplot as plt
import numpy as np
n = 3
x_values = np.arange(0, n)
y_values = np.arange(0, n)
# meshgrid mit broadcasting:
X = np.ones((n, 1)) * x_values
Y = y_values.reshape((n, 1)) * np.ones((1, n))
plt.plot(X, Y, marker='o', color='k', linestyle='none')
plt.xticks(range(-1, n+1))
plt.yticks(range(-1, n+1))
plt.show()
Wir hatten mit meshgrid
eine quadratische Gitterstruktur erzeugt. Selbstverständlich können wir auch beliebige rechteckige Strukturen erzeugen:
import matplotlib.pyplot as plt
import numpy as np
n, m = 9, 16
x_values = np.arange(0, n)
y_values = np.arange(0, m)
X, Y = np.meshgrid(x_values, y_values)
plt.plot(X, Y, marker='o', color='k', linestyle='none')
plt.xticks(range(-1, n+1))
plt.yticks(range(-1, m+1))
plt.show()
import numpy as np
n = 3
X_mgrid, Y_mgrid = np.mgrid[0:n, 0:n]
n = 3
X_meshgrid, Y_meshgrid = np.meshgrid(np.arange(0, n),
np.arange(0, n))
print(X_mgrid == Y_meshgrid)
print(Y_mgrid == X_meshgrid)
ogrid
Wir haben sowohl bei meshgrid
als auch bei mgrid
gesehen, dass sich die Werte der beiden erzeugten Matrizen jeweils zeilen- bzw. spaltenweise wiederholen. ogrid
liefert nun jeweils nur einen Zeilen- und einen Spaltenvektor zurück. Dadurch erhalten wir eine speicherschonende Repräsentierung der Werte. Mittels Broadcasting können dann andere Funktionen, die diese Matrizen benötigen, diese implizit erzeugen.
import numpy as np
n = 5
X_ogrid, Y_ogrid = np.ogrid[0:n, 0:n]
print(X_ogrid)
print(Y_ogrid)
Z = np.sqrt(X**2 + Y**2)
plt.figure()
cp = plt.contour(X, Y, Z)
# progr4book
import numpy as np
import matplotlib.pyplot as plt
def sin2d(x, y):
return np.sin(x**3) + np.cos(y**2)
X, Y = np.meshgrid(np.linspace(0, 5*np.pi, 200),
np.linspace(0, 5*np.pi, 200))
Z = sin2d(X, Y)
plt.imshow(Z, origin='lower')
plt.show()
# prog4book
import matplotlib.pyplot as plt
import numpy as np
y, x = np.ogrid[-1:2:100j, -1:1:100j]
plt.contour(x.ravel(),
y.ravel(),
x ** 2 + (y - ((x ** 2) ** (1.0 / 5))) ** 2,
[1],
colors='red')
plt.axis('equal')
plt.show()
# prog4book
import matplotlib.pyplot as plt
import numpy as np
y, x = np.ogrid[-4:5:100j, -4:4:100j]
plt.contourf(x.ravel(),
y.ravel(),
x ** 2 + (y - ((x ** 2) ** (1.0/5))) ** 2,
levels=np.linspace(0, 10, 10),
cmap='Reds')
plt.axis('equal')
plt.show()