Grafiken erstellen und Skripte schreiben

Block 3

Skripte

Im letzten Block hast du eine Grafiken zur Auswertung eines Experiments gemacht. Du hast die Grafik nun deinem Betreuer gezeigt. Er möchte, dass du sie in einem Bericht verwendest. Dafür musst da aber noch ein paar Dinge anpassen. Um einen Eindruck zu erhalten war die Grafik ok. Für einen Bericht ist sie ohne Achsenbeschriftung und Legende aber nicht viel Wert. Du musst also die Grafik noch einmal machen. (Wenn du die Grafik als PDF gespeichert hast, könntest du sie nun auch mit Inkscape öffnen und anpassen.)

Solche und ähnliche Situationen kommen immer wieder vor. Die beste Lösung um darauf vorbereitet zu sein ist, für kompliziertere Rechnungen ein Skript zu schreiben. Ein Skript ist eine Datei die eine Abfolge von Befehlen enthält. Wenn du diese Datei dann ausführen lässt, werden die Befehle der Reihe nach abgearbeitet.

Musst du in einem Skript etwas kleines ändern, so reicht es die Datei anzupassen und du kannst dann deine ganze Rechnung wiederholen lassen. Von jetzt an solltest du deshalb für alle Aufgaben Skripte erstellen.

Hallo Welt

Als erstes Beispiel erstellen wir traditionsbewusst ein "Hallo Welt"-Skript. Erstelle mit dem Editor deiner Wahl eine Datei hallo.py im Arbeitsverzeichnis deiner Python-Session. Gib der Datei folgenden Inhalt:

print("Hallo Welt")

Hinweis: In diesem Beispiel sind wir auch zum ersten Mal einem String begegnet. Stirngs sind Zeichenketten und werden zwischen "" oder '' geschrieben. Auch Strings kannst du einer Variable zuordnen.

In IPython kannst du diese Datei nun ausführen:

%run hallo.py

%run beginnt mit % es ist also eine weitere Magic-Function von IPython. Das ist nützlich wenn du eine aktive Python-Session hast. Doch du kannst ein Skript auch direkt aus der Shell ausführen.

Skripte ausführen

Beende also nun deine IPython-Session.

Kontrolliere, dass du im Verzeichnis von hallo.py bist und teste dann die folgenden Befehle. (Nach jedem Befehl musst du zurück in die Shell.)

python3 hallo.py python3 -i hallo.py ipython3 -i hallo.py

Wie du siehst macht die -i Option, dass (I)Python am Schluss des Skripts nicht automatisch beendet wird. Das ist praktisch, wenn du dann noch weitere Dinge anpassen möchtest.

Hinweis: Damit du deine Skripts auch in ein paar Tagen noch verstehst, lohnt es sich, wichtige Überlegungen mit Kommentaren im Skript festzuhalten. Du solltest dir deshalb angewöhnen, deinen Code mit aussagekräftigen Kommentaren zu dokumentieren. Jetzt zu Beginn kann es zudem hilfreich sein, wenn du dir notierst, was die Befehle machen.

Du kannst dein Skript auch in ein ausführbares Programm verwandeln. Wir brauchen das nicht für diese Kurs. Wenn du trotzdem wissen möchtest, schau dir die Anleitung unter Verschiedene Hinweise an.

Das Plot-Skript erstellen

Nun kehren wir zum Ausgangsproblem dieses Blocks zurück. Starte IPython. Deine alten Befehle sollten in der History gespeichert sein. Mit der [up]Pfeil-Taste solltest du sie zurückholen können. Dank IPythons Magic-Functions haben wir aber eine viel elegantere Option. Tippe:

%hist -nl 100

Die Ausgabe enthält deine letzten 100 Befehle. Falls die Zeilen zu deiner Grafik nicht dabei sind, erhöhe die Zahl im hist-Befehl. Notiere dir die Nummer vor der ersten und letzten Zeile der Grafik (z.B. 5/20). Du kannst diese Zeilen nun in eine Datei schreiben lassen:

%save dateiname.py start-end

start und end sind dabei die Nummern, die du dir notiert hast.

Wenn du nun versuchst das Skript mit %run auszuführen, bekommst du eine Fehlermeldung zurück. Im Skript ist Pylab nicht geladen. Deshalb fehlen die meisten der verwendeten Befehle. Um Pylab zu laden fügst du zu Beginn der Datei einen Import-Befehl ein:

from pylab import *

Hinweis: Wie du im ersten Block gelernt hast, kann diese Import-Syntax Probleme verursachen. Wir verwenden sie in diesem Kurs deshalb nur für Pylab. Wir schreiben nur kurze (ca. 20 Zeilen) Programme und nutzen jeweils diverse pylab-Funktionen. Schreibst du komplexere Programme oder brauchst du nur einzelne der Befehle aus dem Pylab-Modul, so lohnt es sich eine anderen Import-Syntax zu verwenden.

Nachdem du das Modul geladen hast, kannst du dein Skript ausführen. Es wird dir aber keine Grafik angezeigt. In einem Skript musst du Grafiken explizit anzeigen lassen. Füge dazu show() am Ende deiner Datei an. Nun sollte alles klappen und du kannst dein Skript auch mit dem normalen Python starten

python3 dateiname.py

Dokumentation

Wir haben nun bereits zwei Skripte erstellt. Doch kein Skript ist fertig, solange es nicht dokumentiert ist. Du solltest alle deine Skripte mindestens mit einen Kommentarblock am Anfang (Header) versehen, der den Zweck des Skripts erklärt.

""" 'Hallo Welt'-Skript Traditionelles Beispielskript, gibt 'Hallo Welt' aus. """ print("Hallo Welt")

Die dreifachen Anführungszeichen markieren in Python einen mehrzeiligen Kommentarblock. Für die allgemeine Dokumentation solltest du jeweils diese Art von Kommentaren verwenden. Ist dein Skript komplizierter kannst du die wichtigen Ideen zusätzlich mit #-Kommentaren erklären.

Versehe nun dein Skript zum Fall-Experiment mit einem Header-Kommentar. Füge zudem #-Kommentar ein um den Inhalt zu erklären.

Grafiken

Das Skript für die Grafik aus dem letzten Block ist nun bereit. Es ist also an der Zeit uns die Grafik-Befehle genauer anzuschauen. Wir beginnen mit einer kurzen Wiederholung und schauen dann weitere Befehle an. Die Plot-Befehle werden alle durch das matplotlib-Modul zur Verfügung gestellt. Das Modul ist auf der matplotlib-Website ausführlich Dokumentiert. Dort findest du auch viele Beispiele. Für dieses Tutorial sollte die interne Hilfe aber ausreichen.

Das Grundprinzip

Das Grundprinzip ist bei allen Grafiken das gleiche. Alle Grafiken bestehen aus Punkten, deren Koordinaten in Listen oder Arrays gespeichert sind. Pro Koordinate (z.B. x oder y) übergibst du eine Liste. Der i-te Punkt wird dann durch die i-ten Einträge jeder Liste gegeben. Ein Beispiel: Folgender Code zeichnet die vier Punkte (0,0), (0,1), (1,0), (1,1)

x = [0, 0, 1, 1] y = [0, 1, 0, 1] plot(x, y, '+') axis([-0.2, 1.2, -0.2, 1.2])

Das dritte Argument von Plot '+' legt fest, dass die Punkte mit einem + markiert werden sollen. Die letzte Zeile ändert die Achsen, so dass sie jeweils vom -0.2 bis 1.2 gehen. Das erste Zahlen-Paar definiert die X-, das zweite die Y-Achse.

Aufgabe 1

Wenn du im obigen Plot-Befehl das letzte Argument entfernst, werden die Punkte der Reihe nach verbunden. Welchen Buchstaben gibt das? Sortiere die Punkte um, so dass sie ein Z ergeben.

Lösung anzeigen

# Das Beispiel schreibt ein N x = [0, 1, 0, 1] y = [1, 1, 0, 0]

Titel, Labels und Legenden

Um unser ursprüngliches Problem zu lösen brauchst du title(), xlabel(), ylabel() und legend(). Die Namen sind ziemlich selbsterklärend. Schaue dir die dazugehörige Dokumentation an und passe dann dein Skript entsprechend an. Ausserdem solltest du dir in der Hilfe zu plot() die Details zu den weiteren Argumenten durchlesen. Was macht zum Beispiel die Format-Angabe 'go'? Und wie veränderst du die Grösse deiner Marker?

Funktionen darstellen

Unsere erste Grafik enthielt ebenfalls bereits eine Funktion. Auch eine Funktion wird durch einzelne Punkte dargestellt.

x = frange(-2,2,0.5) y = exp(x) plot(x,y)

In der ersten Zeile definieren wir die x-Werte (Stützstellen), an denen wir unsere Funktion auswerten wollen. In der zweiten Zeile berechnen wir die dazugehörigen y-Werte und schliesslich stellen wir diese dar.

Aufgabe 2

Mit der Funktion polar(theta, r) kannst du in Polarkoordinaten zeichnen. Der Winkel theta wird dabei in Bogenmass angegeben. Verwende polar um die Funktion
f(t) = t \sin(t), t = {0,..., 12\pi}
in Polarkoordinaten darzustellen. Variiere dabei den Abstand der Stützstellen.

Lösung anzeigen

t=frange(0,12*pi,pi/4) polar(t,t*sin(t)) t=frange(0,12*pi,pi/8) polar(t,t*sin(t)) t=frange(0,12*pi,pi/16) polar(t,t*sin(t)) t=frange(0,12*pi,pi/32) polar(t,t*sin(t))

Grafiken mit Fehlerbalken

Wie du im Praktikum gelernt hast, sind die Messungen immer mit einem Fehler behaftet. Entsprechend musst du auch Grafiken mit Fehlerbalken erstellen können. Um Plots mit Fehlerbalken zu zeichnen verwendest du den Befehle errorbar. Damit kannst du alle möglichen Kombinationen von Fehlerbalken zeichnen:

errorbar(range(5), [10, 9, 8, 7, 6], [0.25, 0.5, 0.25, 1, 0.5]) errorbar(range(5), [10, 9, 8, 7, 6], [[.2,.2,.2,.2,.2], [.5,.5,.5,.5,.5]], fmt='.') errorbar(range(5), [10, 9, 8, 7, 6], [1,0.9,0.8,0.7,0.6], [0.1,0.2,0.3,0.4,0.5],'x') errorbar(range(5), [10, 9, 8, 7, 6], xerr=0.2,fmt='x')

Lass diese Befehle laufen und schau dir die Hilfe errorbar? an. Versuche die Befehle zu verstehen und diskutiere sie mit deinem Nachbarn.

In den Beispielen oben, sind wir das erste Mal Keyword-Argumenten begegnet. errorbar akzeptiert viele Argumente. Nur die ersten beiden sind obligatorisch. Alle anderen Argumente kannst du der Reihe nach angeben (wie im 1. und 3. Beispiel). Wie du in der Hilfe siehst, hat aber jedes Argument auch einen Namen (oder Keyword). Mit diesem kannst du dann einzelne Argumente gezielt festlegen (wie im 2. und 4. Beispiel).

Passe nun das Skript aus dem letzten Block noch so an, dass deine Messpunkte alle mit einem symmetrischen Fehler auf der Zeitmessung von 0.02s dargestellt werden. (Wir haben unser Experiment nicht von Hand gestoppt.)

Mehrere Plots

Manchmal wirst du mehrere Plots gemeinsam darstellen wollen. Dafür hast du drei Möglichkeiten. Wie du in der letzten Aufgabe bemerkt hast, kannst du mehrere Grafiken ins gleiche Fenster zeichnen. Du kannst aber auch das Grafik-Fenster unterteilen oder mehrere Grafik-Fenster öffnen. Unterteilen kannst du mit dem Befehl subplot(rows, columns, index). Der Befehl teilt dein Grafik-Fenster in rows Zeilen und columns Spalten. Deine nächster Plot wird in Untergrafik index gezeichnet.

from pylab import * x = frange(-pi,pi,0.1) subplot(1,2,1) plot(x, sin(x)) subplot(1,2,2) plot(x, cos(x))

Ob plot eine bestehende Grafik ergänzen oder ersetzen soll, bestimmst du mit hold(). Sollen Grafiken ersetzt werden, so musst du hold(False) aufrufen. Danach werden bestehende Grafiken durch Zeichen-Befehle ersetzt. Mit hold(True) kannst du das wieder zurück setzen.

Schliesslich kannst du mit figure() ein weiteres Grafikfenster öffnen. Alle weiteren Zeichnungsbefehle werden nun in diesem Fenster ausgeführt. Das alte Fenster bleibt dabei unverändert.

from pylab import * x = frange(-pi,pi,0.1) plot(x, sin(x)) plot(x, cos(x)) figure() hold(False) plot(x, sin(x)) # diese Kurve ist nicht sichtbar plot(x, cos(x))

Aufgabe 3

Erstelle ein Skript, das die Funktion

in folgenden Versionen zeichnet:

  1. Zeichne in einen ersten Subplot die Funktion. Verwende lineare Achsen.
  2. Zeichne in den selben Subplot zusätzlich log10(exp(x/1000)).
  3. Zeichne in einen weiteren Sublot rechts die Funktion. Verwende dieses Mal aber eine logarithmische y-Achse.

Für Plots mit logarithmischen Achsen brauchst du die Befehle loglog, semilogy, semilogx.

Lösung anzeigen

from pylab import * x=frange(0,4000,1.) subplot(1,2,1) plot(x,exp(x/1000)) plot(x,log10(exp(x/1000))) subplot(1,2,2) semilogy(x,exp(x/1000)) show()

Aufgabe 4

Ergänze nun die Grafik aus Aufgabe 3 mit einem zweiten Set von Subplots unterhalb der bisherigen. Zeichne darin die gleiche Funktion einfach mit negativem Exponenten.

Hinweis: Auch dies wird oft vorkommen. Plötzlich brauchst du doch noch einen Subplot mehr. Für solche Fälle kannst du dir viel Arbeit sparen, wenn du in deinem Skript möglichst überall mit Variablen statt Zahlenwerten arbeitest. In unserem Fall solltest du deshalb Zeilen- und Spaltenanzahl in einer Variablen speichern.

Lösung anzeigen

# gesamte Lösung, inklusive 3 from pylab import * rows = 2; cols = 2; x=frange(0,4000); subplot(rows,cols,1) plot(x,exp(x/1000)) plot(x,log10(exp(x/1000))) subplot(rows,cols,2) semilogy(x,exp(x/1000)) subplot(rows,cols,3) plot(x,exp(-x/1000)) plot(x,log10(exp(-x/1000))) subplot(rows,cols,4) semilogy(x,exp(-x/1000)) show()

Polynome

Mit dem Befehl polyval(C,x) kannst du ein Polynom mit den Koeffizienten C für alle Punkte im Vektor x berechnen lassen. Das ist deutlich einfacher, als das Polynom von Hand aufzuschreiben. Das folgenden Beispiel zeigt dies.

from pylab import * x = frange(-10,10,0.5) y1 = 2*x**2+3*x+5; plot(x,y1) figure() C = [2, 3, 5] y2 = polyval(C,x) plot(x,y2,'r') show()

Was macht 'r' in der letzten Zeile?

Ein weitere nützlicher Befehl bei Polynomen ist roots(C). roots gibt einen Vektor mit den x-Positionen der Nullstellen zurück.

Aufgabe 5

Stelle die Funktion
f(x) = x3 + 3x2 - 13x - 15
wie folgt dar:

  • Plotte die Funktion auf der x-Achse zwischen -5.5 und 3.5 und auf der y-Achse zwischen -30 und 30
  • Zeichne ein Gitter (mit grid()).
  • Versehe die Graphik mit dem Titel "Polynom 3. Ordnung" , der x-Achsenbeschriftung "Abszisse" und der y-Achsenbeschriftung "Ordinate".
  • Plotte in dieselbe Graphik die Nullstellen des Polynoms. Markiere diese mit roten Kreislein.
  • Füge dem Plot eine Legende für das Polynom und die Nullstellen hinzu.

Lösung anzeigen

from pylab import * C=[1, 3, -13, -15] x=frange(-10,10,0.1) fx=polyval(C,x) plot(x,fx, label='f(x)=x**3+3x**2-13x-15') axis([-5.5, 3.5, -30, 30]) grid(True) title('Polynom 3. Ordnung') xlabel('Abszisse') ylabel('Ordinate') nullstellen=roots(C) plot(nullstellen,zeros(nullstellen.size),'ro', label='Nullstellen') legend() show()

Aufgaben zur Vertiefung

Entscheide wieder selbst, welche Themen du noch einmal anschauen und welche Vertiefungsaufgaben du lösen möchtest. Wie immer kannst du dir auch selbst Aufgaben stellen.

hallo-Skript

Pendel-Experiment

Erstelle auch ein Skript zum Pendel-Experiment und passe es so an, dass es mit Achsen-Label, Titel, Legende und Fehlerbalken versehen ist.

Kardioide

r(φ) = a*(b + c*cos(φ)), mit a = b = c = 1
ist die Definition einer Kardioide. Erstelle eine Grafik mit verschiedenen Subplots, die jeweils andere Werte für a, b und c verwenden. Versehe die Grafik wieder mit allen nötigen Informationen.

Polynome

Zeichne die beiden Polynome y = 2x2-1 und y = 32x5-32x3+6x mit dem Polyval-Befehl, bestimme ihre Nullstellen und zeichne diese ebenfalls ein.