Nachdem es in Teil 1 erstmal etwas allgemeines Bla zu Python gab, wollen wir uns heute SciPy & Co. zuwenden. Bzw. muss ich jetzt genauer sein, denn eigentlich geht es um PyLab, das vereint die wissenschaftliche Bibliothek SciPy, dazugehörend NumPy zur Arbeit mit Arrays, matplotlib zum Grafiken erzeugen und eine Erweiterung zu IPython, um dynamisch mit einer Python-Konsole zu arbeiten.
PyLab ist noch im Entstehen, aber die Teilpakete sind alle weit entwickelt und (im Vergleich zu den meisten anderen Bibliotheken) gut dokumentiert. Es kann noch ein wenig zu Namensverwirrungen um die Module kommen, aber in neueren Installationen sollte sich durch
from pylab import *
alles notwendige importieren lassen, um mit allen Funktionen zu arbeiten.
Heute wenden wir uns einem der wichtigsten Themen beim Erstellen wissenschaftlicher Texte zu: den bunten Bildchen. Wenn man mal die Bildchen erzeugt hat, hat man meist schon den Großteil der Datenauswertung geschafft, gut, man muss dann noch dazuschreiben was man sieht und die Fehler wegdiskutieren und so 😉
Schauen wir uns vier einfache Beispiele an, denn mit matplotlib lassen sich unschlagbar schnell einfache Plots erzeugen. Als erstes erstellen wir ein Histogramm, dann eine Punkt- und einen Linienplot und schließlich noch einen Kontourplot.
**1. Histogramm**
Nehmen wir also an, wir haben einen Haufen Zahlenwerte und interessieren uns, wie diese verteilt sind. Dazu können wir ein Histogramm erzeugen, das zählt die Werte in eine gegebene Anzahl Kistchen ein (“bins”). Ok, wir bereiten erstmal eine Liste mit allen Zahlenwerten vor. Dazu kann man ein *numpy*-Array nehmen, muss man aber nicht, eine einfache Liste tut es. Sagen wir mal, wir haben eine Datei *daten.txt* in der pro Zeile ein Wert steht. Dann laden wir diese und speichern sie in eine Liste:
from pylab import * datenList = [] # leere Liste f = open("daten.txt") for line in f: line = line.rstrip() datenList.append(float(line))
*rstrip* entfernt leere Zeichen am Anfang und Ende sowie Zeilenumbrüche.
So, jetzt erzeugen wir ein Histogram aus der Liste mit 10 bins:
hist(datenList,10) show()
Das wars? Ja, das wars. Es öffnet sich ein Betrachterfenster mit dem Histogramm, aus dem man es auch abspeichern kann. Mit *savefig(fname)* statt *show* kann man es auch unter dem Dateinamen *fname* abspeichern. Das Grafikformat wird dabei aus der Dateinamen-Endung erkannt. Und so könnte ein Histogramm aussehen:
**2. Punktwolke**
Die häufigsten Daten sollten Funktionswerte sein, also (x,y)-Werte. Sagen wir also, wir haben eine Datei mit einem Haufen unabhängiger Ergebnisse, z.B. von einem Haufen Simulationsläufe mit jeweils leicht unterschiedlichen Bedingungen. Diese wollen wir einlesen und als Punkte darstellen. Dann könnte das z.B. so aussehen:
from pylab import * xList = [] # leere Liste yList = [] f = open("daten.txt") for line in f: line = line.rstrip() parts = line.split() xList.append(float(parts[0])) yList.append(float(parts[1])) plot(xList,yList, 'ro') axis([0,10,0,1]) show()
Unsere Datei listet in jeder Zeile einen x und y-Wert mit Leerzeichen getrennt. *split* teilt einen String auf, ohne Angabe in Klammer automatisch am Leerezeichen. Man könnte z.B. auch an einem Strich trennen mit *split(‘-‘)*. Man erhält eine Liste mit den Stringteilen ohne die Trennzeichen. Also hier ist *parts[0]* der x- und *parts[1]* der y-Wert. Die stecken wir in zwei Listen und die wiederum in *plot(…)*. Der dritte Parameter zu *plot* sorgt für rote Punkte. Eine Liste der möglichen Angaben hier findet sich in der Dokumentation zu plot. Schließlich sorgt *axis* dafür, von wo nach wo die x- und y-Achse gehen sollen, damit auch alle Punkte gut zu sehen sind. So könnte der Plot aussehen:
**3. Linienplot**
Ohne Formatangabe als dritter Parameter würde automatisch eine Linie gezeichnet. Wir wollen jetzt aus zwei Datensätzen einen Plot mit zwei Linien zeichnen. Auch das ist ganz einfach.
from pylab import * def readXYDataFromFile(filename): xList = [] yList = [] f = open(filename) for line in f: line = line.rstrip() parts = line.split() xList.append(float(parts[0])) yList.append(float(parts[1])) return (xList,yList) (xListA, yListA) = readXYDataFromFile("linie1.txt") (xListB, yListB) = readXYDataFromFile("linie2.txt") plot(xListA, yListA, label="blau") plot(xListB, yListB, 'm-.', linewidth=3., label="magenta") legend() show()
Das Einlesen habe ich jetzt in eine Funktion ausgelagert, um es nicht doppelt schreiben zu müssen.
Man sieht, wenn man einfach zweimal hintereinander *plot* aufruft, werden mit dem *show()* beide Plots in ein Bild gezeichnet. Mit *label* lässt sich ein Name festlegen, der später für *legend* verwendet wird. Der zweite plot soll sich unterscheiden, deswegen habe ich ihm nochmal ein Format mitgegeben, *’m-.’ für magenta Strichpunkt-Linie, und auch noch die Liniendicke hochgesetzt. So sieht es dann aus:
**4. Kontourplot**
Und schließlich will ich noch – ganz kurz – den Kontourplot zeigen. Die Voraussetzung dazu ist, das man durch x- und y-Koordinaten die Punkte eines Gitters angibt und dann auf jedem Gitterpunkt einen Wert hat. Diese Werte stellt man farblich codiert da, und der Kontourplot ist eine interpolierte Darstellung die für die ganze Fläche durch Farbbereiche den Werteverlauf kennzeichnet.
from pylab import * N = 20 x = linspace(.0, 1.0, N) y = linspace(.0, 1.0, N) X, Y = meshgrid(x, y) Z = sin(X+0.2) - 2*cos(Y*1.2) contourf(X, Y, Z) colorbar() show()
Auch hier wieder nur ein ganz einfaches Beispiel um das Prinzip zu zeigen, in der Dokumentation finden sich wieder umfangreichere Beispiele. Zunächst brauchen wir jetzt *numpy*-Funktionen. *linspace* erzeugt eine Liste von 20 Werten im Bereich zwischen 0 und 1. So haben wir die x- und y-Aufteilung unseres Gitters. Gut, dass es auch *meshgrid* gibt, das dann dafür die 400 Gitterpunkt koordiniert…
Als Werte hab ich einfach eine Funktion zusammengestöpselt. Python mit PyLab ist clever genug, um automatisch das richtige herauszuwerfen, wenn man die Listen X und Y in die Funktion steckt, nämlich ein 20×20-Feld. Und wieder ist das Plotten simpel! *contourf* erzeugt den gefüllten Kontourplot, will man nur Höhenlinien, verwendet man *contour*. Man übergibt die Gitterkoordinaten in *X, Y* und das Wertefeld in *Z*. Schließlich ruft man noch *colorbar* auf, um den Farbbalken mit dem Wertebereich anzeigen zu lassen. Fertig!
Viele weitere, schönere Beispiele finden sich übrigens z.B. hier. Die Möglichkeiten sind unerschöpflich, und wer noch mehr braucht als diese Arten (z.B. komplizierteres 3D), kann sich z.B. auch mal MayaVi> anschauen.
Kommentare (10)