I have been working through the book "A student's guide to Python for Physical Modeling" by Jesse M. Kinder & Philip Nelson and there is an exercise where I'm instructed to build a Brownian motion simulator/ random walk simulator and plot it. I don't know why my code is not working and I was hoping I could get some help from you:
import numpy as np
import matplotlib.pyplot as plt
from numpy.random import random as rng
def Brownian_motion(steps):
"""
this is a random walk function
define the number of steps to be taken as a integer value
"""
#these are the random numbers
steps_x = rng(steps)
steps_y = rng(steps)
#Here I change the random numbers to 1 or -1
pace_x = (steps_x < 0.5)
for i in pace_x:
if i == False:
pace_x[i] = -1
else:
pace_x[i] = 1
return pace_x
pace_y = (steps_y < 0.5)
for i in pace_y:
if i == False:
pace_y[i] = -1
else:
pace_x[i] = 1
return pace_y
plt.plot(np.cumsum(pace_x), np.cumsum(pace_y))
plt.show()
Brownian_motion(500)
It does not throw and error but I can't get it to plot
EDIT:
This is similar to what I'm expecting to see:
http://people.sc.fsu.edu/~jburkardt/m_src/random_walk_2d_simulation/walks_1_steps_1000_plot.png
With numpy you can create boolean slices which are more efficient. Note that this does not work with Python Lists/Tuples.
import numpy as np
import matplotlib.pyplot as plt
from numpy.random import random as rng
def Brownian_motion(steps):
"""
this is a random walk function
define the number of steps to be taken as a integer value
"""
#these are the random numbers
steps_x = rng(steps)
steps_y = rng(steps)
pace_x = np.ones_like(steps_x)
idx = steps_x < 0.5
pace_x[idx] = -1
idy = steps_y < 0.5
pace_y = np.ones_like(steps_y)
pace_y[idy] = -1
plt.plot(np.cumsum(pace_x), np.cumsum(pace_y))
# plt.axis("equal")
# I would also add this. This way your plot won't be
# distorted.
plt.show()
a = Brownian_motion(500)
You have unnecessary return statements at the end of your loops, so your code never gets to the plot. Remove those and the Brownian_motion function should have a chance to complete execution.
Try to remove the return from your function, and cast your booleans to integers
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
from numpy.random import random as rng
def Brownian_motion(steps):
"""
this is a random walk function
define the number of steps to be taken as a integer value
"""
#these are the random numbers
steps_x = rng(steps)
steps_y = rng(steps)
#Here I change the random numbers to 1 or -1
pace_x = (steps_x < 0.5)*1
for i in pace_x:
if i == False:
pace_x[i] = -1
else:
pace_x[i] = 1
#return pace_x
pace_y = (steps_y < 0.5)*1
for i in pace_y:
if i == False:
pace_y[i] = -1
else:
pace_x[i] = 1
#return pace_y
plt.plot(np.cumsum(pace_x), np.cumsum(pace_y))
plt.show()
Brownian_motion(500)
I do not know what a Brownian motion simulator/ random walk simulator is but the problem in your code is that in your function you have a return statement (actually 2) that makes your function stop without executing the the plot.
Commenting it seems to work and it plots something (I do not know it it is what you are expecting).
The code:
import numpy as np
import matplotlib.pyplot as plt
from numpy.random import random as rng
def Brownian_motion(steps):
"""
this is a random walk function
define the number of steps to be taken as a integer value
"""
#these are the random numbers
steps_x = rng(steps)
steps_y = rng(steps)
#Here I change the random numbers to 1 or -1
pace_x = (steps_x < 0.5)
#print(pace_x)
x_list = list()
y_list = list()
for i in pace_x:
if i == False:
#pace_x[i] = -1
x_list.append(-1)
else:
#pace_x[i] = 1
x_list.append(1)
#return pace_x
print("Hello there")
pace_y = (steps_y < 0.5)
for i in pace_y:
if i == False:
#pace_y[i] = -1
y_list.append(-1)
else:
#pace_x[i] = 1
y_list.append(1)
#return pace_y
plt.plot(x_list, y_list)
plt.show()
Brownian_motion(500)
Piece of advice: when something is wrong in Python try to put print function calls in your code to check what you are expecting is correct. For example I put the line print("Hello there") after the return and have seen that it was never executed (now it's commented).
Related
Basically I'd like to implement BSC. A photo is changed into bits, some of them are changed and a new image is created. The issue I encountered is that I get the same image back. I've put some print() statements to see if the error() works and it looks like it does. Here's my code:
import numpy as np
import random as rand
# Seed
rand.seed(4)
# Filenames
in_name = 'in_img.png'
out_name = 'out_img.png'
# Into bits
in_bytes = np.fromfile(in_name, dtype="uint8")
in_bits = np.unpackbits(in_bytes)
data = list(in_bits)
# BSC
def error(x):
p = 0.1
is_wrong = rand.random() < p
if is_wrong:
if x == 1:
return 0
else:
return 1
else:
return x
for i in data:
i = error(i)
# To PNG
out_bits = np.array(data)
out_bytes = np.packbits(out_bits)
out_bytes.tofile(out_name)
While the problem in your code seems to be a duplicate as kazemakase points out in a comment, your code should not use such a loop and a Python list in the first place. With numpy one usually tries to push as many loops as possible into the numpy data types.
import numpy as np
def main():
np.random.seed(4)
in_name = 'in_img.png'
out_name = 'out_img.png'
bits = np.unpackbits(np.fromfile(in_name, np.uint8))
bits ^= np.random.random(bits.shape) < 0.1
np.packbits(bits).tofile(out_name)
if __name__ == '__main__':
main()
So I have the following MCMC sampler -
import numba
import numpy as np
import scipy.stats as stats
from scipy.stats import multivariate_normal
import seaborn as sns
import pandas as pd
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
import random
import math
def targ_dist2(x1,x2):
target2 = (mlab.bivariate_normal(x1, x2, 1.0, 1.0, -6, -6, 0.9) +
mlab.bivariate_normal(x1, x2, 1.0, 1.0, 4, 4, -0.9) +
mlab.bivariate_normal(x1, x2, 1.0, 1.0, 0.0, 0.0))/3
return target2
nSamples = 5000
propSigma = 2
x = np.zeros((nSamples+1,2))
xCurrent = stats.uniform.rvs(loc=-5, scale=10, size=2, random_state=None)
dims = range(2)
#INITIAL VALUES
t = 0
x[t,0] = xCurrent[0]
x[t,1] = xCurrent[1]
while t < nSamples:
t = t + 1
for iD in range(2):
xStar = np.random.normal(x[t-1,iD], propSigma)
alpha = min(1, (targ_dist2(xStar, x[t-1,iD!=dims]) / targ_dist2(x[t-
1,iD], x[t-1,iD!=dims])))
#ACCEPT OR REJECT
u = random.uniform(0, 1)
if u < alpha:
x[t,iD] = xStar
else:
x[t,iD] = x[t-1,iD]
My error is where I have the != in the alpha equation. Basically here I would like to choose the value in "dims" that is not equal to the value "iD" in the loop. So, for example, if the loop is working through the value iD=0, I would like to have the value 1 in place of iD!=dims in the alpha equation above (if that makes sense). Is there a general way of doing this? I hope to extend this algorithm to multiple dimensions...
what you have doesn't really make sense because you are comparing a range with a value. iD is an int but dims is a range so comparing them doesn't really make sense.
maybe something like this would be better
def get_opposite(iD, dims):
for x in dims:
if x != iD: #Beware here for multi dimentional extension
return x
Then change your offending line to:
... x[t-1,get_opposite(iD,dims)]...
Not sure I get what you want, but if it's to just print the opposite value of iD, if it is a range(2), thus 1 and 0:
for i in range(2):
print("i value: ", i)
print("opposite:" ,1- i)
I am trying to plot with dots hoping in the end i can get a probability density function simulation. My code is:
import random
import math
from numpy import *
from matplotlib.pyplot import *
import matplotlib.pyplot as pl
clock_offset=3000
y=0
p=0.50
for i in range (40):
x = random.random()
if x < p:
clock_offset+=1
for 'bo' in (clock_offset,y):
y+=1
pl.plot(clock_offset,y,'bo')
pl.axis([2980, 3040, 0, 40])
y=0
else:
clock_offset-=1
for 'bo' in (clock_offset,y):
y+=1
pl.plot(clock_offset,y,'bo')
pl.axis([2980, 3040, 0, 40])
y=0
The problem is i can't write a for loop that makes y+=1, when that place (clock_offset,y) has already been occupied with a dot. Any solutions?
I'm not sure what this code of yours is supposed to do. But take a look at this answer of mine that explains how to get a random number on a distribution. Bellow I gave you a rewrite of that C++ code into python.
import random
import math
import numpy as np
import matplotlib.pyplot as plt
def GausPDF(x, a=1., b=2., c=3.):
return a*math.exp( -((x-b)*(x-b)/(2*c*c) ))
def random_on_PDF(PDF, top, bottom, maxPDF):
x = (top-bottom)*np.random.random()+bottom
y = maxPDF*random.random()
while(y>PDF(x)):
x = (top-bottom)*np.random.random()+bottom
y = maxPDF*random.random()
return x,y
x, y, = list(), list()
for i in range(0, 1000):
a,b = random_on_PDF(GausPDF, 10., -5., 1.)
x.append(a)
y.append(b)
plt.scatter(x,y)
plt.show()
Using this code and THIS matplotlib example directly, you can simulate how random voting affects/builds a PDF.
Is that what you're after?
I have a function f(x,t) = cos(t)*t + x and i want to display the change of the result over the width x and time t at discretised time steps t_i and discretised width steps x_j.
Now I am a while here on SX and feel really embarrassed to only can post such little code or in other words nothing (since nothing worked I have done...):
Nevertheless if someone has the time to help, I`d appreciate it.
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as pyplot
from astropy.io.ascii.latex import AASTex
def func(xi, ti):
res = np.cos(ti)*ti + xi
return res
timeSpacing = 100
timeStart = 0
timeEnd = 1
time = np.linspace(timeStart, timeEnd, timeSpacing)
widthSpacing = 300
widthStart = 0
widthEnd = 3
width = np.linspace(widthStart, widthEnd, widthSpacing)
resultList = [None]*timeSpacing
resultListInner = [None]*widthSpacing
for i, ithTime in enumerate(time):
for j, jthWidth in enumerate(width):
aas = np.zeros_like(width)
aas.fill(ithTime)
resultListInner[j] = ithTime, jthWidth, func(jthWidth, aas)
resultList[i] = resultListInner
So how do I correctly index the list and array and plot my data using matplotlib?
My plot should look like this:
where in my case the aperature should be the width x, the sky annulus is my time t and the RMS is my func(x,t).
A couple of points:
Numpy provides a very nice function for doing differences of array elements: diff
Matplotlib uses plot_wireframe for creating a plot that you would want (also using Numpy's meshgrid)
Now, combining these into what you may want would look something like this.
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
def func(xi, ti):
res = np.cos(ti)*np.sin(xi)
return res
timeSpacing = 20
timeStart = 0
timeEnd = 1
time = np.linspace(timeStart, timeEnd, timeSpacing)
widthSpacing = 50
widthStart = 0
widthEnd = 3
width = np.linspace(widthStart, widthEnd, widthSpacing)
X,T = np.meshgrid(width,time)
F = func(X,T)
DF = np.diff(np.diff(F,axis=0),axis=1)
fig = plt.figure()
ax = fig.add_subplot(111,projection='3d')
ax.plot_wireframe(X[:-1,:-1],T[:-1,:-1],DF)
plt.show()
Note that diff is applied twice: once in each dimension axis= . I have also changed the toy function you provided to something that actually looks decent in this case.
For your more general use, it seems that you would want to just collect all of your F data into a 2D array, then proceed from the DF = line.
my issues is with trying to work with arrays that for each elements is a tuple of 2 values.
specifically the problem is to generate a random 2-dimensional walk of 200 (but for testing say 2) steps with a max distance, then 100 (try just 2) of those walks per stage, and commencing each stage at the largest distance from the origin of the previous stage.
I can successfully generate the array of random steps and get them to return the final position (x,y) value and as well calculate the distance of them from the origin of each walk:
That's defined in these functions:
#............................................................getPositionInteger
def getPosInt(description) :
"""Asks the user to enter a positive integer"""
askAgain = False
while askAgain == False:
try:
posInt = eval(raw_input("\n %s : " %description))
assert 0 < posInt , "Not a positive integer"
assert type(posInt) == int , "Not a positive integer"
askAgain = True
except :
print "Input failed, not a positive integer"
return posInt
#...............................................................initialPosition
def initialPosition() :
"""Initial position of walker at the start of a random walk"""
return (0.0, 0.0)
#......................................................................distance
def distance(posA, posB) :
"""Distance between two positions"""
xi = posA[0] ; yi = posA[1]
xf = posB[0] ; yf = posB[1]
return np.sqrt((xf-xi)**2+(yf-yi)**2)
#..................................................................getPositions
def getPositions(start, nSteps, maxStep):
xArray = maxStep * np.random.random(nSteps+1)* np.cos(2.0 * np.pi * random.random())
yArray = maxStep * np.random.random(nSteps+1)* np.sin(2.0 * np.pi * random.random())
xArray[0] = start[0]
yArray[0] = start[-1]
xArray = np.cumsum(xArray)
yArray = np.cumsum(yArray)
return (xArray[-1], yArray[-1])
But I can't get the array of the final position of each walk per stage in (x,y) form per stage
Here's the main script and where I'm having trouble:
import numpy as np
import matplotlib.pylab as plt
import random
import time
MAX_STEP_SIZE = 0.90 # maximum size of a single step [m]
random.seed(12345)
#..........................................................................main
def main ():
''''''
print "RANDOM WALK IN STAGES IN TWO DIMENSIONS"
userdata = getDetails()
print "\nPlease wait while random walks are generated and analyzed..."
NUM_STAGES = userdata[0]
NUM_WALKS = userdata[1]
NUM_STEPS = userdata[2]
stageStart = initialPosition()
for stage in np.arange(NUM_STAGES):
walks = np.zeros((NUM_WALKS, NUM_WALKS), dtype=np.ndarray)
for walk in walks:
walk = getPositions(stageStart, NUM_STEPS, MAX_STEP_SIZE)
print walk
print walks
You will see I'm having trouble making a an (x,y) style array, where the [0 0] should be [0.0 , 0.0] and its printed twice and additionally, its not changing to the final position.
I really appreciate and help, advice or references you can provide.
Thanks
-Sid