yade.plot module¶
Module containing utility functions for plotting inside yade. See examples/simple-scene/simple-scene-plot.py or examples/concrete/uniax.py for example of usage.
- class yade.plot.LineRef(inherits object)[source]¶
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.
- yade.plot.addAutoData()[source]¶
Add data by evaluating contents of plot.plots. Expressions rasing exceptions will be handled gracefully, but warning is printed for each.
>>> from yade import plot >>> from pprint import pprint >>> O.reset() >>> plot.resetData() >>> plot.plots={'O.iter':('O.time',None,'numParticles=len(O.bodies)')} >>> plot.addAutoData() >>> pprint(plot.data) {'O.iter': [0], 'O.time': [0.0], 'numParticles': [0]}
Note that each item in plot.plots can be
an expression to be evaluated (using the
eval
builtin);name=expression
string, wherename
will appear as label in plots, and expression will be evaluated each time;a dictionary-like object – current keys are labels of plots and current values are added to plot.data. The contents of the dictionary can change over time, in which case new lines will be created as necessary.
A simple simulation with plot can be written in the following way; note how the energy plot is specified.
>>> from yade import plot, utils >>> from yade.minieigenHP import * # not needed in actual yade session, but needed for doctests >>> from yade.wrapper import * # not needed in actual yade session, but needed for doctests >>> plot.plots={'i=O.iter':(O.energy,None,'total energy=O.energy.total()')} >>> # we create a simple simulation with one ball falling down >>> plot.resetData() >>> O.bodies.append(utils.sphere((0,0,0),1)) 0 >>> O.dt=utils.PWaveTimeStep() >>> O.engines=[ ... ForceResetter(), ... GravityEngine(gravity=(0,0,-10),warnOnce=False), ... NewtonIntegrator(damping=.4,kinSplit=True), ... # get data required by plots at every step ... PyRunner(command='yade.plot.addAutoData()',iterPeriod=1,initRun=True) ... ] >>> O.trackEnergy=True >>> O.run(2,True) >>> pprint(plot.data) {'gravWork': [0.0, -25.13274...], 'i': [0, 1], 'kinRot': [0.0, 0.0], 'kinTrans': [0.0, 7.5398...], 'nonviscDamp': [0.0, 10.0530...], 'total energy': [0.0, -7.5398...]}
- yade.plot.addData(*d_in, **kw)[source]¶
Add data from arguments name1=value1,name2=value2 to yade.plot.data. (the old {‘name1’:value1,’name2’:value2} is deprecated, but still supported)
New data will be padded with nan’s, unspecified data will be nan (nan’s don’t appear in graphs). This way, equal length of all data is assured so that they can be plotted one against any other.
>>> from yade import plot >>> from yade.minieigenHP import * # not needed in actual yade session, but needed for doctests >>> from pprint import pprint >>> plot.resetData() >>> plot.addData(a=1) >>> plot.addData(b=2) >>> plot.addData(a=3,b=4) >>> pprint(plot.data) {'a': [1, nan, 3], 'b': [nan, 2, 4]}
Some sequence types can be given to addData; they will be saved in synthesized columns for individual components.
>>> plot.resetData() >>> plot.addData(c=Vector3(5,6,7),d=Matrix3(8,9,10, 11,12,13, 14,15,16)) >>> pprint(plot.data) {'c_x': [5.0], 'c_y': [6.0], 'c_z': [7.0], 'd_xx': [8.0], 'd_xy': [9.0], 'd_xz': [10.0], 'd_yx': [11.0], 'd_yy': [12.0], 'd_yz': [13.0], 'd_zx': [14.0], 'd_zy': [15.0], 'd_zz': [16.0]}
- yade.plot.addDataColumns(dd)[source]¶
Add new columns with NaN data, without adding anything to other columns. Does nothing for columns that already exist
- yade.plot.addPointTypeSpecifier(o, noSplit=False)[source]¶
Add point type specifier to simple variable name; optionally take only the part before ‘=’ from the first item.
- yade.plot.afterCurrentAlpha = 0.2¶
Color alpha value for part of lines after plot.current, between 0 (invisible) to 1 (full color)
- yade.plot.autozoom = True¶
Enable/disable automatic plot rezooming after data update. Sometimes rezooming must be skipped unless a call to plot.setLiveForceAlwaysUpdate forces it to work.
- yade.plot.axesWd = 0¶
Linewidth (in points) to make x and y axes better visible; not activated if non-positive.
- yade.plot.createTitleFrame(out, size, title)[source]¶
create figure with title and save to file; a figure object must be opened to get the right size
- yade.plot.current = -1¶
Point that is being tracked with a scatter point. -1 is for the last point, set to nan to disable.
- yade.plot.cycler(*args, **kwargs)[source]¶
Create a new Cycler object from a single positional argument, a pair of positional arguments, or the combination of keyword arguments.
cycler(arg) cycler(label1=itr1[, label2=iter2[, …]]) cycler(label, itr)
Form 1 simply copies a given Cycler object.
Form 2 composes a Cycler as an inner product of the pairs of keyword arguments. In other words, all of the iterables are cycled simultaneously, as if through zip().
Form 3 creates a Cycler from a label and an iterable. This is useful for when the label cannot be a keyword argument (e.g., an integer or a name that has a space in it).
Parameters¶
- argCycler
Copy constructor for Cycler (does a shallow copy of iterables).
- labelname
The property key. In the 2-arg form of the function, the label can be any hashable object. In the keyword argument form of the function, it must be a valid python identifier.
- itriterable
Finite length iterable of the property values. Can be a single-property Cycler that would be like a key change, but as a shallow copy.
Returns¶
- cyclerCycler
New Cycler for the given property
- yade.plot.data = {'eps': [0.0001, 0.001, nan], 'force': [nan, nan, 1000.0], 'sigma': [12, nan, nan]}¶
Global dictionary containing all data values, common for all plots, in the form {‘name’:[value,…],…}. Data should be added using plot.addData function. All [value,…] columns have the same length, they are padded with NaN if unspecified.
- yade.plot.imgData = {}¶
Dictionary containing lists of strings, which have the meaning of images corresponding to respective plot.data rows. See plot.plots on how to plot images.
- yade.plot.labels = {}¶
Dictionary converting names in data to human-readable names (TeX names, for instance); if a variable is not specified, it is left untranslated.
- yade.plot.legendLoc = ('upper left', 'upper right')¶
Location of the y1 and y2 legends on the plot, if y2 is active.
- yade.plot.live = True¶
Enable/disable live plot updating.
- yade.plot.liveForceAlwaysUpdate = False¶
- yade.plot.liveInterval = 1¶
Interval for the live plot updating, in seconds.
- yade.plot.plot(noShow=False, subPlots=True)[source]¶
Do the actual plot, which is either shown on screen (and nothing is returned: if noShow is
False
- note that your yade compilation should present qt4 feature so that figures can be displayed) or, if noShow isTrue
, returned as matplotlib’s Figure object or list of them.You can use
>>> from yade import plot >>> plot.resetData() >>> plot.plots={'foo':('bar',)} >>> plot.plot(noShow=True).savefig('someFile.pdf') >>> import os >>> os.path.exists('someFile.pdf') True >>> os.remove('someFile.pdf')
to save the figure to file automatically.
Note
For backwards compatibility reasons, noShow option will return list of figures for multiple figures but a single figure (rather than list with 1 element) if there is only 1 figure.
- yade.plot.plotSyncLock = <unlocked _thread.lock object>¶
A lock (mutex) used for synchronizing live drawing (happens every
liveInterval
seconds) and adding more plot data. Also see https://gitlab.com/yade-dev/trunk/-/issues/110
- yade.plot.plots = {'i': ('t',), 'i ': ('z1', 'v1')}¶
dictionary x-name -> (yspec,…), where yspec is either y-name or (y-name,’line-specification’). If
(yspec,...)
isNone
, then the plot has meaning of image, which will be taken from respective field of plot.imgData.
- yade.plot.reverseData()[source]¶
Reverse yade.plot.data order.
Useful for tension-compression test, where the initial (zero) state is loaded and, to make data continuous, last part must end in the zero state.
- yade.plot.saveDataTxt(fileName, vars=None, headers=None)[source]¶
Save plot data into a (optionally compressed) text file. The first line contains a comment (starting with
#
) giving variable name for each of the columns. This format is suitable for being loaded for further processing (outside yade) withnumpy.genfromtxt
function, which recognizes those variable names (creating numpy array with named entries) and handles decompression transparently.>>> from yade import plot >>> from pprint import pprint >>> plot.reset() >>> plot.addData(a=1,b=11,c=21,d=31) # add some data here >>> plot.addData(a=2,b=12,c=22,d=32) >>> pprint(plot.data) {'a': [1, 2], 'b': [11, 12], 'c': [21, 22], 'd': [31, 32]} >>> plot.saveDataTxt('/tmp/dataFile.txt.tar.gz',vars=('a','b','c')) >>> import numpy >>> d=numpy.genfromtxt('/tmp/dataFile.txt.tar.gz',dtype=None,names=True) >>> d['a'] array([1, 2]) >>> d['b'] array([11, 12]) >>> import os # cleanup >>> os.remove('/tmp/dataFile.txt.tar.gz')
- Parameters:
fileName – file to save data to; if it ends with
.bz2
/.gz
, the file will be compressed using bzip2 / gzip.vars – Sequence (tuple/list/set) of variable names to be saved. If
None
(default), all variables in plot.plot are saved.headers – Set of parameters to write on header
- yade.plot.saveGnuplot(baseName, term='wxt', extension=None, timestamp=False, comment=None, title=None, varData=False)[source]¶
Save data added with plot.addData into (compressed) file and create .gnuplot file that attempts to mimick plots specified with plot.plots.
- Parameters:
baseName – used for creating baseName.gnuplot (command file for gnuplot), associated
baseName.data.bz2
(data) and output files (if applicable) in the formbaseName.[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 arepng
,cairopdf
and so onextension – extension for
baseName
defaults to terminal name; fine for png for example; if you usecairopdf
, you should also sayextension='pdf'
howevertimestamp (bool) – append numeric time to the basename
varData (bool) – 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
- Returns:
name of the gnuplot file created.
- yade.plot.savePlotSequence(fileBase, stride=1, imgRatio=(5, 7), title=None, titleFrames=20, lastFrames=30)[source]¶
Save sequence of plots, each plot corresponding to one line in history. It is especially meant to be used for utils.makeVideo.
- Parameters:
stride – only consider every stride-th line of history (default creates one frame per each line)
title – Create title frame, where lines of title are separated with newlines (
\n
) and optional subtitle is separated from title by double newline.titleFrames (int) – Create this number of frames with title (by repeating its filename), determines how long the title will stand in the movie.
lastFrames (int) – Repeat the last frame this number of times, so that the movie does not end abruptly.
- Returns:
List of filenames with consecutive frames.
- yade.plot.savePylab(baseName, timestamp=False, title=None)[source]¶
This function is not finished, do not use it.
- yade.plot.scatterMarkerKw = {'marker': [(0.0, 0.0), (-30.0, 10.0), (-25, 0), (-30.0, -10.0)]}¶
Parameters for the current position marker
- yade.plot.scientific = True¶
Use scientific notation for axes ticks.
- yade.plot.setLiveForceAlwaysUpdate(forceLiveUpdate)[source]¶
The plot.liveInterval and plot.live control live refreshing of the plot during calculations. The refreshing is done in a separate thread, so that it does not interfere with calculations. Drawing the data will not work when at exactly the same time it is being updated in other thread. Use
yade.plot.setLiveForceAlwaysUpdate(True)
if you want calculations to PAUSE during the plot updates. This function returns currentbool
value of forced updates if the call was a success, otherwise it returns astr
with explanation why it failed. It is guaranteed to work if simulation was paused with O.pause() call.
- yade.plot.splitData()[source]¶
Make all plots discontinuous at this point (adds nan’s to all data fields)
- yade.plot.xlateLabel(l)[source]¶
Return translated label; return l itself if not in the labels dict.
- yade.plot.xylabels = {}¶
Dictionary of 2-tuples specifying (xlabel,ylabel) for respective plots; if either of them is None, the default auto-generated title is used.