1 BSV MT-B 5, WS 15/16 Kurze Einführung in (I)Python und Matplotlib richard rascher-friesenhausen [email protected] Mit der Programmiersprache Python und dem zusätzlichen Modul Matplotlib steht ein Tool für anspruchsvolle technische und wissenschaftliche Berechnungen und Darstellungen zur Verfügung. Dieser Text stellt einige der für die Veranstaltung BSV wichtigen Python-Befehle zusammen. Wir gehen dabei stets davon aus, dass in Python das Modul ‚Matplotlib‘ geladen wurde. Entweder direkt über from pylab import * oder indirekt durch die Verwendung der IPython Shell mit der pylab Option c:> ipython -pylab IPython mit der pylab Option kann auch über die Start-Leiste unter dem Python-Ordner aufgerufen werden. Diese kurze Tutorial verwendet die Programmiersprache Python unter der IPython Shell, da hier insbesondere die Grafikbefehle der Matplotlib auch interaktiv zu verwenden sind. Die Grafikbefehle spielen (noch) nicht ideal mit der Python IDE ‚IDLE‘ zusammen, weshalb von deren Benutzung abzuraten ist. Die Entwicklungsumgebung ‚Spyder‘ hingegen funktioniert damit gut. Mit pylab stehen einem neben allen mathematischen Funktionen insbesondere Matlab-ähnliche Vektor- und Matrix-Konstrukte und Grafikbefehle zur Verfügung. Weitere Informationen zur Programmiersprache ‚Python‘ findet man im Internet unter der Adresse www.python.org, zu der ‚IPython‘ Shell unter ipython.scipy.org und zur Graphikerweiterung ‚Matplotlib‘ unter matplotlib.sf.net. Eine kurze und empfehlenswerte Einführung in die Programmiersprache Python findet man unter http://starship.python.net/crew/gherman/publications/tut-de/tut-de-21.pdf 1 Erste Python Schritte Wir beginnen, indem wir die IPython Shell über die Startleiste aufrufen. In einem Befehlsfenster erhalten wir folgenden Ausdruck: 2 Python 2.4.3 - Enthought Edition 1.0.0 (#69, Aug 2 2006, 12:09:59) [MSC v.1310 32 bit (Intel)] Type "copyright", "credits" or "license" for more information. IPython ? %magic help object? 0.7.2 – An enhanced Interactive Python. -> Introduction to IPython’s features. -> Information about IPython’s ’magic’ % functions. -> Python’s own help system. -> Details about ’object’. ?object also works, ?? prints more. Welcome to pylab, a matplotlib-based Python environment. For more information, type ’help(pylab)’. In [1]: Wir erhalten Information darüber, welche Version von Python verwendet wird. Darüberhinaus werden Hinweise gegeben, wie man Hilfe zur IPython Shell kommen kann. Zuletzt wird an einem Prompt In [1]: die erste Eingabe erwartet. Wir spielen nun einige häufig verwendete Python-Befehle durch. In [1]: ((42*36) / (10+4) - 110)**3 Out[1]: -8 In [2]: Addition, Subtraktion, Multiplikation und Division wird mit den üblichen Symbolen angegeben. Das Potenzieren verwendet das Symbol **. Aufgabe Probieren Sie die Rechenoperationen selber an einfachen Beispielen aus. Bei der Division darf man nicht durch Null teilen. In [2]: 54/0 –––––––––––––––––––––––––––––––––––––exceptions.ZeroDivisionError Traceback (most recent call last) C:\Dokumente und Einstellungen\richard\Desktop\<ipython console> ZeroDivisionError: integer division or modulo by zero In [3]: Ansonsten bekommt man einen Fehler mit Namen ‚ZeroDivisionError‘. Vorsicht beim Dividieren. Werden zwei ganzzahlige Werte dividiert, so berechnet Python ein ganzzahliges Ergebnis! 3 In [3]: 7/2 Out[3]: 3 Will man das korrekte Ergebnis, so muss mindestens einer der Operanden einen Dezimalpunkt erhalten. Also In [4]: 7./2 Out[4]: 3.5 Typische mathematische Konstanten sind direkt vorhanden: In [5]: pi Out[5]: 3.1415926535897931 In [6]: e Out[6]: 2.7182818284590451 Ebenfalls kann direkt auf verschiedene mathematische Funktionen zugegriffen werden. In [7]: sin(2*pi) Out[7]: -2.4492127076447545e-016 In [8]: cos(0) Out[8]: 1.0 In [9]: tan(pi/4) Out[9]: 0.99999999999999989 Man beachte, dass alle Argumente für die trigonometrischen Funktionen in Bogenmass angegeben werden müssen. Ebenfalls erkennen wir, dass bei den Auswertungen numerische Rundefehler ins Spiel kommen. In [10]: exp(0) Out[10]: 1.0 In [11]: exp(1) Out[11]: 2.7182818284590451 Hilfe zu den Funktionen erhält man in der IPython Shell über In [12]: exp? Type: String Form: Namespace: ufunc <ufunc ’exp’> Interactive 4 Docstring: exp(x) returns array of elementwise e**x. Aufgabe Berechnen Sie die Werte cos(π/2), cot(π/4), log(e) und √ 4. Komplexe Zahlen werden durch Angabe ihres Real- und Imaginärteils definiert. In [13]: 2+2j Out[13]: (2+2j) Hier bezeichnet j die komplexe Einheit. Man beachte, dass kein * Zeichen zwischen der komplexen Einheit und dem Imaginärteil stehen darf. Aufgabe Berechnen Sie exp(jπ) + 1. 2 Python Scripte Alle Rechnungen auf dem Python-Prompt durchzuführen ist nicht immer ganz einfach. Insbsondere bei längeren und komplizierten Berechnungen. Hier ist es sinnvoll, Python-Scripte zu schreiben, also die Befehle in einer Datei zu speichern und sie vollständig von Python abarbeiten zu lassen. Geeignet ist jeder reine ASCII-Editor, etwa der einfache Windows Editor. Oder man verwendet Spyder. Betrachten wir ein einfaches Beispiel. 1 # Volumenberechnung fuer eine Kugel 3 # pi importieren 4 from pylab import pi 6 # Radius einlesen 7 r = input(’Bitte eine Radius eingeben: ’) 9 # Volumen berechnen 10 V = (4./3)*pi*r**3 12 # Ergebnis ausgeben 13 print ’Die Kugel mit Radius %f hat ein Volumen von %f’ % (r,V) kugelvolumen.py 5 Aufgabe Schreiben Sie obiges Programm in eine Datei kugelvolumen.py und probieren Sie es aus. Speichern Sie dazu das Programm in einem Verzeichnis Verz und wechseln Sie in der IPython Shell mit cd Verz in dieses Verzeichnis. Nun können Sie mit run kugelvolumen Ihr Programm laufen lassen. Innerhalb der Entwicklungsumgebung Spyder drücken Sie die Taste F5. Zeilen, die mit einem # eingeleitet werden, sind Kommentarzeilen. In Zeile 2 wird die vordefinierte Konstante π aus dem Modul pylab importiert. In der Zeile 7 wir der Wert für den Radius r vom Benutzer abgefragt. Nun wird in Zeile 10 das Volumen der Kugel berechnet und in 13 zusammen mit dem Radius für den Benutzer ausgegeben. Kommentare werden in der Bearbeitung ignoriert. Sie könnten also weggelassen werden. Aber mit den Kommentaren weiss man, was das Python Script eigentlich macht! 2.1 Kontrollstrukturen In dem Programm kugelvolumen.py wurden die Befehle zeilenweise nacheinander ausgeführt. Manchmal möchte man in einem Programm aber auch verzweigen oder Dinge wiederholen. Dies geschieht in Python vermittels Schleifen und Abfragen. Hierzu auch ein Beispiel. Aufgabe Schreiben Sie das nachfolgende Programm in eine Datei fakultaet.py und probieren Sie es aus. In Zeil 5 wird eine while-Schleife begonnen, die solange durchlaufen wird, bis der Wert der Variablen ok gleich True ist. Das ist dann der Fall, wenn in N ein Integerwert zwischen 0 und 10 steht. Dies wird sichergestellt in den Zeilen 7 bis 12 durch die if..elif..else Abfrage. In der Berechnung des Fakultätenwertes ab Zeile 14 wird wieder in einer if..elif..else Abfrage die möglichen Berechnungsfälle durchgespielt: 0! = 1, 1! = 1, N ! = 1 · 2 · (N − 1) · N. Dabei durchläuft in der for-Schleife in Zeile 21 die Variable k nacheinander die Werte 2, 3, . . ., N . Die Schleife hört also einen Wert vor N + 1 auf! Welche Befehle zu einer Kontrollstruktur gehören, wird durch Einrückung gekennzeichnet. Aufgabe Machen Sie sich schlau über die Kontrollstrukturen in Python. 2.2 Funktionen Innerhalb von Programmen können Funktionen aufgerufen werden. Das haben wir schon anhand der mathematischen Funktionen zu Beginn gesehen. Und man kann auch eigene Funktionen definieren. Auch dazu ein Beispiel. 6 1 # Berechnung der Fakultaeten 3 # Integer einlesen 4 ok = False 5 while not ok: 6 N = input(’Gebe eine Zahl zwischen 0 und 10 ein: ’) 7 if int(N) != N: 8 print ’Es muss ein Integer sein!’ 9 elif not(0 <= N <= 10): 10 print ’Die Zahl ist ausserhalb des erlaubten Bereiches!’ 11 else: 12 ok = True 14 15 16 17 18 19 20 21 22 # Fakultaet berechnen if N == 0: # trivialer Fall f = 0 elif N == 1: # einfacher Fall f = 1 else: # hier muss man rechnen f = 1 for k in range(2,N+1): f = f*k 24 # Ergebnis ausgeben 25 print ’Die Fakultaet von %d ist %d’ % (N,f) fakultaet.py Aufgabe Schreiben Sie das Programm auf der nächsten Seite in eine Datei gaussian.py und probieren Sie es aus. In den Zeilen 3 bis 18 wird eine Funktion gaussian definiert, welche die Gauss-Funktion an einer Stelle x mit gegebenen Mittelwert mu und Standardabweichung sigma auswertet. Der in der Funktion berechnete Wert y wird in Zeile 18 über return an den Aufrufer der Funktion zurückgegeben. Die Funktion wird ab Zeile 20 getestet. Die Zeilen 4 bis 9 innerhalb der Funktion gaussian sind der „Dokumentationsstring“ der neuen Funktion. Er dient als Hilfetext. Aufgabe Geben Sie einmal help(gaussian) in der Python-Shell ein. 7 1 from pylab import * # insb. fuer sqrt() 3 def gaussian(x,mu,sigma): 4 """Funktion zur Berechnung der Werte auf einer Gauss’schen 5 Glockenkurve mit Mittelwert mu und Streuung sigma. 7 8 9 Fuer sigma=0 wird None zurueckgegeben, da dann die Kurve undefiniert ist. """ 11 12 13 14 15 16 if sigma == 0: y = None else: tmp1 = 1./(sigma*sqrt(2*pi)) tmp2 = (x-mu)/sigma y = tmp1*exp(-0.5*tmp2**2) 18 return y 20 # Anwendungen der neuen Funktion 21 y1 = gaussian(3,0,1) 22 y2 = gaussian(3,0,0) 24 print y1 25 print y2 gaussian.py Aufgabe Schreiben Sie eine eigene Funktion sqr, welche einen x-Wert übergeben bekommt und dann das Quadrat dieses Werte zurückgibt. 3 Vektoren/Arrays In Matlab ist es möglich, direkt mit Vektoren und Matrizen zu arbeiten. In Python wird dies über das Modul pylab ebenfalls zur Verfügung gestellt. In [14]: x = arange(-4*pi,4*pi,0.1) # start,stop,step In [15]: y = sin(x) 8 Die Daten können wir uns anschauen mit In [16]: for i in range(len(x)): ....: print x[i], y[i] ....: ....: und eine lange zweispaltige Tabelle rauscht an uns vorbei. Wir haben mit den Eingaben 14 und 15 zwei Listen (Arrays) erzeugt. Die x-Liste enthält 252 (=len(x)) Werte von −4 π bis kurz vor 4 π in 0.1 Schritten. Die gleichlange y-Liste enthält die dazu passenden Sinus-Werte. Aus den Listen können durch Indices einzelne Werte ausgelesen werden. Die Indices beginnen bei 0 (und hören hier bei 251 auf). Siehe dazu auch die Schleife in der Eingabe 16. Aufgabe Erzeugen Sie eine Tabelle von Werten zur Gauss’schen Funktion mit Mittelwert 0 und Standardabweichung 1. Mit den Arrays kann man wie mit langen Vektoren rechnen. Alle Berechnungen werden elementweise durchgeführt. Ein Beispiel dazu war die Eingabe 15 mit der Berechnung des Sinus. Dazu jetzt noch einige kleinere Beispiele: x = arange(0,1,0.1) y = arange(1,0,-0.1) z v w u = = = = x+y x-y x*y x/y n = zeros(10) o = ones(10) Aufgabe Spielen Sie die obigen Befehle durch und lassen Sie sich die Ergebnisse mit dem print Befehl ausgeben. 4 Graphische Darstellungen Für Signale ist es unhandlich, die enthaltenen Daten mittels der print Anweisung auf dem Bildschirm auszugeben. Besser wäre da ein Bild. Dazu liefert das Matplotlib-Modul entsprechende Befehle. Wir spielen dies hier einmal durch. Zuerst erzeugen wir ein etwas komplizierteres Signal. 9 In [17]: fs = 1000. In [18]: T = 1./fs In [19]: tf = 5 # Abtastfrequenz # Abtastintervall # maximale Zeit In [20]: t = arange(0,tf,T) # Zeitvektor In [21]: y = 5*sin(2*pi*3*(t-0.5)) + 2*sin(2*pi*5*t) # Signalvektor Und dann zeigen wir es an. In [22]: figure() In [22]: plot(t,y) In [23]: title(’Plot Beispiel’) In [24]: xlabel(’Zeit [s]’) In [25]: ylabel(’Amplitude’) # Bild Titel # Beschriftung x-Achse # Beschriftung y-Achse Es öffnet sich ein Grafikfenster mit unserer Signalkurve und der Beschriftung. Den Inhalt eines ‚Plots‘ kann man in eine Bilddatei speichern über In [26]: savefig(’plot-beispiel.png’) Aufgabe Erzeugen Sie einen Plot zur Gauss-Funktion mit Mittelwert 0 und Standardabweichung 1. Beschriften Sie die Grafik und speichern Sie sie ab unter dem Namen gauss-bild.png. 10 Aufgabe Die Darstellung des ‚Plot‘ kann man variieren. Spielen Sie dazu einmal folgende Befehle durch T = arange(-4*pi,4*pi,0.1) X = sin(T) plot(T,X,’r’) clf() # Bild loeschen plot(T,X,’go’) clf() plot(T,X,’b^’) clf() stem(T,X) clf() bar(T,X) Was passiert, wenn Sie den Befehl clf() weglassen? Was passiert, wenn Sie anstelle von clf() den Befehl figure() eingeben? 5 Schreiben und Lesen von Daten Bis hier können wir also Signale, die in Python generiert wurden auch in Python darstellen und das Ergebnis als Bilddatei abspeichern. Wir wollen nun ‚externe‘ Signale betrachten. Dazu nehmen wir an, dass diese Signale in einer Datei daten.txt im ASCII Format abgelegt sind. Hier ein kurzer Ausschnitt aus dieser Datei: ... -12.566371 -12.466371 -12.366371 -12.266371 -12.166371 -12.066371 ... 0.000000 0.099833 0.198669 0.295520 0.389418 0.479426 In der ersten Spalte stehen die x-Werte und in der zweiten Spalte die y-Werte. Wir können eine Datei daten.txt in Python erzeugen über 11 fd = open(’daten.txt’,’w’) for i in range(len(x)): fd.write("%f %f\n" % (x[i],y[i])) fd.close() Unsere erste Aufgabe besteht darin, diese Daten wieder einzulesen. fd = open(’daten.txt’,’r’) lines = fd.readlines() fd.close() x, y = [], [] for line in lines: s = string.split(line) x.append(float(s[0])) y.append(float(s[1])) Und dann können wir sie auch wieder wie vorhin darstellen. Das Einlesen von tabellarischen Textdaten geht auch noch etwas einfacher mit der Funktion numpy.loadtxt(). Lesen Sie dazu die entsprechende Hilfe nach (etwa unter www.scipy.org). Und mit numpy.savetxt() können Sie Matrizen in einer Textdatei speichern. Aufgabe In der Datei ecg.txt (siehe Webseite zur Vorlesung) stehen in drei (!) Spalten Zeiten und EKG Werte. Lesen Sie diese Datei in drei Signale t, x und y ein. Stellen Sie beide Signale x und y über der Zeit t dar. So, dass soll als erster schneller Einstieg einmal genügen.