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.
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.
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.
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
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.
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 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.
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.
# Das Beispiel schreibt ein N x = [0, 1, 0, 1] y = [1, 1, 0, 0]
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?
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.
Mit der Funktion polar(theta, r)
kannst du in Polarkoordinaten zeichnen.
Der Winkel theta wird dabei in Bogenmass angegeben.
Verwende polar um die Funktion
in Polarkoordinaten darzustellen.
Variiere dabei den Abstand der Stützstellen.
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))
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.)
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))
Erstelle ein Skript, das die Funktion
in folgenden Versionen zeichnet:
log10(exp(x/1000))
.Für Plots mit logarithmischen Achsen brauchst du die Befehle loglog
, semilogy
, semilogx
.
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()
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.
# 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()
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.
Stelle die Funktion
f(x) = x3 + 3x2 - 13x - 15
wie folgt dar:
grid()
).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()
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.
Erstelle auch ein Skript zum Pendel-Experiment und passe es so an, dass es mit Achsen-Label, Titel, Legende und Fehlerbalken versehen ist.
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.
Zeichne die beiden Polynome y = 2x2-1 und y = 32x5-32x3+6x mit dem Polyval-Befehl, bestimme ihre Nullstellen und zeichne diese ebenfalls ein.