yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #05101
[Branch ~yade-dev/yade/trunk] Rev 2325: 1. LIVE PLOTTING (thanks to Janek for the idea and the suggestion of mtTkinter). Report bugs.
------------------------------------------------------------
revno: 2325
committer: Václav Šmilauer <eudoxos@xxxxxxxx>
branch nick: trunk
timestamp: Tue 2010-07-06 13:31:29 +0200
message:
1. LIVE PLOTTING (thanks to Janek for the idea and the suggestion of mtTkinter). Report bugs.
added:
py/3rd-party/mtTkinter-0.3/
py/3rd-party/mtTkinter-0.3/mtTkinter.py
modified:
examples/concrete/uniax.py
examples/simple-scene/simple-scene-plot.py
py/3rd-party/README
py/SConscript
py/plot.py
py/yadeWrapper/yadeWrapper.cpp
--
lp:yade
https://code.launchpad.net/~yade-dev/yade/trunk
Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-dev/yade/trunk/+edit-subscription
=== modified file 'examples/concrete/uniax.py'
--- examples/concrete/uniax.py 2010-06-29 14:32:03 +0000
+++ examples/concrete/uniax.py 2010-07-06 11:31:29 +0000
@@ -103,7 +103,7 @@
#O.miscParams=[Gl1_CpmPhys(dmgLabel=False,colorStrain=False,epsNLabel=False,epsT=False,epsTAxes=False,normal=False,contactLine=True)]
# plot stresses in ¼, ½ and ¾ if desired as well; too crowded in the graph that includes confinement, though
-plot.plots={'eps':('sigma',)} #'sigma.25','sigma.50','sigma.75')}
+plot.plots={'eps':('sigma','sigma.50'),'t':('eps')} #'sigma.25','sigma.50','sigma.75')}
plot.maxDataLen=4000
O.saveTmp('initial');
=== modified file 'examples/simple-scene/simple-scene-plot.py'
--- examples/simple-scene/simple-scene-plot.py 2010-05-29 20:52:10 +0000
+++ examples/simple-scene/simple-scene-plot.py 2010-07-06 11:31:29 +0000
@@ -25,7 +25,7 @@
from yade import utils
O.bodies.append(utils.box(center=[0,0,0],extents=[.5,.5,.5],dynamic=False,color=[1,0,0]))
O.bodies.append(utils.sphere([0,0,2],1,color=[0,1,0]))
-O.dt=.2*utils.PWaveTimeStep()
+O.dt=.002*utils.PWaveTimeStep()
############################################
@@ -46,9 +46,9 @@
sph=O.bodies[1]
## store some numbers under some labels
plot.addData(t=O.time,i=O.iter,z_sph=sph.state.pos[2],z_sph_half=.5*sph.state.pos[2],v_sph=sph.state.vel.norm())
-
-O.run(int(2./O.dt),True);
-print "Now calling plot.plot() to show the figures (close them to continue)."
+print "Now calling plot.plot() to show the figures. The timestep is artificially low so that you can watch graphs being updated live."
+plot.liveInterval=.2
plot.plot()
-plot.saveGnuplot('/tmp/a')
+O.run(int(2./O.dt));
+#plot.saveGnuplot('/tmp/a')
## you can also access the data in plot.data['i'], plot.data['t'] etc, under the labels they were saved.
=== modified file 'py/3rd-party/README'
--- py/3rd-party/README 2009-08-23 15:50:47 +0000
+++ py/3rd-party/README 2010-07-06 11:31:29 +0000
@@ -11,3 +11,7 @@
license: Boost software license 1.0
note: only headers are copied here
+mtTkinter-0.3:
+ homepage: http://tkinter.unpythonic.net/wiki/mtTkinter
+ source: http://tkinter.unpythonic.net/attach//mtTkinter/attachments/mtTkinter-0.3.tar.gz
+ license: unspecified
=== added directory 'py/3rd-party/mtTkinter-0.3'
=== added file 'py/3rd-party/mtTkinter-0.3/mtTkinter.py'
--- py/3rd-party/mtTkinter-0.3/mtTkinter.py 1970-01-01 00:00:00 +0000
+++ py/3rd-party/mtTkinter-0.3/mtTkinter.py 2010-07-06 11:31:29 +0000
@@ -0,0 +1,227 @@
+'''Thread-safe version of Tkinter.
+
+Usage:
+
+ import mtTkinter as Tkinter
+ # Use "Tkinter." as usual.
+
+or
+
+ from mtTkinter import *
+ # Use Tkinter module definitions as usual.
+
+This module modifies the original Tkinter module in memory, making all
+functionality thread-safe. It does this by wrapping the Tk class' tk
+instance with an object that diverts calls through an event queue when
+the call is issued from a thread other than the thread in which the Tk
+instance was created. The events are processed in the creation thread
+via an 'after' event.
+
+The modified Tk class accepts two additional keyword parameters on its
+__init__ method:
+ mtDebug:
+ 0 = No debug output (default)
+ 1 = Minimal debug output
+ ...
+ 9 = Full debug output
+ mtCheckPeriod:
+ Amount of time in milliseconds (default 100) between checks for
+ out-of-thread events when things are otherwise idle. Decreasing
+ this value can improve GUI responsiveness, but at the expense of
+ consuming more CPU cycles.
+
+Note that, because it modifies the original Tkinter module (in memory),
+other modules that use Tkinter (e.g., Pmw) reap the benefits automagically
+as long as mtTkinter is imported at some point before extra threads are
+created.
+
+Author: Allen B. Taylor, a.b.taylor@xxxxxxxxx
+'''
+
+from Tkinter import *
+import threading
+import Queue
+
+class _Tk(object):
+ """
+ Wrapper for underlying attribute tk of class Tk.
+ """
+
+ def __init__(self, tk, mtDebug = 0, mtCheckPeriod = 10):
+ self._tk = tk
+
+ # Create the incoming event queue.
+ self._eventQueue = Queue.Queue(1)
+
+ # Identify the thread from which this object is being created so we can
+ # tell later whether an event is coming from another thread.
+ self._creationThread = threading.currentThread()
+
+ # Store remaining values.
+ self._debug = mtDebug
+ self._checkPeriod = mtCheckPeriod
+
+ def __getattr__(self, name):
+ # Divert attribute accesses to a wrapper around the underlying tk
+ # object.
+ return _TkAttr(self, getattr(self._tk, name))
+
+class _TkAttr(object):
+ """
+ Thread-safe callable attribute wrapper.
+ """
+
+ def __init__(self, tk, attr):
+ self._tk = tk
+ self._attr = attr
+
+ def __call__(self, *args, **kwargs):
+ """
+ Thread-safe method invocation.
+ Diverts out-of-thread calls through the event queue.
+ Forwards all other method calls to the underlying tk object directly.
+ """
+
+ # Check if we're in the creation thread.
+ if threading.currentThread() == self._tk._creationThread:
+ # We're in the creation thread; just call the event directly.
+ if self._tk._debug >= 8 or \
+ self._tk._debug >= 3 and self._attr.__name__ == 'call' and \
+ len(args) >= 1 and args[0] == 'after':
+ print 'Calling event directly:', \
+ self._attr.__name__, args, kwargs
+ return self._attr(*args, **kwargs)
+ else:
+ # We're in a different thread than the creation thread; enqueue
+ # the event, and then wait for the response.
+ responseQueue = Queue.Queue(1)
+ if self._tk._debug >= 1:
+ print 'Marshalling event:', self._attr.__name__, args, kwargs
+ self._tk._eventQueue.put((self._attr, args, kwargs, responseQueue))
+ isException, response = responseQueue.get()
+
+ # Handle the response, whether it's a normal return value or
+ # an exception.
+ if isException:
+ exType, exValue, exTb = response
+ raise exType, exValue, exTb
+ else:
+ return response
+
+# Define a hook for class Tk's __init__ method.
+def _Tk__init__(self, *args, **kwargs):
+ # We support some new keyword arguments that the original __init__ method
+ # doesn't expect, so separate those out before doing anything else.
+ new_kwnames = ('mtCheckPeriod', 'mtDebug')
+ new_kwargs = {}
+ for name, value in kwargs.items():
+ if name in new_kwnames:
+ new_kwargs[name] = value
+ del kwargs[name]
+
+ # Call the original __init__ method, creating the internal tk member.
+ self.__original__init__mtTkinter(*args, **kwargs)
+
+ # Replace the internal tk member with a wrapper that handles calls from
+ # other threads.
+ self.tk = _Tk(self.tk, **new_kwargs)
+
+ # Set up the first event to check for out-of-thread events.
+ self.after_idle(_CheckEvents, self)
+
+# Replace Tk's original __init__ with the hook.
+Tk.__original__init__mtTkinter = Tk.__init__
+Tk.__init__ = _Tk__init__
+
+def _CheckEvents(tk):
+ "Event checker event."
+
+ used = False
+ try:
+ # Process all enqueued events, then exit.
+ while True:
+ try:
+ # Get an event request from the queue.
+ method, args, kwargs, responseQueue = \
+ tk.tk._eventQueue.get_nowait()
+ except:
+ # No more events to process.
+ break
+ else:
+ # Call the event with the given arguments, and then return
+ # the result back to the caller via the response queue.
+ used = True
+ if tk.tk._debug >= 2:
+ print 'Calling event from main thread:', \
+ method.__name__, args, kwargs
+ try:
+ responseQueue.put((False, method(*args, **kwargs)))
+ except SystemExit, ex:
+ raise SystemExit, ex
+ except Exception, ex:
+ # Calling the event caused an exception; return the
+ # exception back to the caller so that it can be raised
+ # in the caller's thread.
+ from sys import exc_info
+ exType, exValue, exTb = exc_info()
+ responseQueue.put((True, (exType, exValue, exTb)))
+ finally:
+ # Schedule to check again. If we just processed an event, check
+ # immediately; if we didn't, check later.
+ if used:
+ tk.after_idle(_CheckEvents, tk)
+ else:
+ tk.after(tk.tk._checkPeriod, _CheckEvents, tk)
+
+# Test thread entry point.
+def _testThread(root):
+ text = "This is Tcl/Tk version %s" % TclVersion
+ if TclVersion >= 8.1:
+ try:
+ text = text + unicode("\nThis should be a cedilla: \347",
+ "iso-8859-1")
+ except NameError:
+ pass # no unicode support
+ try:
+ if root.globalgetvar('tcl_platform(threaded)'):
+ text = text + "\nTcl is built with thread support"
+ else:
+ raise RuntimeError
+ except:
+ text = text + "\nTcl is NOT built with thread support"
+ text = text + "\nmtTkinter works with or without Tcl thread support"
+ label = Label(root, text=text)
+ label.pack()
+ button = Button(root, text="Click me!",
+ command=lambda root=root: root.button.configure(
+ text="[%s]" % root.button['text']))
+ button.pack()
+ root.button = button
+ quit = Button(root, text="QUIT", command=root.destroy)
+ quit.pack()
+ # The following three commands are needed so the window pops
+ # up on top on Windows...
+ root.iconify()
+ root.update()
+ root.deiconify()
+ # Simulate button presses...
+ button.invoke()
+ root.after(1000, _pressOk, root, button)
+
+# Test button continuous press event.
+def _pressOk(root, button):
+ button.invoke()
+ try:
+ root.after(1000, _pressOk, root, button)
+ except:
+ pass # Likely we're exiting
+
+# Test. Mostly borrowed from the Tkinter module, but the important bits moved
+# into a separate thread.
+if __name__ == '__main__':
+ import threading
+ root = Tk(mtDebug = 1)
+ thread = threading.Thread(target = _testThread, args=(root,))
+ thread.start()
+ root.mainloop()
+ thread.join()
=== modified file 'py/SConscript'
--- py/SConscript 2010-06-18 13:02:01 +0000
+++ py/SConscript 2010-07-06 11:31:29 +0000
@@ -51,6 +51,7 @@
# ==================
env.Install('$PREFIX/lib/yade$SUFFIX/py',[
env.SharedLibrary('miniEigen',['mathWrap/miniEigen.cpp'],SHLIBPREFIX='',CPPPATH=env['CPPPATH']+['../lib/'],LIBS=env['LIBS']+['core']),
+ env.File('mtTkinter.py','3rd-party/mtTkinter-0.3'),
])
if 'YADE_GTS' in env['CPPDEFINES']:
=== modified file 'py/plot.py'
--- py/plot.py 2010-07-01 09:56:50 +0000
+++ py/plot.py 2010-07-06 11:31:29 +0000
@@ -4,7 +4,16 @@
Module containing utility functions for plotting inside yade. See :ysrc:`scripts/simple-scene-plot.py` or :ysrc:`examples/concrete/uniax.py` for example of usage.
"""
-import matplotlib,os
+
+## all exported names
+__all__=['data','plots','labels','live','liveInterval','autozoom','plot','reset','resetData','splitData','reverse','addData','saveGnuplot']
+
+# multi-threaded support for Tk
+# safe to import even if Tk will not be used
+import mtTkinter as Tkinter
+
+import matplotlib,os,time
+
# running in batch
#
# If GtkAgg is the default, X must be working, which is not the case
@@ -20,8 +29,8 @@
matplotlib.use('Agg')
#matplotlib.use('TkAgg')
-#matplotlib.use('GTKCairo')
-#matplotlib.use('QtAgg')
+#matplotlib.use('GTKAgg')
+##matplotlib.use('QtAgg')
matplotlib.rc('axes',grid=True) # put grid in all figures
import pylab
@@ -32,6 +41,13 @@
labels={}
"Dictionary converting names in data to human-readable names (TeX names, for instance); if a variable is not specified, it is left untranslated."
+live=True
+"Enable/disable live plot updating. Disabled by default for now, since it has a few rough edges."
+liveInterval=1
+"Interval for the live plot updating, in seconds."
+autozoom=True
+"Enable/disable automatic plot rezooming after data update."
+
def reset():
"Reset all plot-related variables (data, plots, labels)"
global data, plots, labels # plotLines
@@ -78,84 +94,133 @@
if name in d: data[name].append(d[name]) #numpy.append(data[name],[d[name]],1)
else: data[name].append(nan)
-def _addPointTypeSpecifier(o):
+# not public functions
+def addPointTypeSpecifier(o):
"""Add point type specifier to simple variable name"""
if type(o) in [tuple,list]: return o
else: return (o,'')
-def _tuplifyYAxis(pp):
+def tuplifyYAxis(pp):
"""convert one variable to a 1-tuple"""
if type(pp) in [tuple,list]: return pp
else: return (pp,)
-def _xlateLabel(l):
+def xlateLabel(l):
"Return translated label; return l itself if not in the labels dict."
global labels
if l in labels.keys(): return labels[l]
else: return l
-def plot(noShow=False):
- """Do the actual plot, which is either shown on screen (and nothing is returned: if *noShow* is False) or returned as object (if *noShow* is True).
-
- You can use
-
- >>> from yade import plot
- >>> plot.plot(noShow=True).savefig('someFile.pdf')
- >>> import os
- >>> os.path.exists('someFile.pdf')
- True
-
- to save the figure to file automatically.
- """
- if not noShow: pylab.ion() ## # no interactive mode (hmmm, I don't know why actually...)
+class LineRef:
+ """Holds reference to plot line and to original data arrays (which change during the simulation),
+ and updates the actual line using those data upon request."""
+ def __init__(self,line,xdata,ydata):
+ self.line,self.xdata,self.ydata=line,xdata,ydata
+ def update(self):
+ self.line.set_xdata(self.xdata)
+ self.line.set_ydata(self.ydata)
+
+currLineRefs=[]
+liveTimeStamp=0 # timestamp when live update was started, so that the old thread knows to stop if that changes
+nan=float('nan')
+
+def createPlots():
+ global currLineRefs
+ figs=set([l.line.get_axes().get_figure() for l in currLineRefs]) # get all current figures
+ for f in figs: pylab.close(f) # close those
+ currLineRefs=[] # remove older plots (breaks live updates of windows that are still open)
+ if len(plots)==0: return # nothing to plot
for p in plots:
p=p.strip()
pylab.figure()
- plots_p=[_addPointTypeSpecifier(o) for o in _tuplifyYAxis(plots[p])]
+ plots_p=[addPointTypeSpecifier(o) for o in tuplifyYAxis(plots[p])]
plots_p_y1,plots_p_y2=[],[]; y1=True
+ missing={} # missing data columns
+ if p not in data.keys(): missing[p]=nan
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]=
- pylab.plot(*sum([[data[p],data[d[0]],d[1]] for d in plots_p_y1],[]))
- 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 d[0] not in data.keys(): missing[d[0]]=nan
+ addData(missing)
+ # create y1 lines
+ for d in plots_p_y1:
+ line,=pylab.plot(data[p],data[d[0]],d[1])
+ currLineRefs.append(LineRef(line,data[p],data[d[0]]))
+ # create the legend
+ 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]))
+ # create y2 lines, if any
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]+=
- [pylab.plot(*sum([[data[p],data[d[0]],d[1]] for d in plots_p_y2],[]))]
- pylab.legend([_xlateLabel(_p[0]) for _p in plots_p_y2],loc='upper right')
+ for d in plots_p_y2:
+ line,=pylab.plot(data[p],data[d[0]],d[1])
+ currLineRefs.append(LineRef(line,data[p],data[d[0]]))
+ # legend
+ 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))
+ 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
+
+def liveUpdate(timestamp):
+ global liveTimeStamp
+ liveTimeStamp=timestamp
+ while True:
+ if not live or liveTimeStamp!=timestamp: return
+ figs,axes=set(),set()
+ for l in currLineRefs:
+ l.update()
+ figs.add(l.line.get_figure())
+ axes.add(l.line.get_axes())
+ if autozoom:
+ for ax in axes:
+ try:
+ ax.relim() # recompute axes limits
+ ax.autoscale_view()
+ except RuntimeError: pass # happens if data are being updated and have not the same dimension at the very moment
+ for fig in figs:
+ fig.canvas.draw()
+ time.sleep(liveInterval)
+
+
+def plot(noShow=False):
+ """Do the actual plot, which is either shown on screen (and nothing is returned: if *noShow* is False) or returned as object (if *noShow* is True).
+
+ You can use
+
+ >>> from yade import plot
+ >>> plot.plot(noShow=True).savefig('someFile.pdf')
+ >>> import os
+ >>> os.path.exists('someFile.pdf')
+ True
+
+ to save the figure to file automatically.
+ """
+ createPlots()
+ global currLineRefs
+ if not noShow:
+ if live:
+ import thread
+ thread.start_new_thread(liveUpdate,(time.time(),))
+ # pylab.show() # this blocks for some reason; call show on figures directly
+ figs=set([l.line.get_axes().get_figure() for l in currLineRefs])
+ for f in figs: f.show()
+ else: return pylab.gcf() # return the current figure
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`.
-:parameters:
- baseName:
- used for creating baseName.gnuplot (command file for gnuplot),
- associated baseName.data (data) and output files (if applicable) in the form baseName.[plot number].extension
- term:
- specify the gnuplot terminal;
- defaults to x11, in which case gnuplot will draw persistent windows to screen and terminate; other useful terminals are 'png', 'cairopdf' and so on
- extension:
- defaults to terminal name; fine for png for example; if you use 'cairopdf', you should also say extension='pdf' however
- timestamp:
- append numeric time to the basename
- varData:
- whether file to plot will be declared as variable or be in-place in the plot expression
- comment:
- a user comment (may be multiline) that will be embedded in the control file
+:param baseName: used for creating baseName.gnuplot (command file for gnuplot), associated ``baseName.data.bz2`` (data) and output files (if applicable) in the form ``baseName.[plot number].extension``
+:param term: specify the gnuplot terminal; defaults to ``x11``, in which case gnuplot will draw persistent windows to screen and terminate; other useful terminals are ``png``, ``cairopdf`` and so on
+:param extension: extension for ``baseName`` defaults to terminal name; fine for png for example; if you use ``cairopdf``, you should also say ``extension='pdf'`` however
+:param bool timestamp: append numeric time to the basename
+:param bool varData: whether file to plot will be declared as variable or be in-place in the plot expression
+:param comment: a user comment (may be multiline) that will be embedded in the control file
-Returns name fo the gnuplot file created.
+:return: name of the gnuplot file created.
"""
import time,bz2
if len(data.keys())==0: raise RuntimeError("No data for plotting were saved.")
@@ -178,10 +243,10 @@
i=0
for p in plots:
p=p.strip()
- plots_p=[_addPointTypeSpecifier(o) for o in _tuplifyYAxis(plots[p])]
+ plots_p=[addPointTypeSpecifier(o) for o in tuplifyYAxis(plots[p])]
if term in ['wxt','x11']: fPlot.write("set term %s %d persist\n"%(term,i))
else: fPlot.write("set term %s; set output '%s.%d.%s'\n"%(term,baseNameNoPath,i,extension))
- fPlot.write("set xlabel '%s'\n"%_xlateLabel(p))
+ fPlot.write("set xlabel '%s'\n"%xlateLabel(p))
fPlot.write("set grid\n")
fPlot.write("set datafile missing 'nan'\n")
if title: fPlot.write("set title '%s'\n"%title)
@@ -191,46 +256,14 @@
y1=False; continue
if y1: plots_y1.append(d)
else: plots_y2.append(d)
- fPlot.write("set ylabel '%s'\n"%(','.join([_xlateLabel(_p[0]) for _p in plots_y1])))
+ fPlot.write("set ylabel '%s'\n"%(','.join([xlateLabel(_p[0]) for _p in plots_y1])))
if len(plots_y2)>0:
- fPlot.write("set y2label '%s'\n"%(','.join([_xlateLabel(_p[0]) for _p in plots_y2])))
+ fPlot.write("set y2label '%s'\n"%(','.join([xlateLabel(_p[0]) for _p in plots_y2])))
fPlot.write("set y2tics\n")
ppp=[]
- for pp in plots_y1: ppp.append(" %s using %d:%d title 'â %s(%s)' with lines"%(dataFile,vars.index(p)+1,vars.index(pp[0])+1,_xlateLabel(pp[0]),_xlateLabel(p),))
- for pp in plots_y2: ppp.append(" %s using %d:%d title '%s(%s) â' with lines axes x1y2"%(dataFile,vars.index(p)+1,vars.index(pp[0])+1,_xlateLabel(pp[0]),_xlateLabel(p),))
+ for pp in plots_y1: ppp.append(" %s using %d:%d title 'â %s(%s)' with lines"%(dataFile,vars.index(p)+1,vars.index(pp[0])+1,xlateLabel(pp[0]),xlateLabel(p),))
+ for pp in plots_y2: ppp.append(" %s using %d:%d title '%s(%s) â' with lines axes x1y2"%(dataFile,vars.index(p)+1,vars.index(pp[0])+1,xlateLabel(pp[0]),xlateLabel(p),))
fPlot.write("plot "+",".join(ppp)+"\n")
i+=1
fPlot.close()
return baseName+'.gnuplot'
-
-
-
-import random
-if __name__ == "__main__":
- for i in range(10):
- addData({'a':random.random(),'b':random.random(),'t':i*.001,'i':i})
- print data
- for i in range(15):
- addData({'a':random.random(),'c':random.random(),'d':random.random(),'one':1,'t':(i+10)*.001,'i':i+10})
- print data
- # all lists must have the same length
- l=set([len(data[n]) for n in data])
- print l
- assert(len(l)==1)
- plots={'t':('a',('b','g^'),'d'),'i':('a',('one','g^'))}
- fullPlot()
- print "PLOT DONE!"
- fullPlot()
- plots['t']=('a',('b','r^','d'))
- print "FULLÂ PLOTÂ DONE!"
- for i in range(20):
- addData({'d':.1,'a':.5,'c':.6,'c':random.random(),'t':(i+25)*0.001,'i':i+25})
- updatePlot()
- print "UPDATED!"
- print data['d']
- import time
- #time.sleep(60)
- killPlots()
- #pylab.clf()
-
-
=== modified file 'py/yadeWrapper/yadeWrapper.cpp'
--- py/yadeWrapper/yadeWrapper.cpp 2010-06-13 21:25:46 +0000
+++ py/yadeWrapper/yadeWrapper.cpp 2010-07-06 11:31:29 +0000
@@ -9,7 +9,10 @@
#include<boost/python.hpp>
#include<boost/python/raw_function.hpp>
-#include<boost/python/suite/indexing/vector_indexing_suite.hpp>
+// unused now
+#if 0
+ #include<boost/python/suite/indexing/vector_indexing_suite.hpp>
+#endif
#include<boost/bind.hpp>
#include<boost/lambda/bind.hpp>
#include<boost/thread/thread.hpp>
Follow ups