NumPy Tutorial

NumPy ist eine Bibliothek für Python. Ich empfehle Python 3 zu benutzen. Es werden unter Ubuntu folgende Pakete benötigt:

  • python3-matplotlib
  • python3-numpy
  • python3-scipy

Offizielle Dokumentation:

Beispiel: Anpassen einer Gaußfunktion

Gegeben sei die Datei gauss.csv in der $x$ und $y$ Werte stehen. Dies sind die ersten paar Zeilen der Datei:

-5.000000000000000000e+00 6.500006597214588178e-01
-4.989989989989989994e+00 5.909619296200073757e-01
-4.979979979979979987e+00 5.267851553980463786e-01
-4.969969969969969981e+00 4.393687797793060512e-01
-4.959959959959959974e+00 8.199626613472296155e-01

Dazu beginne ich eine neue Textdatei, auswertung.py:

import matplotlib.pyplot as pl
import numpy as np
import scipy.optimize as op

def normal_distribution(x, integral, mean, sigma):
    return integral / np.sqrt(2 * np.pi) / sigma * np.exp(- x**2 / sigma**2)

Mit import numpy as np importierte ich die NumPy Bibliothek unter dem Kurznamen np. Das gleiche mache ich ebenfalls mit der Plotbibliothek matplotlib.

Danach definiere ich die Funktion normal_distribution die einer Gaußfunktion entspricht:

$$N(x; I, \mu, \sigma) := \frac{I}{\sqrt{2\pi} \sigma} \exp\left(-\frac{x^2}{\sigma^2}\right)$$

Dieses Programm kann immer mit python3 auswertung.py ausgeführt werden.

Die Daten können nun wie folgt eingelesen werden:

data = np.loadtxt('gauss.csv')

Dies erstellt ein numpy.array, ein Objekt in dem Arrays beliebiger Größe gespeichert werden können, sowohl 1D als auch 2D. Daraus müssen nun $x$ und $y$ extrahiert werden:

x = data[:, 0]
y = data[:, 1]

Die Syntax mit den […] ist ähnlich wie in C auch. In NumPy ist die Syntax allerdings erweitert, so dass direkt Zeilen und Spalten ausgewählt werden kann. Der erste Index ist die Zeile, der zweite die Spalte. Für alle Elemente gibt es das Symbol :. Die oberen zwei Zeilen Quelltext nehmen also die erste (Index 0) und zweite (Index 1) Spalte aus der Datenmatrix heraus.

Die Funktion curve_fit passt eine beliebige Funktion an die Daten an:

popt, pconv = op.curve_fit(normal_distribution, x, y)

popt ist ein Vektor (Array) mit den Fitparametern, pconv ist die Kovarianzmatrix, aus der die Fehler für den Fit berechnet werden können.

Hier ist popt[0] also die Amplitude der Gaußfunktion, popt[1] der Mittelwert und popt[2] die Standardabweichung.

Für die Fehler der Parameter braucht man noch eine Zeile mehr:

fehler = np.sqrt(pconv.diagonal())

Dies nimmt die Diagonalen Elemente und zieht die Wurzel aus diesen. Das Array fehler enthält in der gleichen Reihenfolge die Fehler.

Das ganze soll jetzt noch in einer Grafik dargestellt werden. Dazu wird matplotlib benutzt:

pl.plot(x, y)

Die Grafik kann jetzt interaktiv angezeigt werden:

pl.show()

Oder gespeichert werden:

pl.savefig('gauss.pdf')

Es können alle üblichen Dateiformate wie .png oder .pdf benutzt werden.

Dies hat jetzt nur die Originaldaten geplottet. Es soll noch die angepasste Funktion geplottet werden. NumPy kann keine Funktion direkt plotten. Man muss erst $x$-Punkte erzeugen, dann die Funktion darauf anwenden um $y = f(x)$ Werte zu erzeugen und dies dann plotten.

fitted_x = np.linspace(np.min(x), np.max(x), 1000)
fitted_y = normal_distribution(fitted_x, *popt)

Diese Zeilen bedürfen einiger Erklärung: linspace erzeugt linear gleichverteilte Punkte zwischen zwei Punkten. Die ersten beiden Parameter sind Start- und Endpunkt, der dritte Parameter die Anzahl der Stützstellen. Ich wähle immer das Minimum und Maximum meiner Eingangsdaten als Endpunkte, auf diese Weise ist der Definitionsbereich genau gleich. 1000 Stützstellen geben immer schön glatte Kurven, 100 ist oft zu wenig. Dies wird als Vektor in fitted_x gespeichert.

Dann wird die Funktion normal_distribution auf den ganzen Vektor fitted_x elementweise angewandt. Es bedarf hier keiner for-Schleife, da NumPy dies im Hintergrund automatisch macht. Das *popt ist kein Pointer, sondern bedeutet in Python, dass die Liste popt „ausgeschüttet" werden soll und die Einträge als einzelne Parameter benutzt werden sollen. Die Funktion normal_distribution erwartet ja vier Parameter, popt enthält die letzten drei. Somit passt das dann.

Dies soll in einen schönen Plot:

# Plotte die Originaldaten. Da es Messdaten sind, werden sie nicht mit
# einer Linie verbunden.
pl.plot(x, y, linestyle='none', marker='.', label='Daten')

# Plotte die Anpassungsfunktion. Diesmal ohne Punkte, aber mit einer Linie.
pl.plot(fitted_x, fitted_y, linestyle='-', marker='none', label='Anpassung')

# Aktiviere das Gitter.
pl.grid(True)

# Setze eine Legende an den optimalen Platz.
pl.legend(loc='best')

# Speichere den Plot als PDF.
pl.savefig('anpassung.pdf')

# Setze die Plot-Umgebung zurück. Dies ist wichtig, weil mehrere ``plot()``
# Befehle in einen Plot gehen, wie oben schon benutzt.
pl.clf()

Wichtige Funktionen

NumPy

Diese Funktionen können mit np. benutzt werden.

array([1, 2, 3])

Erzeugt aus einer Liste ein NumPy Array.

linspace(min, max, anzahl)

Erzeugt eine Liste mit Stützstellen.

sqrt(x), exp(x), pi, sin(x)

Normale Mathematikfunktionen, die direkt auf NumPy Arrays angewandt werden können und so elementweise angewandt.

Matplotlib

Diese Funktionen können mit pl. benutzt werden.

plot(x, y)

Plottet einfache Punkte. Es gibt noch sehr viele Extraoptionen, die man noch angeben kann, zum Beispiel linestyle, marker, label. Siehe plot Dokumentation.

errorbar(x, y, yerr, xerr)

Plottet Punkte mit Fehlerbalken. errorbar Dokumentation

set_xscale('log')

Setzt die $x$-Achse auf logarithmisch.

set_yscale('log')

Setzt die $y$-Achse auf logarithmisch.

legend(loc='best')

Aktiviert die Legende.