Reputation: 297
I am new to Python and wxPython I am trying to simulate particles in a box with random velocities in random directions. I created a simple GUI in wxFormBuilder where I have a panel to show a plot of the paricles. The particles are set to a position and plotted onto the panel, then I start the simulation and update the x and y positons of the particles. When redrawing the positions The axes appear 'thicker' as before, it looks like if there are several axes ontop of eachother.
I cant find anything about this problem, I hope somebody could help me with this?
This is the code that creates the Plot:
import wx
import particles
import random
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import \
FigureCanvasWxAgg as FigCanvas, \
NavigationToolbar2WxAgg as NavigationToolbar
matplotlib.rcParams.update({'font.size': 8})
class MyFrameSub( particles.GUI_MainFrame ):
def __init__( self, parent ):
particles.GUI_MainFrame.__init__( self, parent )
def InitData(self):
self.npart = int(self.m_npart.GetValue())
self.nsteps = int(self.m_steps.GetValue())
self.ndt = float(self.m_dt.GetValue())
self.x= [random.random() for I in range(self.npart)]
self.y= [2*random.random()-1 for I in range(self.npart)]
self.vx= [self.ndt*(2*random.random()-1) for I in range(self.npart)]
self.vy= [self.ndt*(2*random.random()-1) for I in range(self.npart)]
return
def CreatePlot(self):
panelsize = self.m_PlotPanel.GetClientSize()
self.figure = Figure(figsize=(panelsize[0]/100.0,panelsize[1]/100.0), dpi=100, frameon=False)
self.canvas = FigCanvas(self.m_PlotPanel, wx.ID_ANY, self.figure)
self.axes = self.figure.add_subplot(111)
self.axes.axis((-1,1,-1,1))
self.partplot, = self.axes.plot(self.x, self.y, 'ro')
self.canvas.draw()
return
def UpdateData(self):
for i in range(self.nsteps):
for j in range(self.npart):
self.x[j]=self.x[j]+self.vx[j]
self.y[j]=self.y[j]+self.vy[j]
if abs(self.x[j])>1:
self.vx[j]=-self.vx[j]
if abs(self.y[j])>1:
self.vy[j]=-self.vy[j]
self.partplot.set_xdata(self.x)
self.partplot.set_ydata(self.y)
self.canvas.draw()
return
followed by the button definitions, it looks like this: Before running the simulation: www.merlinvs.de/before.jpg
and after running the simulation: www.merlinvs.de/after.jpg
As you see the axes got ugly and I have no idea why.
Another question I was thinking about is the following: When I run a loop that takes a while the UI is unresponsive, is it possible to have the UI active to cancel a loop if desired?
Upvotes: 1
Views: 582
Reputation: 15266
As for the unresponsive UI, I used greenlets for my Matplotlib stuff while updating it
from gevent.greenlet import Greenlet
from gevent import sleep
import matplotlib.plot as plt
# Plot stuff
def event_handler():
# Can update plot
sleep(1) # Simulate handling or number crunching (numpy WILL block)
g = Greenlet(event_handler)
g.start()
plt.plot(0,0) # Works immediately and updates
Some things of note is that for serious applications you need to add some protection against race coditions with the plot. Numpy and external science libraries typically cause the entire application to become unresponsive (in my experience) because they are blocking system calls outside of the greenlet context switcher's reach. For something simple though the above pattern works well.
Upvotes: 0