\( \usepackage{euler} % must be loaded before fontspec for the whole doc (below); this must be kept for pngmath, however \usepackage{hyperref} \usepackage{amsmath} \usepackage{amsbsy} %\usepackage{mathabx} \usepackage{underscore} \usepackage[all]{xy} % Metadata of the pdf output \hypersetup{pdftitle={Yade Documentation}} \hypersetup{pdfauthor={Smilauer, V., et al.}} \hypersetup{pdfkeywords={Discrete element method, granular materials, contact law, hydromechanical coupling}} % symbols \renewcommand{\mat}{\boldsymbol} \renewcommand{\vec}{\boldsymbol} \renewcommand{\tens}{\boldsymbol} %normalized and locfram here \def\normalized#1{\widehat{#1}} \def\locframe#1{\widetilde{#1}} % timestep \def\Dt{\Delta t} \def\Dtcr{\Dt_{\rm cr}} % algorithm complexity \def\bigO#1{{\mathcal{O}(#1)}} % variants for greek symbols \let\epsilon\varepsilon \let\theta\vartheta \let\phi\varphi % shorthands \let\sig\sigma \let\eps\epsilon % variables at different points of time \def\prev#1{#1^-} \def\pprev#1{#1^\ominus} \def\curr#1{#1^{\circ}} \def\nnext#1{#1^\oplus} \def\next#1{#1^+} % shorthands for geometry \def\currn{\curr{\vec{n}}} \def\currC{\curr{\vec{C}}} \def\uT{\vec{u}_T} \def\curruT{\curr{\vec{u}}_T} \def\prevuT{\prev{\vec{u}}_T} \def\currn{\curr{\vec{n}}} \def\prevn{\prev{\vec{n}}} % motion \def\pprevvel{\pprev{\dot{\vec{u}}}} \def\nnextvel{\nnext{\dot{\vec{u}}}} \def\curraccel{\curr{\ddot{\vec{u}}}} \def\prevpos{\prev{\vec{u}}} \def\currpos{\curr{\vec{u}}} \def\nextpos{\next{\vec{u}}} \def\curraaccel{\curr{\dot{\vec{\omega}}}} \def\pprevangvel{\pprev{\vec{\omega}}} \def\nnextangvel{\nnext{\vec{\omega}}} \def\loccurr#1{\curr{\locframe{#1}}} \def\numCPU{n_{\rm cpu}} \DeclareMathOperator{\Align}{Align} \DeclareMathOperator{\sign}{sgn} % sorting algorithms \def\isleq#1{\currelem{#1}\ar@/^/[ll]^{\leq}} \def\isnleq#1{\currelem{#1}\ar@/^/[ll]^{\not\leq}} \def\currelem#1{\fbox{$#1$}} \def\sortSep{||} \def\sortInv{\hbox{\phantom{||}}} \def\sortlines#1{\xymatrix@=3pt{#1}} \def\crossBound{||\mkern-18mu<} \)

# 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.

yade.plot.addAutoData()

  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, where `name` 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)

  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.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.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.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.live = False

  Enable/disable live plot updating.

yade.plot.liveInterval = 1

  Interval for the live plot updating, in seconds.

yade.plot.plot(noShow=False, subPlots=True)

  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 is `True`, 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.plots = {'i': ('t',), 'i ': ('z1', 'v1')}

  dictionary x-name -> (yspec,…), where yspec is either y-name or (y-name,’line-specification’). If `(yspec,...)` is `None`, then the plot has meaning of image, which will be taken from respective field of plot.imgData.

yade.plot.reset()

  Reset all plot-related variables (data, plots, labels)

yade.plot.resetData()

  Reset all plot data; keep plots and labels intact.

yade.plot.reverseData()

  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)

  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) with `numpy.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)

  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 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 – extension for `baseName` defaults to terminal name; fine for png for example; if you use `cairopdf`, you should also say `extension='pdf'` however

    - timestamp (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)

  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.setLiveForceAlwaysUpdate(forceLiveUpdate)

  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 current `bool` value of forced updates if the call was a success, otherwise it returns a `str` with explanation why it failed. It is guaranteed to work if simulation was paused with O.pause() call.

yade.plot.splitData()

  Make all plots discontinuous at this point (adds nan’s to all data fields)