yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #05088
live plot update during simulation
-
To:
yade-dev@xxxxxxxxxxxxxxxxxxx
-
From:
Janek Kozicki <janek_listy@xxxxx>
-
Date:
Tue, 6 Jul 2010 04:39:07 +0200
-
Face:
iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAALVBMVEUBAQEtLS1KSkpRUVFXV1dYWFhjY2Nzc3N3d3eHh4eKioqdnZ24uLjLy8vc3NxVIagyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH2AIVEzgS1fgQtQAAAjRJREFUOMtt1DFv00AUAOAzFQNbjigSyoQaRaBMhKgLUyKXpVNNeUpk9vyDqFJhQ1kiBuaqAwJCqvPtSLY7RlTn5+5IdnYkkt/AOyfxXVLe5vf53Z1875kd34tOEax8djmj6GyjhB5bxz50GdsVZr9fqRjZwAtKOJw5Wqs2MMZ16ALHsaDncF7xAHix1oEFHAB8f+pRjcO4gfZDykcYzbiucRolOLUJ6kjA0xtVt+A6TySlM0RajIpK6DzwKZ/nOYbF/gclHMo1ZOHYY/+Ha+AWuM+3oMS4eeqYzZ8FiCltgUqI8cd2wwAVpJk+8LWYjBtnJdQpHQqJMd4Oxt4bU9ESiFGc5hkqaH74asAX4iabP5I5gZ+qjgGlJCqZa3h3lxhoeVcSE1qLQC4sqKOK9MGW9E3izFqqHokoztLFEgXg31sbZEKnWi2T74A4NxfVQqlkjKtcAWD+zcArFEES01dR0E/nnV0IgugmDd/2L84sOAouRBBHEc7gtc8teDkRlE0iNQPo2w3Xhh/D4TCIQ4LRLoTvgwjj6RRgavdurxYGMaIuGOyAW/PpNlCcU9/93AHenAWYjPoAwa+G3e3to/MgFNTAEKvKDjzuCzHTnY3qqdXtx24VijzQfZ0yewZ5cwRFQaa+mIYr1uI0I76+3W4xhlvoVRwOA0Fdl64HlJnxP6T8YpX/Lga4Wv4A3ErrU5oTfN7Mu/llXMl8RXEPji/lQkN3H7qXqgC2By47EXeU/7PJ/wPxRKMnuZwIeAAAAABJRU5ErkJggg==
Hello,
I am learning python and there's a lot of stuff in python that I
don't know yet. To learn a little bit more I decided to try adding a
feature of showing live plot updates during simulation, like this:
http://geo.hmg.inpg.fr/~janek/yade-videos/yade_livePlot.mpg
https://www.yade-dem.org/wiki/Screenshots_and_videos#Experimantal_feature:_live_update_of_plotting
By doing this I am sure that I broke some clean coding python
conventions, just because I don't know python yet ;)
And there is a very ugly trick involved, and I hope Vaclav that you
could make this trick not ugly.
The trick is following:
wget http://tkinter.unpythonic.net/attach//mtTkinter/attachments/mtTkinter-0.3.tar.gz
tar -xvzf ./mtTkinter-0.3.tar.gz
sudo cp ./mtTkinter.py /usr/lib/python2.6/lib-tk/mtTkinter.py
sudo vim /usr/lib/pymodules/python2.6/matplotlib/backends/tkagg.py
:%s/import Tkinter as Tk/import mtTkinter as Tk/g
:wq
It is the ugliest thing that I have done to my debian installation recently.
But after that? It works like a charm.
Vaclav, I am not committing this, but rather sending as attachments.
I prefer that you will review and clean it up.
after applying those two patches you can just run uniax.py and enjoy
live updating plot.
best regards
--
Janek Kozicki http://janek.kozicki.pl/ |
=== modified file 'py/plot.py'
--- py/plot.py 2010-07-01 09:56:50 +0000
+++ py/plot.py 2010-07-06 02:05:36 +0000
@@ -32,9 +32,12 @@
labels={}
"Dictionary converting names in data to human-readable names (TeX names, for instance); if a variable is not specified, it is left untranslated."
+liveLines=[]
+plotFigs=[]
+
def reset():
"Reset all plot-related variables (data, plots, labels)"
- global data, plots, labels # plotLines
+ global data, plots, labels, liveLines, plotFigs # plotLines
data={}; plots={}; # plotLines={};
pylab.close('all')
@@ -105,10 +108,12 @@
to save the figure to file automatically.
"""
+ retPlots = []
if not noShow: pylab.ion() ## # no interactive mode (hmmm, I don't know why actually...)
for p in plots:
p=p.strip()
- pylab.figure()
+ thisFig=pylab.figure()
+ retPlots.append(thisFig)
plots_p=[_addPointTypeSpecifier(o) for o in _tuplifyYAxis(plots[p])]
plots_p_y1,plots_p_y2=[],[]; y1=True
for d in plots_p:
@@ -132,9 +137,95 @@
pylab.ylabel(','.join([_xlateLabel(_p[0]) for _p in plots_p_y2]))
pylab.xlabel(_xlateLabel(p))
if 'title' in O.tags.keys(): pylab.title(O.tags['title'])
- if not noShow: pylab.show()
- else: return pylab.gcf() # return current figure
-updatePeriod=0
+ if not noShow:
+ pylab.show()
+ return retPlots
+ else:
+ return pylab.gcf() # return current figure
+
+def livePlotInit():
+ """Prepare live plot
+
+ """
+ global plotFigs
+ global liveLines
+ plotFigs = []
+ liveLines = []
+ pylab.ion() ## # no interactive mode (hmmm, I don't know why actually...)
+ for p in plots:
+ p=p.strip()
+ thisFig=pylab.figure()
+ plotFigs.append(thisFig)
+ plots_p=[_addPointTypeSpecifier(o) for o in _tuplifyYAxis(plots[p])]
+ plots_p_y1,plots_p_y2=[],[]; y1=True
+ for d in plots_p:
+ if d[0]=='|||' or d[0]==None:
+ y1=False; continue
+ if y1: plots_p_y1.append(d)
+ else: plots_p_y2.append(d)
+ #plotLines[p]=
+ line, = pylab.plot(*sum([[data[p],data[d[0]],d[1]] for d in plots_p_y1],[]))
+ liveLines.append((line,p))
+ pylab.legend([_xlateLabel(_p[0]) for _p in plots_p_y1],loc=('upper left' if len(plots_p_y2)>0 else 'best'))
+ pylab.ylabel(','.join([_xlateLabel(_p[0]) for _p in plots_p_y1]))
+ if len(plots_p_y2)>0:
+ # try to move in the color palette a little further (magenta is 5th): r,g,b,c,m,y,k
+ origLinesColor=pylab.rcParams['lines.color']; pylab.rcParams['lines.color']='m'
+ # create the y2 axis
+ pylab.twinx()
+ #plotLines[p]+=
+ line, = pylab.plot(*sum([[data[p],data[d[0]],d[1]] for d in plots_p_y2],[]))
+ liveLines.append((line,p))
+ pylab.legend([_xlateLabel(_p[0]) for _p in plots_p_y2],loc='upper right')
+ pylab.rcParams['lines.color']=origLinesColor
+ pylab.ylabel(','.join([_xlateLabel(_p[0]) for _p in plots_p_y2]))
+ pylab.xlabel(_xlateLabel(p))
+ if 'title' in O.tags.keys(): pylab.title(O.tags['title'])
+
+def livePlotUpdateData():
+ global plotFigs
+ global liveLines
+ for (line,p) in liveLines:
+ p=p.strip()
+ plots_p=[_addPointTypeSpecifier(o) for o in _tuplifyYAxis(plots[p])]
+ plots_p_y1,plots_p_y2=[],[]; y1=True
+ for d in plots_p:
+ if d[0]=='|||' or d[0]==None:
+ y1=False; continue
+ if y1: plots_p_y1.append(d)
+ else: plots_p_y2.append(d)
+ # I don't know how to directly make a call to line.set_data, so I am using TMP_data
+ # for calling set_xdata() and set_ydata()
+ # but all those lines with TMP_data should be instead done by this single line below:
+ #line.set_data(*sum([[data[p],data[d[0]],d[1]] for d in plots_p_y1],[]))
+ TMP_data=sum([[data[p],data[d[0]],d[1]] for d in plots_p_y1],[])
+ line.set_ydata(TMP_data[1])
+ line.set_xdata(TMP_data[0])
+ if len(plots_p_y2)>0:
+ # same here, with TMP_data again...
+ #line.set_data(sum([[data[p],data[d[0]],d[1]] for d in plots_p_y2],[]))
+ TMP_data=sum([[data[p],data[d[0]],d[1]] for d in plots_p_y2],[])
+ line.set_ydata(TMP_data[1])
+ line.set_xdata(TMP_data[0])
+
+def livePlotRefresh():
+ livePlotUpdateData()
+ global plotFigs
+ for fig in plotFigs:
+ fig.canvas.draw()
+
+
+def livePlot():
+ livePlotInit()
+ import thread
+ thread.start_new_thread(livePlotLoop,(1,2))
+
+
+def livePlotLoop(dummy1,dummy2):
+ import time
+ while True:
+ livePlotRefresh()
+ time.sleep(1)
def saveGnuplot(baseName,term='wxt',extension=None,timestamp=False,comment=None,title=None,varData=False):
"""Save data added with :yref:`yade.plot.addData` into (compressed) file and create .gnuplot file that attempts to mimick plots specified with :yref:`yade.plot.plots`.
@@ -155,7 +246,7 @@
comment:
a user comment (may be multiline) that will be embedded in the control file
-Returns name fo the gnuplot file created.
+Returns name for the gnuplot file created.
"""
import time,bz2
if len(data.keys())==0: raise RuntimeError("No data for plotting were saved.")
=== modified file 'examples/concrete/uniax.py'
--- examples/concrete/uniax.py 2010-06-29 14:32:03 +0000
+++ examples/concrete/uniax.py 2010-07-06 02:15:01 +0000
@@ -176,5 +176,8 @@
# sleep forever if run by yade-multi, exit is called from stopIfDamaged
if os.environ.has_key('PARAM_TABLE'): time.sleep(1e12)
-
+# don't start the livePlot immediately because the autscale will be very bad
+import time
+time.sleep(2)
+yade.plot.livePlot()
Follow ups