plot multiple plots at different iterPeriods

Asked by Alexander Eulitz [Eugen] on 2013-04-25

Hi,
following examples/normalInelasticity-test.py I created multiple plots for my simulation by writing:

plot.plots={'t':('Fn', 'Fmess',), 't_xyz':('Fx', 'Fy', 'Fz',), 't_perf':('speed',)}
plot.plot(noShow=False, subPlots=True)
#...
O.run()

at the end of my script.

I'm using diffrent PyRunners to addData to the plot. These Pyrunners have different iterPeriods.
One PyRunner generates data für the plots 't':('Fn', 'Fmess',) and 't_xyz':('Fx', 'Fy', 'Fz',) and adds it via:

force=plot.addData(t=O.time,t_xyz=O.time, Fn=normalforce, Fmess=Fm, Fx=Fx,Fy=Fy,Fz=Fz)

The other one calls updatePerformancePlot() which adds performance data of the simulation (aka speed of simulation) to the third plot 't_perf':('speed',):

def updatePerformancePlot():
 """Berechnet die Performance (Speed) zwischen zwei Ausführungen dieser Funktion und gibt sie im Plot aus.
 """
 global start, finish
 start=finish
 #start=performancePlotter.realLast #doesn't work as supposed to
 finish=O.realtime
 #finish=time.time() #doesn't work as supposed to
 nIter=performancePlotter.iterPeriod
 speed=round(nIter/(finish-start),1)
 plot.addData(t_perf=O.time, speed=speed)

In my simulation performance recording (shown in the third subpot) begins at first iteration wheras force recording (shown in the first two subplots) starts at a later point.
The plots behave as they are supposed as long as only one plot.addData(...) function is called.
But as soon as force recording should start, data in the plots wont be updated anymore.

In the Inelsticity example this wasnt of any interesest, because all data was plotted in the same pyrunner that is at same iterPeriod with ONE plot.addData(...) function.
How can I realize multiple plot.addData calls from diffrent pyrunners at diffrent "periodicity" (iterPeriods)?

Thank you guys again for your help and effort

Question information

Language:
English Edit question
Status:
Solved
For:
Yade Edit question
Assignee:
No assignee Edit question
Solved by:
Alexander Eulitz [Eugen]
Solved:
2013-04-25
Last query:
2013-04-25
Last reply:
2013-04-25
Christian Jakob (jakob-ifgt) said : #1

Hallo Eugen,

Ich persoenlich bevorzuge Daten waehrend der Rechnung in einer Textdatei zu speichern ...
Personally I prefer to store data during simulation in a text file ...

e.g. every 100th step:

f = open(outputfilename, 'a')
f.write('%f %f %f %f %f' % (vel_av,coord_num,poro_now,F_unbal,rel_time))
for x in range(0,3):
 for y in range(0,3):
  f.write(' %f' % cap_stress[x,y])
f.write('%f %f %f %f %f %f %f %f %f %f' % (E_kin_trans,E_kin_rot,E_pot,E_total,local_damp_dissip,norm_damp_dissip,shear_damp_dissip,fric_dissip,plastic_dissip,E_dissip))
f.write('\n')
f.close()

Nachdem die Rechnung beendet ist, wird die Datei ausgelesen und die plots erzeugt...
After simulation finished, file is read and plots are created ...

(here my full script:)

#!/usr/bin/python
# -*- coding: utf-8 -*-

vel_av_list = []
coord_list = []
poro_list = []
F_unbal_list = []
rel_time_list = []
trace_stress = []
E_kin_trans_list= []
E_kin_rot_list = []
E_pot_list = []
E_total_list = []
local_damp_dissip_list = []
norm_damp_dissip_list = []
shear_damp_dissip_list = []
fric_dissip_list = []
plastic_dissip_list = []
E_dissip_list = []

#get data from table file:
f = open(outputfilename, 'r')
c_line = 0
for line in f:
 c_line += 1
 if c_line == 1:
  header = str(line)
 else:
  tmp_line = str(line)
  tmp_value_list = tmp_line.split(" ")
  vel_av_list.append(float(tmp_value_list[0]))
  coord_list.append(float(tmp_value_list[1]))
  poro_list.append(float(tmp_value_list[2]))
  F_unbal_list.append(float(tmp_value_list[3]))
  rel_time_list.append(float(tmp_value_list[4]))
  trace_stress.append(float(tmp_value_list[5]) + float(tmp_value_list[9]) + float(tmp_value_list[13]))
  E_kin_trans_list.append(float(tmp_value_list[14]))
  E_kin_rot_list.append(float(tmp_value_list[15]))
  E_pot_list.append(float(tmp_value_list[16]))
  E_total_list.append(float(tmp_value_list[17]))
  local_damp_dissip_list.append(float(tmp_value_list[18]))
  norm_damp_dissip_list.append(float(tmp_value_list[19]))
  shear_damp_dissip_list.append(float(tmp_value_list[20]))
  fric_dissip_list.append(float(tmp_value_list[21]))
  plastic_dissip_list.append(float(tmp_value_list[22]))
  E_dissip_list.append(float(tmp_value_list[23]))
f.close()

#get maximum and minimum of porosity:
poro_max = max(poro_list)
poro_min = min(poro_list)

### make a nice plot:
from pylab import * #overwrites angle, box, ... see 0-generate.py

font_global = {'family':'serif','weight':'normal'}
rc('font', **font_global)

# adapt font and style to latex-similar pendant:
from matplotlib.font_manager import FontProperties
font = FontProperties()
font.set_size('x-large')
font.set_family('serif')
# for more arguments see here:
# http://matplotlib.sourceforge.net/api/font_manager_api.html?highlight=set_size#matplotlib.font_manager.FontProperties

figure()
plot(rel_time_list, vel_av_list, label = 'average velocity of particles')
xlabel('time in [s]',fontproperties=font)
ylabel('average velocity in [m/s]',fontproperties=font)
savefig(savefigname_av_vel)

figure()
plot(rel_time_list, coord_list, label = 'coordination number')
xlabel('time in [s]',fontproperties=font)
ylabel('coordination number',fontproperties=font)
savefig(savefigname_coord)

figure()
plot(rel_time_list, poro_list, label = 'porosity')
xlabel('time in [s]',fontproperties=font)
ylabel('porosity in [%]',fontproperties=font)
ylim(poro_min-1,poro_max+1)
savefig(savefigname_poro)

figure()
plot(rel_time_list, F_unbal_list, label = 'unbalanced force')
xlabel('time in [s]',fontproperties=font)
ylabel('unbalanced force in [%]',fontproperties=font)
savefig(savefigname_unbal)

figure()
plot(rel_time_list, trace_stress, label = 'capillary stress')
xlabel('time in [s]',fontproperties=font)
ylabel('capillary stress in [N/m^2]',fontproperties=font)
savefig(savefigname_stress)

figure()
plot(rel_time_list, E_kin_trans_list, label = 'translational energy')
plot(rel_time_list, E_kin_rot_list, label = 'rotational energy')
plot(rel_time_list, E_pot_list, label = 'potential energy')
plot(rel_time_list, E_total_list, label = 'total energy (sum)')
xlabel('time in [s]',fontproperties=font)
ylabel('energy in [J]',fontproperties=font)
legend()
savefig(savefigname_energy)

figure()
plot(rel_time_list, local_damp_dissip_list, label = 'energy dissipation from local damping')
plot(rel_time_list, norm_damp_dissip_list, label = 'energy dissipation from viscous normal damping')
plot(rel_time_list, shear_damp_dissip_list, label = 'energy dissipation from viscous shear damping')
plot(rel_time_list, fric_dissip_list, label = 'energy dissipation from friction')
plot(rel_time_list, plastic_dissip_list, label = 'energy dissipation from plastic deformation')
plot(rel_time_list, E_dissip_list, label = 'total energy dissipation (sum)')
xlabel('time in [s]',fontproperties=font)
ylabel('energy dissipation in [J]',fontproperties=font)
legend()
savefig(savefigname_energy_dissip)

hope it helps,

Gruss aus Freiberg ;)

Christian

Jan Stránský (honzik) said : #2

Hello Eugen,

But as soon as force recording should start, data in the plots wont be
> updated anymore.
>

do you ask about live plot updates, or the plot data in general?

>
> In the Inelsticity example this wasnt of any interesest, because all data
> was plotted in the same pyrunner that is at same iterPeriod with ONE
> plot.addData(...) function.
> How can I realize multiple plot.addData calls from diffrent pyrunners at
> diffrent "periodicity" (iterPeriods)?
>

for only storing the data and postprocessing then using gnuplot [1], it is
no problem.

If I understood it wrong, sorry for spamming :-)

cheers
Jan

PS: next time please provide us with minimal working example reproducing
your problem, usually it is then much easier to help

[1] https://yade-dem.org/doc/yade.plot.html#yade.plot.saveGnuplot

Hello und schöne Grüße nach Freiberg aus Berlin,
thank you both. Id really like to see the plots live when I run my simulation in batch mode. ;)
 Sorry I forgot to mention it...
Saving it as a textfile is a great idea too. In fact I save it via gnuplot at certain timesteps - which is really a great Yade feature.

I tried using just one plot.addData function and it works fine, but how can I use two addPlot calls in different pyrunners?

Next time youll get a more extensive script :)

Anton Gladky (gladky-anton) said : #4

2013/4/25 Eugen Kubowsky <email address hidden>:
> Eugen Kubowsky is still having a problem:
> Hello und schöne Grüße nach Freiberg aus Berlin,

Cool, we have a nice "triangle" : Berlin, Freiberg, Prague and Grenoble.

> Id really like to see the plots live when I run my simulation in batch mode.

Do you know, that you can observe them in the web-browser?

Anton

>> Eugen Kubowsky is still having a problem:
>> Hello und schöne Grüße nach Freiberg aus Berlin,
> Cool, we have a nice "triangle" : Berlin, Freiberg, Prague and Grenoble.
Berlin is missing here. Please Eugen :)
https://www.ohloh.net/p/yade/map

All users/devs are invited to subscribe at Ohloo to fill this google map.

For different periods, I don't know any solution. I don't think it is
possible as yade plot is using a global table where all columns are
supposed to have the same length.

Bruno

p.s. Eugen, yade's wiki is back

@bruno: done ;) berlin is listed as user location. Are you sure about the wiki? what have you done to fix stability issues?
@Anton: Yes, I know how to observe the batch status using webbrowser of the simulating computer localhost:9080 by defaut. But thanks for asking ;) this is an amazing feature of Yade btw.

I solved my problem. The problem was at an other part of the code.
So it is indeed possible to use plot.addData() multiple times for your plots.

Heres an example of the saveGnuplot-Output of my data.
t, t_perf, and t_xyz represent simulated time (so called virtPeriod).
t and t_xyz are the same. I just added t_xyz because I want Fx,Fy and Fz be plotted in a diffrent window than Fmess and Fn.

You're right Bruno, the columns of the global yade plot table have to have the same length. But calling plot.addData() will take care of it by inserting 'nan' to all columns which are not specified inside the brackets of addData().

# Fmess Fn Fx Fy Fz speed t t_perf t_xyz
nan nan nan nan nan 46.1 nan 1.0 nan
nan nan nan nan nan 43.5 nan 2.0 nan
nan nan nan nan nan 39.5 nan 3.0 nan
nan nan nan nan nan 39.4 nan 4.0 nan
nan nan nan nan nan 39.9 nan 5.0 nan
0.0106798197616 0.00806601710035 -0.0290951885327 0.0106798197616 0.147109672769 nan 6.0 nan 6.0
nan nan nan nan nan 39.1 nan 6.0 nan
nan nan nan nan nan 28.0 nan 6.001 nan
-0.0439469776697 0.00750723497695 -0.0125561404419 -0.0439471354583 0.144946720092 nan 6.002 nan 6.002

so it is possible to create to Engines that plot different data at different times.
Here's an example, maybe we can add it at the plot.addData documentation?

O.engines+=[ PyRunner(iterPeriod=1,command="myAddPlotData()", label='plotPlotter', dead=False),
 PyRunner(iterPeriod=2000,command="updatePerformancePlot()", label='performancePlotter', dead=False)]

#...data producing part
# In some cases it is useful to set the "dead" flag of one or both of the "plotengines" to True. Doing this you can start plotting at a certian time or iteration by changing the flag by e.g. plotPlotter.dead=True

plot.plots={'t':('Fn', 'Fmess',), 't_xyz':('Fx', 'Fy', 'Fz',), 't_perf':('speed',)} #creates 3 different plots
fig=plot.plot(noShow=True)#because I use batch mode I dont need the plots to be plotted, besides it will raise a warning
O.run(10000) #run 10000 iterations
O.wait()
plot.saveGnuplot(baseName='savedPlot')

def myAddPlotData():
   force=plot.addData(t=O.time, t_xyz=O.time,Fn=normalforce, Fmess=Fm, Fx=Fx,Fy=Fy,Fz=Fz)

def updatePerformancePlot():
   plot.addData(t_perf=O.time, speed=speeddata)

>what have you done to fix stability issues?

Remi Cailletaud upgraded the host system, and for me at least it doesn't crash. Do you still have problems?

>calling plot.addData() will take care of it by inserting 'nan'

Well, this is precisely why I thought it didn't work. Plotting functions don't really like nan's usually. Does it display correctly for you?

>Remi Cailletaud upgraded the host system, and for me at least it doesn't crash. Do you still have problems?
in fact I did not try wiki again.

>Well, this is precisely why I thought it didn't work. Plotting functions don't really like nan's usually. Does it display correctly for you?
well it worked in normal mode. i'm trying it in batch now - we'll see if it works.
nans are no problem if you use gnuplots, i think. (like written in the yade plot documentation)

Jan Stránský (honzik) said : #9

> nans are no problem if you use gnuplots, i think. (like written in the
> yade plot documentation)
>

exactly, see [1,2]
Jan

[1] https://github.com/yade/trunk/blob/master/py/plot.py#L712
[2] http://gnuplot.sourceforge.net/docs_4.2/node172.html

I tried wiki and it works great! Thank you Remi Cailletaud!