Ich habe mir hier ein Beispiel ausgedacht, was mein Problem verdeutlichen soll. Im Netz hab ich ein Beispiel für einen Ringspeicher gefunden. Der Ringspeicher hat zwei Funktionen: .add(value) zum anfügen und .array(), um den Inhalt auszugeben. Mit .add will ich - wenn es später mal klappt - in einem Thread Daten einfügen in den Ringspeicher. Die Inhalte des Ringspeichers sollen in einem Graphen angezeigt werden und nach einer festgesetzten Zeit auch aktualisiert werden. Ich habe Angst, dass es bei dem Reinschreibeprozess bei der add-Methode und dem Lesen mit der array-Methode zu Problemen kommen könnte, da sie ja in verschiedenen Threads ablaufen.
Ich habe bei diesem Beispiel allerdings noch ein Problem - ich weis nicht, wie ich einen Plot aktualisieren soll. Ich habe - um den Plot in ein tkinter-Frame einzubauen, mit Funktionen aus matplotlib.figure gearbeitet, nicht mit matplotlib.pyplot. Pyplot hat nicht funktioniert. Bei Pyplot gibt es die Methoden pyplot.ion(), um den interaktiven Modus einzuschalten, dann erreichte ich es in einem anderen Beispiel, dass bei Veränderung des Datenarrays auch der Plot aktualisiert wurde. Jetzt möchte ich die Daten erstmal per Tastendruck aktualisieren mit der Methode refresh_plot. Wenn das klappt, dann kann ich später - wie in diesem Beispiel:
http://www.python-forum.de/viewtopic.ph ... 05&start=0 mit der after-Methode die Refresh-Funktion erneut aufrufen.
In einem anderen Beispiel habe ich zur Aktualisierung auch etwas mit funcanimation gefunden:
http://jakevdp.github.io/blog/2012/08/1 ... -tutorial/
Aber dieses Beispiel arbeitet auch mit der Pyplot-Klasse und nicht mit der figure-Klasse. Ich habe es aber nicht hinbekommen, mit der Pyplot-Klasse die Einbindung in einen tkinter-Frame hinzukriegen
Code: Alles auswählen
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
import matplotlib.animation as animation
from matplotlib import pyplot as plt
import random
import time
try:
import tkinter as tk
except:
import Tkinter as tk
class FIFOBuffer(object):
"""
A circular FIFO buffer implemented on top of numpy.
"""
__instance=None
def __init__(self, shape, dtype=np.float32, filled=False):
self._cache = np.zeros(shape, dtype)
self._values = np.zeros(shape, dtype)
self.shape = shape
self._cached=True
if filled:
self._ind = self.shape[0]
else:
self._ind = 0
self._cached = False
def add(self, value):
"""
Add a value to the buffer.
"""
ind = self._ind % self.shape[0]
self._values[ind] = value
self._ind += 1
self._cached = False
def array(self):
"""
Returns a numpy array containing the last stored values.
"""
if self._ind < self.shape[0]:
return self._values[:self._ind]
if not self._cached:
ind = self._ind % self.shape[0]
self._cache[:self.shape[0] - ind] = self._values[ind:]
self._cache[self.shape[0] - ind:] = self._values[:ind]
self._cached = True
return self._cache
def __len__(self):
return min(self._ind, self.shape[0])
def create_data(channels, container):
for i in range (0, channels):
container[i].add(random.random()*10)
def print_data(channels, container):
for i in range (0, channels):
print (container[i].array())
class PlotDisplay(tk.Frame):
def __init__(self, master, channels, data, style_args, refreshtime=100):
# tk.Frame.__self__(self, master=master)
self._master = master
self._data = data
self._styleargs = style_args
self._refreshtime = refreshtime
self._channels = channels
self._fig = Figure()
#self._fig = plt.Figure()
#plt.ion()
self._plot1 = self._fig.add_subplot(111)
self._canvas = FigureCanvasTkAgg(self._fig, master=self._master)
self._canvas.show()
self._canvas._tkcanvas.pack()
print ("in plotdisplayinit")
self._init_plot()
def _init_plot(self):
print ("in initplot")
for i in range (0, self._channels):
print (self._data[i].array())
# plt.plot(self._data[i].array(), self._styleargs[i])
self._plot1.plot(self._data[i].array(), self._styleargs[i])
def refresh_plot(self):
print ("in refresh_plot")
create_data(self._channels, self._data)
print_data (self._channels, self._data)
def main ():
root = tk.Tk()
def do_exit():
root.quit()
root.destroy()
plotframe = tk.Frame(master=root)
buttonframe = tk.Frame(master=root)
exit_button = tk.Button (buttonframe, text=" Beenden ", width=21, command=do_exit)
exit_button.pack()
refresh_button = tk.Button (buttonframe, text = " Refresh display ", width=21)
refresh_button.pack()
buttonframe.grid(row=0, column=2)
plotframe.grid(row=0, column=1)
style_args=['g-x', 'b*-', 'g','y--','r','b']
channels=6
values = 10
maxdata=channels*values
print ("Maxdata ---> %s" %str(maxdata))
# init data_container
data_container=[]
for i in range (0,channels):
data_container.append( FIFOBuffer(shape=[(values)], dtype=np.float16, filled=True) )
create_data(channels, data_container)
create_data(channels, data_container)
create_data(channels, data_container)
create_data(channels, data_container)
display = PlotDisplay (plotframe, channels, data_container, style_args)
refresh_button['command']=display.refresh_plot
"""
fig = plt.Figure()
for i in range (0, channels):
plt.plot(data_container[i].array(), style_args[i])
plt.show()
"""
root.mainloop()
print ("... PRG_end ...")
if __name__ == "__main__":
main ()