Hier werden die Unterschiede zwischen zwei Versionen gezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
ws1415:beispiel_zu_graphiken_mit_matplotlib [2015/01/29 12:41] stefanborn |
ws1415:beispiel_zu_graphiken_mit_matplotlib [2016/05/10 14:46] (aktuell) |
||
---|---|---|---|
Zeile 5: | Zeile 5: | ||
Dafür muss man von der Klassenstruktur von Matplotlib etwas mehr verstehen. | Dafür muss man von der Klassenstruktur von Matplotlib etwas mehr verstehen. | ||
- | Eine Graphik ist eine ''Figure'', in ein solches Figure-Objekt kann man verschiedene ``Axes``-Objekte einfügen. Ein solches Axes-Objekt definiert ein Koordinatensystem, um einen gewissen Ort der Graphik anzusteuern. In das Axes-Objekt kann man nun verschiedene ``Artist``-Objekte einfügen, etwas Dreiecke, Kreise, oder auch die Darstellng eines Arrays als Bild. Ein Dreieck-Objekt ist nicht etwas ein kleines Bildchen, sondern ein Objekt, das Methoden hat, die es in einem gegebenen Koordinatensystem zeichnen, löschen, verändern. | + | Eine Graphik ist eine ''Figure'', in ein solches Figure-Objekt kann man verschiedene ''Axes''-Objekte einfügen. Ein solches Axes-Objekt definiert ein Koordinatensystem, um einen gewissen Ort der Graphik anzusteuern. In das Axes-Objekt kann man nun verschiedene ''Artist''-Objekte einfügen, etwas Dreiecke, Kreise, oder auch die Darstellng eines Arrays als Bild. Ein Dreieck-Objekt ist nicht etwas ein kleines Bildchen, sondern ein Objekt, das Methoden hat, die es in einem gegebenen Koordinatensystem zeichnen, löschen, verändern. |
- | Diese Artist-Objekte werden durch gewisse Daten und durch gewisse Parameter bestimmt. Der Unterschied zwischen Daten und Parametern ist zwar willkürlich, aber wichtig. Für die Daten (im Falle der Bildanzeige wäre das das Array) gibt es eine Methode, die die Daten zu veränderen erlaubt (sie heißt leider nicht immer ``set_data``. Man muss in der ``matplotlib``-Dokumentation nachsehen, um diese Methoden zu finden. Für Polygone etwa (also zum Beispiel Dreiecke) lassen sich die Koordinaten der Eckpunkte mit ``set_xy`` setzen. | + | Diese Artist-Objekte werden durch gewisse Daten und durch gewisse Parameter bestimmt. Der Unterschied zwischen Daten und Parametern ist zwar willkürlich, aber wichtig. Für die Daten (im Falle der Bildanzeige wäre das das Array) gibt es eine Methode, die die Daten zu veränderen erlaubt (sie heißt leider nicht immer ''set_data''. Man muss in der ''matplotlib''-Dokumentation nachsehen, um diese Methoden zu finden. Für Polygone etwa (also zum Beispiel Dreiecke) lassen sich die Koordinaten der Eckpunkte mit ''set_xy'' setzen. Zu den Parametern gehört normalerweise die Farbe ''color'', die Transparenz ''alpha'', etc. Diese Parameter können entweder mit speziellen Methoden (''set_color'',...) oder aber mit der generischen Methode ''matplotlib.artist.setp(...)'' gesetzt werden. |
- | Im folgenden Beispiel wird ein Koordinatensystem [0,2N]x[0,2N] für das erste Axes-Objekt ax geschaffen. Später wird ein zweites Koordinatensystem ``ax1`` rechts oben in dem ersten platziert. | + | Im folgenden Beispiel wird ein Koordinatensystem [0,2N]x[0,2N] für das erste Axes-Objekt ax geschaffen. Später wird ein zweites Koordinatensystem ''ax1'' rechts oben in dem ersten platziert. |
- | | + | Durch ''ax.imshow(...)'' wird dem Koordinatensystem ''ax'' ein ''Artist'' hinzugefügt. Anderer ''Artists'' werden mit entsprechenden Klassen von matplotlib erzeugt und durch ''ax.add_artist(...)'' dem Koordinatensystem hinzugefügt. |
+ | |||
+ | |||
+ | ==== Das Beispiel ==== | ||
+ | |||
+ | <code python> | ||
+ | import matplotlib | ||
+ | ## Hier wird das so genannte 'backend' eingestellt. matplotlib kann die | ||
+ | ## eigentliche Erzeugung der Graphik von verschiedenen Systemen durchführen | ||
+ | ## lassen. Das beeinflusst die Geschwindigkeit, aber auch, wie die Fenster | ||
+ | ## aussehen. | ||
+ | matplotlib.use('GTKAgg') | ||
+ | import matplotlib.pyplot as plt | ||
+ | |||
+ | import numpy as np | ||
+ | import time | ||
+ | import sys | ||
+ | |||
+ | |||
+ | def anzeige(): | ||
+ | '''wird aufgerufen, um den Plot zu aktualisieren''' | ||
+ | fig.canvas.draw() | ||
+ | fig.canvas.flush_events() | ||
+ | |||
+ | |||
+ | |||
+ | def main(): | ||
+ | global im | ||
+ | while True: | ||
+ | |||
+ | ## verändere Bilddaten und setze diese | ||
+ | |||
+ | im=4*im*(1-im)#np.random.rand(N*N).reshape(N,N) | ||
+ | im=np.where(im<1,im, 1) | ||
+ | image.set_data(im) | ||
+ | |||
+ | ## verändere die Kreisdaten | ||
+ | |||
+ | # Mittelpunkt ist ein Attribut | ||
+ | |||
+ | c1.center=(c1.center[0]+np.random.randint(3)-1,c1.center[1]+np.random.randint(3)-1) | ||
+ | |||
+ | # Parameter wie 'color' verändert man so | ||
+ | |||
+ | matplotlib.artist.setp(c1,color=(np.random.rand(),np.random.rand(),np.random.rand())) | ||
+ | |||
+ | ## verändere die Dreiecksdaten: | ||
+ | |||
+ | dt=time.time()-now | ||
+ | p1.set_xy(np.array([[np.cos(dt)*N/2.+N/2., np.sin(dt)*N/2.+N/2], | ||
+ | [np.cos(0.4*dt)*N/2.+N/2., np.sin(0.4*dt)*N/2.+N/2], | ||
+ | [np.cos(0.1*dt)*N/2.+N/2., np.sin(0.1*dt)*N/2.+N/2]])) | ||
+ | matplotlib.artist.setp(p1,color=(np.abs(np.sin(dt)),np.abs(np.cos(dt)), np.abs(np.sin(1.777*dt)))) | ||
+ | |||
+ | |||
+ | ## Verändere die Farben der Dreiecke und Kanten (simultan) | ||
+ | |||
+ | # Hier wird eine Liste von Farbtripeln erzeugt | ||
+ | |||
+ | colors=[] | ||
+ | for i in range(len(triangles)): | ||
+ | colors.append((np.abs(np.sin(0.1*dt*i)),np.abs(np.sin(0.1*2*dt*i)),np.abs(0.1*np.sin(3*dt*i)))) | ||
+ | |||
+ | # Hier wird die Liste als den Dreiecken zugeordnet | ||
+ | |||
+ | triangle_collection.set_color(colors) | ||
+ | |||
+ | # Genauso für die Kanten, erst Liste erzeugen, dann zuordnen | ||
+ | |||
+ | colors=[] | ||
+ | for i in range(len(lines)): | ||
+ | colors.append((np.abs(np.sin(0.1*dt*i)),np.abs(np.sin(0.1*2*dt*i)),np.abs(0.1*np.sin(3*dt*i)))) | ||
+ | line_collection.set_color(colors) | ||
+ | |||
+ | ## Zeichne mit den aktuellen Werten | ||
+ | |||
+ | anzeige() | ||
+ | return 0 | ||
+ | |||
+ | if __name__ == '__main__': | ||
+ | |||
+ | now=time.time() | ||
+ | |||
+ | ############## | ||
+ | |||
+ | matplotlib.rcParams['toolbar'] = 'None' # Keine Buttons zum Vergrößern/Verkleinern anzeigen | ||
+ | fig=plt.figure() # Figure Objekt | ||
+ | |||
+ | N=100 | ||
+ | ax = plt.axes(xlim=(0,2*N),ylim=(0,2*N)) # Axes (Koordinatensystem)-Objekt | ||
+ | plt.axis("off") # Achsen nicht beschriften | ||
+ | |||
+ | ############## | ||
+ | |||
+ | # Ein Bild ("Artist") in ax erzeugen, das ein Array durch farbige Punkte ausdrückt | ||
+ | |||
+ | im=np.array([[np.abs(np.sin(0.1*(i*i+j*j))) for i in range(N)]for j in range(N)])#np.random.rand(N*N).reshape(N,N) | ||
+ | image=ax.imshow(im) | ||
+ | |||
+ | # Einen Kreis ("Artist") erzeugen und zu ax hinzufügen. | ||
+ | |||
+ | c1=matplotlib.patches.Circle([N/2,N/2],color=(1,0,0),alpha=0.8) | ||
+ | ax.add_artist(c1) | ||
+ | |||
+ | # Ein Dreieck mit identischen Ecken erzeugen und zu ax hinzufügen | ||
+ | |||
+ | p1=matplotlib.patches.Polygon(np.array([[1,0],[1,0],[1,0]]),color=(1.,0,0),alpha=0.8) | ||
+ | ax.add_artist(p1) | ||
+ | |||
+ | |||
+ | ## Eine Liste von Dreiecken erzeugen | ||
+ | |||
+ | ax1=fig.add_axes((0.5,0.5,0.5,0.5)) ## Standard-Koordinatensystem der neuen Achse 0-1 x 0-1 | ||
+ | ## lässt sich mit xlim und ylim überschreiben, s. o. | ||
+ | plt.axis("off") | ||
+ | |||
+ | triangles=[] | ||
+ | points=np.random.rand(30,2) | ||
+ | import scipy.spatial | ||
+ | tri=scipy.spatial.Delaunay(points) | ||
+ | for simplex in tri.simplices: | ||
+ | p=matplotlib.patches.Polygon(np.array([points[simplex[0]],points[simplex[1]],points[simplex[2]]])) | ||
+ | triangles.append(p) | ||
+ | triangle_collection=matplotlib.collections.PatchCollection(triangles) | ||
+ | ax1.add_artist(triangle_collection) | ||
+ | |||
+ | ## Eine Liste der zugehörigen Dreieckskanten | ||
+ | |||
+ | lines=set([]) | ||
+ | for simplex in tri.simplices: | ||
+ | lines.add((simplex[0],simplex[1])) | ||
+ | lines.add((simplex[1],simplex[2])) | ||
+ | lines.add((simplex[2],simplex[0])) | ||
+ | |||
+ | line_collection=matplotlib.collections.LineCollection([(points[line[0]], points[line[1]]) for line in lines],color=(0,1,0)) | ||
+ | ax1.add_artist(line_collection) | ||
+ | # Anzeigen | ||
+ | |||
+ | anzeige() | ||
+ | |||
+ | ## Beim erstem Aufbau der Graphik muss eine solche Pause erzwungen werden | ||
+ | ## für die späteren Updates der Graphik ist das nicht notwendig. | ||
+ | |||
+ | plt.pause(0.05) | ||
+ | |||
+ | # Animationsschleife starten | ||
+ | |||
+ | main() | ||
+ | |||
+ | </code> |