global name is not defined

Asked by nobody on 2019-10-13

Hi all,

I'm trying to use plot.savadatatxt to save some data.

here is the MWE:
###################################################
from yade import pack, plot, export
import math
O.bodies.append(geom.facetBox((.5,.5,.5),(.5,.5,.5),wallMask=31))
sp=pack.SpherePack()
sp.makeCloud((0,0,0),(1,1,1),rMean=.04,rRelFuzz=.2, seed =1)
sp.toSimulation()
O.engines=[
 ForceResetter(),
 InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb()]),
 InteractionLoop(
  [Ig2_Sphere_Sphere_ScGeom(),Ig2_Facet_Sphere_ScGeom()],
  [Ip2_FrictMat_FrictMat_FrictPhys()],
  [Law2_ScGeom_FrictPhys_CundallStrack()]
 ),
 PyRunner(command='checkUnbalanced()',realPeriod=2),
 PyRunner(command='subbox()',iterPeriod=1000),
 NewtonIntegrator(gravity=(0,0,-9.81),damping=0.4),
]
O.dt=.5*PWaveTimeStep()
print(len(O.bodies))
def checkUnbalanced():
 if unbalancedForce()<.0001:
  O.pause()
x0 = 0.5
y0 = 0.5
z0 = 0.5
######################## sub-region and coloring#########################################
def subbox():
 global ball_list1
 ball_list1 =[]
 global b_radius
 b_radius = []
 for b in O.bodies:
  brp = math.sqrt((b.state.pos[0]-x0)**2 + (b.state.pos[1]-y0)**2)
  if brp >= 0.2:
   if brp <= 0.4:
    if (b.state.pos[2]-z0 >= -0.5) and (b.state.pos[2]-z0 <= 0.0):
     if isinstance(b.shape,Sphere):
      b.shape.color =Vector3(255,255,255) # white
      m = b.id
      r = b.state.pos[0]
      ball_list1.append(m)
      b_radius.append(r)
      ccc = sum(b_radius)
      aaa= len(ball_list1)
 plot.addData(bbb=aaa,ddd = ccc )
 plot.saveDataTxt('ball-number.txt')
O.run(1000000,True)
###############################################

If I just use this command :plot.saveDataTxt('ball-number.txt') it works fine.
but if I just want to save the bbb data, I change the command plot.saveDataTxt('ball-number.txt') to plot.saveDataTxt('ball-number.txt',vars = bbb)

the error will be: NameError: global name 'bbb' is not defined

To my knowledge, I put the plot.savedatatxt command inside the function, why do we still need the global name?

Besides, I want to use the plot.savedatatxt to save some other information. so I made another MWE:

from yade import pack, plot, export
import math
O.bodies.append(geom.facetBox((.5,.5,.5),(.5,.5,.5),wallMask=31))
sp=pack.SpherePack()
sp.makeCloud((0,0,0),(1,1,1),rMean=.04,rRelFuzz=.2, seed =1)
sp.toSimulation()
O.engines=[
 ForceResetter(),
 InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb()]),
 InteractionLoop(
  [Ig2_Sphere_Sphere_ScGeom(),Ig2_Facet_Sphere_ScGeom()],
  [Ip2_FrictMat_FrictMat_FrictPhys()],
  [Law2_ScGeom_FrictPhys_CundallStrack()]
 ),
 PyRunner(command='checkUnbalanced()',realPeriod=2),
 PyRunner(command='subbox()',iterPeriod=1000),
 PyRunner(command='getdata()',iterPeriod=100),
 NewtonIntegrator(gravity=(0,0,-9.81),damping=0.4),

]
O.dt=.5*PWaveTimeStep()
print(len(O.bodies))
def checkUnbalanced():
 if unbalancedForce()<.0001:
  O.pause()
x0 = 0.5
y0 = 0.5
z0 = 0.5
######################## sub-region and coloring#########################################

def subbox():
 global ball_list1
 ball_list1 =[]
 global aaa
 global bbb
 aaa = 0.0
 bbb = 0.0
 for b in O.bodies:
  brp = math.sqrt((b.state.pos[0]-x0)**2 + (b.state.pos[1]-y0)**2)
  if brp >= 0.2:
   if brp <= 0.4:
    if (b.state.pos[2]-z0 >= -0.5) and (b.state.pos[2]-z0 <= 0.0):
     if isinstance(b.shape,Sphere):
      b.shape.color =Vector3(255,255,255) # white
      m = b.id
      ball_list1.append(m)
      aaa= len(ball_list1)

def getdata():
 plot.addData(bbb=aaa )
 plot.saveDataTxt('ball-number.txt',vars=(bbb))

O.run(1000000,True)

##############
for this code, even though, I set the global aaa, but i still got the error:

NameError: global name 'aaa' is not defined

##########
I don't know is this related to my misunderstanding of the global variable and local variable in python or something else?

thanks in advance.

best,
yong

Question information

Language:
English Edit question
Status:
Solved
For:
Yade Edit question
Assignee:
No assignee Edit question
Solved by:
Jan Stránský
Solved:
2019-10-14
Last query:
2019-10-14
Last reply:
2019-10-13
Best Jan Stránský (honzik) said : #1

Hello,

a quick solution:
Note that vars in plot.saveDataTxt is "Sequence (tuple/list/set) of variable names to be saved" [1], so use something like:
###
from yade import plot
plot.addData(bbb=1,aaa=2,ccc=3)
plot.addData(bbb=4,aaa=5,ccc=6)
plot.saveDataTxt("testAll.dat")
plot.saveDataTxt("testaaabbb.dat",vars=["aaa","bbb"])
plot.saveDataTxt("testaaa.dat",vars=["aaa"])
###

> I don't know is this related to my misunderstanding of the global variable and local variable in python

most likely.
a good solution is not to modify global variables :-)

For the first code:
> plot.addData(bbb=aaa )
bbb is just a parameter name of plot.addData function, not even a variable.
> plot.saveDataTxt('ball-number.txt',vars=(bbb))
here Python is lost, because it does not know anything about bbb..
A variable becomes variable after assignment "="

Second code:
First time you declare aaa in subbox (iterPeriod=1000), before Python knows nothing about aaa.
But you require it in getdata (iterPeriod=100), which is called prior to subbox and, as Python says, aaa is not defined.

also please try to make your MWE really MWE, where M stands for minimal [2].
As you add some toy data anyway, packing, checkUnbalanced, most engines, most of subbox function etc. are not related to the problem at all and could be excluded..

cheers
Jan

[1] https://yade-dem.org/doc/yade.plot.html#yade.plot.saveDataTxt
[2] https://www.yade-dem.org/wiki/Howtoask

nobody (nobody01) said : #2

Thanks Jan Stránský, that solved my question.