How to share variable between multiple functions in Python, i.e., globally? - python

In the code below, I have two functions: func1 and gillespie. I have defined p_tot_stoch as a global variable, within func1. (The reason for placing it inside a function is to allow Numba's #jit wrapper to work properly... Numba is used for code optimization.)
But when I try to print p_tot_stoch at the very end of the code, I get the following error message:
Traceback (most recent call last):
File "C:/Users/dis_YO_boi/Documents/Programming/Python/CodeReview.py", line 85, in <module>
p_tot_stoch = gillespie()
NameError: global name 'p_tot_stoch' is not defined
I declared it as global, but it looks like the main function gillespie cannot access it. How can I fix this?
My code is below, thanks for any help.
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
from numba import jit
import math
random = np.random
DELTA = 1e-3
SIM_NUM = 100
K_MINUS = 1e-3
K_CAT = 1 - 1e-3
ZETA = 1e-4
D = 10000
QP_VEC = np.logspace(-2, 1, 101, 10)
KAPPA_M = (K_CAT + K_MINUS) / ZETA
P0_VEC = QP_VEC / DELTA
QP_DEG = np.true_divide(1000*D*QP_VEC*K_CAT,1000*QP_VEC+KAPPA_M)
#jit
def func1():
global p_tot_stoch
p_tot_stoch = np.empty((SIM_NUM, len(QP_VEC)))
#jit
def gillespie(max_time=1000):
for len_qp_ind in range(len(QP_VEC)):
qp = QP_VEC[len_qp_ind]
p0 = math.ceil(P0_VEC[len_qp_ind])
for sim_num_ind in range(SIM_NUM):
p = p0
d = D
dp = time = 0
while True:
tot = [qp, ZETA * p * d, K_MINUS * dp, K_CAT * dp]
for i in range(3):
tot[i + 1] += tot[i]
p_tot = p + dp
kt = tot[-1]
time += -np.log(1 - random.random()) / kt
if time > max_time:
p_tot_stoch[sim_num_ind, len_qp_ind] = p_tot
break
event_kt = random.random() * kt
if event_kt < tot[0]:
p += 1
elif event_kt < tot[1]:
p -= 1
dp += 1
d -= 1
elif event_kt < tot[2]:
p += 1
dp -= 1
d += 1
elif event_kt < tot[3]:
dp -= 1
d += 1
return p_tot_stoch
if __name__ == '__main__':
p_tot_stoch = gillespie()
p_mean = p_tot_stoch.mean(axis=0)
p_std = p_tot_stoch.std(axis=0)
print(p_tot_stoch)

cat test.py
my_variable = 0
def func1():
global my_variable
my_variable = -1
print "func1:{0}".format(my_variable)
def gillespie():
global my_variable
my_variable = 4
print "gillespie:{0}".format(my_variable)
# Starts testing...
print "before:{0}".format(my_variable)
func1()
gillespie()
print "after:{0}".format(my_variable)
python test.py
before:0
func1:-1
gillespie:4
after:4
You can declare your variable p_tot_stoch(in my test.py I declared a variable named my_varialble it is used in func1() and gillespie()) on the top of your script and outside of your functions. Each time you want to modify it you have to declare it is a global variable and then assign a new value to it.
Im using python2.7

I modified #haifzhan's example because it is simple. Python benefits from OOP tremendously and it is a sin not to use it:
#!/usr/bin/env python3
class Stoch:
def __init__(self):
self.my_variable = 0
def __str__(self):
return str(self.my_variable)
def func1(self):
self.my_variable = -1
print ("func1:", self)
def gillespie(self):
self.my_variable = 4
print ("gillespie:", self)
#classmethod
def main(cls):
stoch = Stoch()
print ("before:", stoch)
stoch.func1()
stoch.gillespie()
print ("after:", stoch)
if __name__ == '__main__':
Stoch.main()

Related

Returning None after conditional

Trying to return the math.floor of k, which is 2
import numpy as np
import math
j = 1
def k(j):
k = j + 1.2
return k # 2.2
def foo2():
num = k(j)
floor = math.floor(num)
threshold = 5.1
a = 22.5094
i = np.arange(threshold, 50)
if a in i:
return floor
print(foo2())
It worked without conditional
import math
j = 1
def k(j):
k = j + 1.2
return k #2.2
def foo2():
num = k(j)
b = math.floor(num)
return b
print(foo2())
If you spot where I made a wrong assumption, do share please.
Try add line: print(a, i)
after: i = np.arange(threshold, 50)
You will see that a doesn't belong to i, and becouse of this if that is in the next line will not execute return function, becouse as we saw earlier there is no any value in list i that is equal to value of a.
And if return in function isn't executed then function will return None.

Why is ROS Publisher not publishing values?

I am currently trying to write a Python ROS program which can be executed as a ROS node (using rosrun) that implements the defs declared in a separate Python file arm.py (available at: https://github.com/nortega1/dvrk-ros/...). The program initially examines the current cartesian position of the arm. Subsequently, when provided with a series of points that the arm must pass through, the program calculates a polynomial equation and given a range of x values the program evaluates the equation to find the corresponding y values.
Within the arm.py file there is a publisher set_position_cartesian_pub that sets the Cartesian position of the arm as follows:
self.__set_position_cartesian_pub = rospy.Publisher(self.__full_ros_namespace + '/set_position_cartesian', Pose, latch = True, queue_size = 1)
The issue is that the publisher set_position_cartesian is not publishing the values of the newPose to the robot - can anyone figure out what the issue might be? I can confirm that the def lagrange correctly calculates the values of the x and y coordinates, which are printed out to the terminal via the command rospy.loginfo(newPose). Any help would be greatly appreciated as I've been trying to solve this issue for the last 2 days!
#! /usr/bin/python
import rospy
import sys
from std_msgs.msg import String, Bool, Float32
from geometry_msgs.msg import Pose
from geometry_msgs.msg import PoseStamped
from geometry_msgs.msg import Vector3
from geometry_msgs.msg import Quaternion
from geometry_msgs.msg import Wrench
class example_application:
def callback(self, data):
self.position_cartesian_current = data.pose
rospy.loginfo(data.pose)
def configure(self,robot_name):
self._robot_name = 'PSM1'
ros_namespace = '/dvrk/PSM1'
rospy.Subscriber('/dvrk/PSM1/position_cartesian_current', PoseStamped, self.callback)
self.set_position_cartesian = rospy.Publisher('/dvrk/PSM1/set_position_cartesian', Pose, latch=True, queue_size = 10)
rospy.sleep(3)
rospy.init_node('listener', anonymous=True)
rospy.spin()
def lagrange(self, f, x):
total = 0
n = len(f)
for i in range(n):
xi, yi = f[i]
def g(i, n):
g_tot = 1
for j in range(n):
if i == j:
continue
xj, yj = f[j]
g_tot *= (x - xj) / float(xi - xj)
return g_tot
total += yi * g(i, n)
return total
def trajectoryMover(self):
newPose = Pose()
points =[(0.0156561,0.123151),(0.00715134,0.0035123151),(0.001515177,0.002123151),(0.0071239751,0.09123150)]
xlist = [i*0.001 for i in range(10)]
ylist = [self.lagrange(points, xlist[i])*0.001 for i in range(10)]
for x, y in zip(xlist, ylist):
newPose.position.x = x
newPose.position.y = y
newPose.position.z = 0.001
newPose.orientation.x = 0.001
newPose.orientation.y = 0.001
newPose.orientation.z = 0.005
newPose.orientation.w = 0.002
rospy.sleep(1)
self.set_position_cartesian.publish(newPose)
rospy.loginfo(newPose)
rospy.spin()
def run(self):
# self.home()
self.trajectoryMover()
if __name__ == '__main__':
try:
if (len(sys.argv) != 2):
print(sys.argv[0] + ' requires one argument, i.e. name of dVRK arm')
else:
application = example_application()
application.configure(sys.argv[1])
application.run()
except rospy.ROSInterruptException:
pass
You are not publishing because the code stops at rospy.spin() when you call application.configure(). For what I understand of what you are trying to do, the code will publish 10 poses to a topic, then you don't need it anymore.
I've moved the location of rospy.spin(), but the code needs more revision than that.
#! /usr/bin/python
import rospy
import sys
from std_msgs.msg import String, Bool, Float32
from geometry_msgs.msg import Pose
from geometry_msgs.msg import PoseStamped
from geometry_msgs.msg import Vector3
from geometry_msgs.msg import Quaternion
from geometry_msgs.msg import Wrench
class example_application(object):
def callback(self, data):
self.position_cartesian_current = data.pose
rospy.loginfo(data.pose)
def configure(self,robot_name):
self._robot_name = 'PSM1'
ros_namespace = '/dvrk/PSM1'
rospy.Subscriber('/dvrk/PSM1/position_cartesian_current', PoseStamped, self.callback)
self.set_position_cartesian = rospy.Publisher('/dvrk/PSM1/set_position_cartesian', Pose, latch=True, queue_size = 10)
def lagrange(self, f, x):
total = 0
n = len(f)
for i in range(n):
xi, yi = f[i]
def g(i, n):
g_tot = 1
for j in range(n):
if i == j:
continue
xj, yj = f[j]
g_tot *= (x - xj) / float(xi - xj)
return g_tot
total += yi * g(i, n)
return total
def trajectoryMover(self):
newPose = Pose()
points =[(0.0156561,0.123151),(0.00715134,0.0035123151),(0.001515177,0.002123151),(0.0071239751,0.09123150)]
xlist = [i*0.001 for i in range(10)]
ylist = [self.lagrange(points, xlist[i])*0.001 for i in range(10)]
for x, y in zip(xlist, ylist):
newPose.position.x = x
newPose.position.y = y
newPose.position.z = 0.001
newPose.orientation.x = 0.001
newPose.orientation.y = 0.001
newPose.orientation.z = 0.005
newPose.orientation.w = 0.002
self.set_position_cartesian.publish(newPose)
rospy.loginfo(newPose)
def run(self):
# self.home()
self.trajectoryMover()
if __name__ == '__main__':
if (len(sys.argv) != 2):
print(sys.argv[0] + ' requires one argument, i.e. name of dVRK arm')
else:
application = example_application()
application.configure(sys.argv[1])
application.run()
try:
rospy.spin()
except KeyboardInterrupt:
rospy.loginfo("Keyboard Interrupt")
Think of:
making the script argument a parameter of the node.
moving the configure method to the __init__ method.
taking the g() function outside lagrange().
It's a good practice to use relative topic names, instead of absolute ones (absolute: topic name start with /, e.g.: '/dvrk/PSM1').

How do I plot the integral of e^(-t^2) from x=0 to x=3 in Python?

I need to both calculate and plot the integral below in Python:
integral of the function e^(-t^2) from x=0 to x=3
So far I've managed to calculate the integral using Simpson's rule. The next bit which I'm struggling with is plotting the integral of e^(-t^2) vs x from x=0 to x=3 (see the image above).
Here's the code I've written to calculate the integral -
from math import exp
def f(t):
return exp(-(t**2))
a = 0
b = 3
h = 0.1
N = int((b-a)/h)
s_even = 0
s_odd = 0
for k in range(1,N,2):
s_odd += f(a+k*h)
for k in range(2,N,2):
s_even += f(a+k*h)
s = f(a) + f(b) + 4*s_odd + 2*s_even
Integral = h*s/3
print(Integral)
How do I then create a graph of this integral?
Here's a script I wrote that performs your calculation and plots it using PyQtGraph:
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
from math import exp
class I:
def f(self,t):
return exp(-(t**2))
def __init__(self, a = 0, b = 3, h = 0.1):
N = int((b-a)/h)
s_even = s_odd = 0
for k in range(1,N,2):
s_odd += self.f(a+k*h)
for k in range(2,N,2):
s_even += self.f(a+k*h)
s = self.f(a) + self.f(b) + 4*s_odd + 2*s_even
self.I = h*s/3
def __str__(self):
return "I: %s" % self.I
def plot(array):
app = QtGui.QApplication([])
win = pg.GraphicsWindow(title="Basic plotting examples")
win.resize(1000,600)
win.setWindowTitle('pyqtgraph example: Plotting')
# Enable antialiasing for prettier plots
pg.setConfigOptions(antialias=True)
p1 = win.addPlot(title="Basic array plotting", y=array)
QtGui.QApplication.instance().exec_()
def main():
a=0
b=a+0.001
points=[]
while(a<3):
points.append(I(a,b).I)
a=b
b=a+0.001
plot(points)
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
main()
Here is the graph it draws:
Thanks for your help Red Cricket. It looks like you may have graphed the function e^(-t^2) rather than the integral of that function. Nonetheless, I think I've worked it out; I've discovered scipy has an integrate function:
from math import exp
from numpy import arange
from scipy import integrate
def f(t):
return exp(-(t**2))
a = 0
b = 3
h = 0.1
N = int((b-a)/h)
s_even = 0
s_odd = 0
for k in range(1,N,2):
s_odd += f(a+k*h)
for k in range(2,N,2):
s_even += f(a+k*h)
s = f(a) + f(b) + 4*s_odd + 2*s_even
I = h*s/3
function = []
x = []
for t in arange(0,4,h):
function.append(f(t))
for i in arange(0,4,h):
x.append(i)
function_int = integrate.cumtrapz(function,x,initial=0)
plot(x,function_int)
show()
print(I)
This produces a graph of the integral and prints the final value of the integral itself. Hooray!

Python - high disk usage in SumTree

I've encountered some weird behaviour of my python program. Basically when I tried to create adn fill a SumTree of length larger than 1000, my disk usage increases a lot to ~300MB/s then the programme died.
I'm pretty sure there's no file r/w involved in this process, and the problem is with the add function. The code is shown below.
import numpy as np
class SumTree():
trans_idx = 0
def __init__(self, capacity):
self.num_samples = 0
self.capacity = capacity
self.tree = np.zeros(2 * capacity - 1)
self.transitions = np.empty(self.capacity, dtype=object)
def add(self, p, experience):
tree_idx = self.trans_idx + self.capacity - 1
self.transitions[self.trans_idx] = experience
self.transitions.append(experience)
self.update(tree_idx, p)
self.trans_idx += 1
if self.trans_idx >= self.capacity:
self.trans_idx = 0
self.num_samples = min(self.num_samples + 1, self.capacity)
def update(self, tree_idx, p):
diff = p - self.tree[tree_idx]
self.tree[tree_idx] = p
while tree_idx != 0:
tree_idx = (tree_idx - 1) // 2
self.tree[tree_idx] += diff
def get_leaf(self, value):
parent_idx = 0
while True:
childleft_idx = 2 * parent_idx + 1
childright_idx = childleft_idx + 1
if childleft_idx >= len(self.tree):
leaf_idx = parent_idx
break
else:
if value <= self.tree[childleft_idx]:
parent_idx = childleft_idx
else:
value -= self.tree[childleft_idx]
parent_idx = childright_idx
data_idx = leaf_idx - self.capacity + 1
return leaf_idx, self.tree[leaf_idx], self.transitions[data_idx]
#property
def total_p(self):
return self.tree[0] # the root
#property
def volume(self):
return self.num_samples # number of transistions stored
Here's an example where this SumTree object will be used:
def add(self, experience)
max_p = np.max(self.tree.tree[-self.tree.capacity:])
if max_p == 0:
max_p = 1.0
exp = self.Experience(*experience)
self.tree.add(max_p, exp)
where Experience is a named tuple and self.tree is a Sumtree instance, when I removed the last line the high disk usage disappears.
Can anyone help me with this?
I finally sort this out because each experience is a tuple of namedtuple and I'm creating another namedtuple Experience from it. Fixed by changing experience to a tuple of numpy arrays.

Function not defined after declaration in python3

Using python 3: I have three functions: montePi, isInCircle and main.
I need to have the isInCircle called by montePi. The function will work, it just says that isInCircle is not defined. How can I define it?
import random
import math
def montePi(numDarts):
inCircle = 0
def isInCircle(x, y, r):
r = 1
d = math.sqrt(x**2 + y**2)
if d <= r:
return True
else:
return False
for i in range(numDarts):
x = random.random()
y = random.random()
d = math.sqrt(x**2 + y**2)
if d <= 1:
inCircle = inCircle +1
pi = inCircle / numDarts * 4
return pi
def main():
print(montePi(100))
print(montePi(1000))
print(montePi(10000))
print(montePi(100000))
main()
Because function isInCircle is defined in montePi, it can be called within montePi but not other functions as it is local. If you define isInCircle outside of montePi then you'll be able to call it from main.
Not sure what you're trying to program here, but there seems to be a chance that this question, regarding functions within functions can help you decide what you want here. Here is a question that covers how scopes work.
Should you need to call isInCircle from main or outside main, then this is how it should be formatted;
import random
import math
def isInCircle(x, y, r):
r = 1
d = math.sqrt(x**2 + y**2)
if d <= r:
return True
else:
return False
def montePi(numDarts):
inCircle = 0
for i in range(numDarts):
x = random.random()
y = random.random()
d = math.sqrt(x**2 + y**2)
if d <= 1:
inCircle = inCircle +1
pi = inCircle / numDarts * 4
return pi
def main():
print(montePi(100))
print(montePi(1000))
print(montePi(10000))
print(montePi(100000))
main()

Categories

Resources