Ik heb problemen met het opnieuw tekenen van de afbeelding hier. Ik sta de gebruiker toe om de eenheden in de tijdschaal (x-as) te specificeren en dan herbereken ik en noem ik deze functie plots()
. Ik wil dat de plot gewoon wordt bijgewerkt, niet dat er nog een plot aan de figuur wordt toegevoegd.
def plots():
global vlgaBuffSorted
cntr()
result = collections.defaultdict(list)
for d in vlgaBuffSorted:
result[d['event']].append(d)
result_list = result.values()
f = Figure()
graph1 = f.add_subplot(211)
graph2 = f.add_subplot(212,sharex=graph1)
for item in result_list:
tL = []
vgsL = []
vdsL = []
isubL = []
for dict in item:
tL.append(dict['time'])
vgsL.append(dict['vgs'])
vdsL.append(dict['vds'])
isubL.append(dict['isub'])
graph1.plot(tL,vdsL,'bo',label='a')
graph1.plot(tL,vgsL,'rp',label='b')
graph2.plot(tL,isubL,'b-',label='c')
plotCanvas = FigureCanvasTkAgg(f, pltFrame)
toolbar = NavigationToolbar2TkAgg(plotCanvas, pltFrame)
toolbar.pack(side=BOTTOM)
plotCanvas.get_tk_widget().pack(side=TOP)
Antwoord 1, autoriteit 100%
Je hebt in wezen twee opties:
-
Doe precies wat u momenteel doet, maar bel
graph1.clear()
engraph2.clear()
voordat u de gegevens opnieuw plot. Dit is de langzaamste, maar meest eenvoudige en meest robuuste optie. -
In plaats van opnieuw te repletten, kunt u gewoon de gegevens van de plotobjecten bijwerken. U moet enkele wijzigingen in uw code aanbrengen, maar dit zou veel moeten zijn, veel sneller dan elke keer opnieuw te replatteren. De vorm van de gegevens die u plotte, kan echter niet veranderen, en als het bereik van uw gegevens verandert, moet u de X- en Y-aslimieten handmatig resetten.
Om een voorbeeld van de tweede optie te geven:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 6*np.pi, 100)
y = np.sin(x)
# You probably won't need this if you're embedding things in a tkinter plot...
plt.ion()
fig = plt.figure()
ax = fig.add_subplot(111)
line1, = ax.plot(x, y, 'r-') # Returns a tuple of line objects, thus the comma
for phase in np.linspace(0, 10*np.pi, 500):
line1.set_ydata(np.sin(x + phase))
fig.canvas.draw()
fig.canvas.flush_events()
Antwoord 2, Autoriteit 24%
U kunt ook het volgende doen:
Dit trekt een 10×1 willekeurige matrixgegevens op het perceel voor 50 cycli van de voor lus.
import matplotlib.pyplot as plt
import numpy as np
plt.ion()
for i in range(50):
y = np.random.random([10,1])
plt.plot(y)
plt.draw()
plt.pause(0.0001)
plt.clf()
Antwoord 3, Autoriteit 9%
Dit werkte voor mij. Roept herhaaldelijk een functie op de grafiek bij het bijwerken van de grafiek.
import matplotlib.pyplot as plt
import matplotlib.animation as anim
def plot_cont(fun, xmax):
y = []
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
def update(i):
yi = fun()
y.append(yi)
x = range(len(y))
ax.clear()
ax.plot(x, y)
print i, ': ', yi
a = anim.FuncAnimation(fig, update, frames=xmax, repeat=False)
plt.show()
“fun” is een functie die een geheel getal retourneert.
FuncAnimation zal herhaaldelijk “update” aanroepen, het zal dat “xmax” keer doen.
Antwoord 4, autoriteit 4%
Voor het geval iemand dit artikel tegenkomt op zoek naar wat ik zocht, ik vond voorbeelden op
Hoe kan ik scalaire 2D-gegevens visualiseren met Matplotlib?
en
http://mri.brechmos.org/2009/ 07/automatisch-update-een-cijfer-in-een-loop
(op web.archive.org)
vervolgens aangepast om imshow te gebruiken met een invoerstapel van frames, in plaats van on-the-fly contouren te genereren en te gebruiken.
Begin met een 3D-array van vormafbeeldingen (nBins, nBins, nBins), genaamd frames
.
def animate_frames(frames):
nBins = frames.shape[0]
frame = frames[0]
tempCS1 = plt.imshow(frame, cmap=plt.cm.gray)
for k in range(nBins):
frame = frames[k]
tempCS1 = plt.imshow(frame, cmap=plt.cm.gray)
del tempCS1
fig.canvas.draw()
#time.sleep(1e-2) #unnecessary, but useful
fig.clf()
fig = plt.figure()
ax = fig.add_subplot(111)
win = fig.canvas.manager.window
fig.canvas.manager.window.after(100, animate_frames, frames)
Ik heb ook een veel eenvoudigere manier gevonden om dit hele proces aan te pakken, zij het minder robuust:
fig = plt.figure()
for k in range(nBins):
plt.clf()
plt.imshow(frames[k],cmap=plt.cm.gray)
fig.canvas.draw()
time.sleep(1e-6) #unnecessary, but useful
Merk op dat allebei alleen lijken te werken met ipython --pylab=tk
, A.K.A. backend = TkAgg
Bedankt voor de hulp bij alles.
Antwoord 5, Autoriteit 4%
Ik heb een pakket vrijgegeven genaamd python-curatow die functionaliteit biedt om een figuur-update te laten updaten, Typisch gebeld in een voor lus, vergelijkbaar met Matlab’s drawnow
.
Een voorbeeldgebruik:
from pylab import figure, plot, ion, linspace, arange, sin, pi
def draw_fig():
# can be arbitrarily complex; just to draw a figure
#figure() # don't call!
plot(t, x)
#show() # don't call!
N = 1e3
figure() # call here instead!
ion() # enable interactivity
t = linspace(0, 2*pi, num=N)
for i in arange(100):
x = sin(2 * pi * i**2 * t / 100.0)
drawnow(draw_fig)
Dit pakket werkt met een matplotlib-figuur en biedt opties om te wachten na elke figuur-update of dalen in de debugger.
Antwoord 6, Autoriteit 2%
Dit werkte voor mij:
from matplotlib import pyplot as plt
from IPython.display import clear_output
import numpy as np
for i in range(50):
clear_output(wait=True)
y = np.random.random([10,1])
plt.plot(y)
plt.show()
Antwoord 7, Autoriteit 2%
Al het bovenstaande kan waar zijn, maar voor mij werkt “online-updaten” van cijfers alleen met sommige backends, met name wx
. Je zou kunnen proberen om hierin te veranderen, b.v. door ipython/pylab te starten door ipython --pylab=wx
! Veel succes!
Antwoord 8
Op basis van de andere antwoorden heb ik de update van de figuur in een python-decorateur gewikkeld om het updatemechanisme van de plot te scheiden van de eigenlijke plot. Op deze manier is het veel gemakkelijker om een plot bij te werken.
def plotlive(func):
plt.ion()
@functools.wraps(func)
def new_func(*args, **kwargs):
# Clear all axes in the current figure.
axes = plt.gcf().get_axes()
for axis in axes:
axis.cla()
# Call func to plot something
result = func(*args, **kwargs)
# Draw the plot
plt.draw()
plt.pause(0.01)
return result
return new_func
Gebruiksvoorbeeld
En dan kun je het gebruiken zoals elke andere decorateur.
@plotlive
def plot_something_live(ax, x, y):
ax.plot(x, y)
ax.set_ylim([0, 100])
De enige beperking is dat je de figuur vóór de lus moet maken:
fig, ax = plt.subplots()
for i in range(100):
x = np.arange(100)
y = np.full([100], fill_value=i)
plot_something_live(ax, x, y)