I would like to create an array with values that range from 0.0 to 1.0 as shown here:
weighting matrix
Basically, the left and top edges should remain close to 1.0 but slowly decay to 0.5 in the corners.
The bottom and right edges should remain close to 0.0
The middle region should be mostly 0.5, and the values should be decaying diagonally from 1.0 to 0.0.
This is what I've tried but it doesn't give me exactly what I would like.
import numpy as np
import matplotlib.pyplot as plt
def sigmoid(x):
y = np.zeros(len(x))
for i in range(len(x)):
y[i] = 1 / (1 + math.exp(-x[i]))
return y
sigmoid_ = sigmoid(np.linspace(20, 2.5, 30))
temp1 = np.repeat(sigmoid_.reshape((1,len(sigmoid_))), repeats=10, axis=0)
sigmoid_ = sigmoid(np.linspace(6, 3, 10))
temp2 = np.repeat(sigmoid_.reshape((len(sigmoid_),1)), repeats=30, axis=1)
alpha1 = temp1 + temp2
sigmoid_ = sigmoid(np.linspace(-2.5, -20, 30))
temp1 = np.repeat(sigmoid_.reshape((1,len(sigmoid_))), repeats=10, axis=0)
sigmoid_ = sigmoid(np.linspace(-3, -6, 10))
temp2 = np.repeat(sigmoid_.reshape((len(sigmoid_),1)), repeats=30, axis=1)
alpha2 = temp1 + temp2
alpha = alpha1 + alpha2
alpha = alpha - np.min(alpha)
alpha = alpha / np.max(alpha)
plt.matshow(alpha)
Which gives me this: results
Can someone help me?
This is the simplest function I can think of:
tune_me = 101
x = np.linspace(0, 1, tune_me)
y = np.linspace(0, 1, tune_me)
xv, yv = np.meshgrid(x, y)
sig = 1/(1 + np.exp(tune_me - xv - yv))
plt.matshow(sig)
But if you want something specific, you should probably figure out your math (maybe on the math stack exchange) before you try to implement it.
I'd use the same function for all parts of the weighting matrix area, if not otherwise required. A sigmoid function (which changes rapidly near the center and slowly away from it) is indeed suitable after appropriate translation and scaling. For the sigmoid function's argument I'd choose the taxicab distance from a corner of the area.
import math
import numpy as np
import matplotlib.pyplot as plt
alpha = np.ndarray((10, 30))
ymax, xmax = alpha.shape[0]-1, alpha.shape[1]-1
for y in range(alpha.shape[0]):
for x in range(alpha.shape[1]):
M = x/xmax+y/ymax # Manhattan distance, range [0;2]
M -= 1 # make range [-1;1], so that inflection point is in the middle
M *= 3.0 # the higher this factor, the steeper the sigmoid curve at the flex
s = 1 / (1 + math.exp(-M)) # sigmoid function, range ]0;1[
alpha[y, x] = 1-s # decay from 1 to 0
plt.matshow(alpha)
plt.show()
# show the values close to 0.5
h = [(y, x) for y in range(alpha.shape[0])
for x in range(alpha.shape[1]) if .4 < alpha[y, x] and alpha[y, x] < .6]
hy, hx = zip(*h)
plt.plot(hx, hy, 'o')
plt.gca().invert_yaxis()
plt.show()
Illustration of values in center region close to 0.5, e. g. in ]0.4;0.6[:
Related
I would like to make an image of a ring of inner radius r1 and outter radius r2 with values modulated by a cosinus.
I've already made this and tried several options (comments in the code) :
import numpy as np
import matplotlib.pyplot as plt
def circle(x_center,y_center,r):
# theta = np.linspace(0, 2*np.pi, 500)
# x = r*np.cos(theta) - x_center
# y = r*np.sin(theta) - y_center
xv = np.linspace(-r-1,r+1,500)
X,Y = np.meshgrid(xv, xv)
profilegrid = np.ones(X.shape, float)
for i, a in enumerate(X[0, :]):
for k, z in enumerate(Y[:, 0]):
theta = np.arctan(z/a)
current_radius = np.sqrt(a**2 + z**2)
cond1 = current_radius <= r
# cond2 = np.logical_and(np.abs(theta)>=0,np.abs(theta)<=pi)
cond2 = a==a
if np.logical_and(cond1,cond2)==False :
profilegrid[i, k] = 0
else :
profilegrid[i, k] = np.cos(theta)
return xv,profilegrid
xv1,circle_big = circle(0,0,1)
xv2,circle_small = circle(0,0,0.5)
new = circle_big - circle_small
plt.imshow(new, interpolation="bicubic",
origin="lower", extent=[min(xv1),max(xv1),min(xv1),max(xv1)])
plt.colorbar()
plt.show()
But the output image gives me :
I should have values between -1 and 1 and not between 0 and 1. Furthermore, as you can see I've asked a circle of radius r1=1 substracted to a circle of radius r2=0.5 in order to simulate the ring but the circle seems to be a little bit bigger.
Any idea about the origin of those issues?
EDIT :
Found the issue concerning the radius problem thanks to #tgrtim :
xv = np.linspace(-r-1,r+1,500) should be fixed and replaced by :
xv = np.linspace(-2,2,500)
Furthermore the problem of the values interval [0:1] instead of [-1:1] comes from the arctan boundaries. So do you have any idea how to change this in order to have only one maximum and no mirror pattern like this?
The problem for the mirror pattern can be resolved involving the function math.atan2(y,x) instead of np.arctan(y/x).
It is the first time I am trying to write a Poincare section code at Python.
I borrowed the piece of code from here:
https://github.com/williamgilpin/rk4/blob/master/rk4_demo.py
and I have tried to run it for my system of second order coupled odes. The problem is that I do not see what I was expecting to. Actually, I need the Poincare section when x=0 and px>0.
I believe that my implementation is not the best out there. I would like to:
Improve the way that the initial conditions are chosen.
Apply the correct conditions (x=0 and px>0) in order to acquire the correct Poincare section.
Create one plot with all the collected poincare section data, not four separate ones.
I would appreciate any help.
This is the code:
from matplotlib.pyplot import *
from scipy import *
from numpy import *
# a simple Runge-Kutta integrator for multiple dependent variables and one independent variable
def rungekutta4(yprime, time, y0):
# yprime is a list of functions, y0 is a list of initial values of y
# time is a list of t-values at which solutions are computed
#
# Dependency: numpy
N = len(time)
y = array([thing*ones(N) for thing in y0]).T
for ii in xrange(N-1):
dt = time[ii+1] - time[ii]
k1 = dt*yprime(y[ii], time[ii])
k2 = dt*yprime(y[ii] + 0.5*k1, time[ii] + 0.5*dt)
k3 = dt*yprime(y[ii] + 0.5*k2, time[ii] + 0.5*dt)
k4 = dt*yprime(y[ii] + k3, time[ii+1])
y[ii+1] = y[ii] + (k1 + 2.0*(k2 + k3) + k4)/6.0
return y
# Miscellaneous functions
n= 1.0/3.0
kappa1 = 0.1
kappa2 = 0.1
kappa3 = 0.1
def total_energy(valpair):
(x, y, px, py) = tuple(valpair)
return .5*(px**2 + py**2) + (1.0/(1.0*(n+1)))*(kappa1*np.absolute(x)**(n+1)+kappa2*np.absolute(y-x)**(n+1)+kappa3*np.absolute(y)**(n+1))
def pqdot(valpair, tval):
# input: [x, y, px, py], t
# takes a pair of x and y values and returns \dot{p} according to the Hamiltonian
(x, y, px, py) = tuple(valpair)
return np.array([px, py, -kappa1*np.sign(x)*np.absolute(x)**n+kappa2*np.sign(y-x)*np.absolute(y-x)**n, kappa2*np.sign(y-x)*np.absolute(y-x)**n-kappa3*np.sign(y)*np.absolute(y)**n]).T
def findcrossings(data, data1):
# returns indices in 1D data set where the data crossed zero. Useful for generating Poincare map at 0
prb = list()
for ii in xrange(len(data)-1):
if (((data[ii] > 0) and (data[ii+1] < 0)) or ((data[ii] < 0) and (data[ii+1] > 0))) and data1[ii] > 0:
prb.append(ii)
return array(prb)
t = linspace(0, 1000.0, 100000)
print ("step size is " + str(t[1]-t[0]))
# Representative initial conditions for E=1
E = 1
x0=0
y0=0
init_cons = [[x0, y0, np.sqrt(2*E-(1.0*i/10.0)*(1.0*i/10.0)-2.0/(n+1)*(kappa1*np.absolute(x0)**(n+1)+kappa2*np.absolute(y0-x0)**(n+1)+kappa3*np.absolute(y0)**(n+1))), 1.0*i/10.0] for i in range(-10,11)]
outs = list()
for con in init_cons:
outs.append( rungekutta4(pqdot, t, con) )
# plot the results
fig1 = figure(1)
for ii in xrange(4):
subplot(2, 2, ii+1)
plot(outs[ii][:,1],outs[ii][:,3])
ylabel("py")
xlabel("y")
title("Full trajectory projected onto the plane")
fig1.suptitle('Full trajectories E = 1', fontsize=10)
# Plot Poincare sections at x=0 and px>0
fig2 = figure(2)
for ii in xrange(4):
subplot(2, 2, ii+1)
xcrossings = findcrossings(outs[ii][:,0], outs[ii][:,3])
yints = [.5*(outs[ii][cross, 1] + outs[ii][cross+1, 1]) for cross in xcrossings]
pyints = [.5*(outs[ii][cross, 3] + outs[ii][cross+1, 3]) for cross in xcrossings]
plot(yints, pyints,'.')
ylabel("py")
xlabel("y")
title("Poincare section x = 0")
fig2.suptitle('Poincare Sections E = 1', fontsize=10)
show()
You need to compute the derivatives of the Hamiltonian correctly. The derivative of |y-x|^n for x is
n*(x-y)*|x-y|^(n-2)=n*sign(x-y)*|x-y|^(n-1)
and the derivative for y is almost, but not exactly (as in your code), the same,
n*(y-x)*|x-y|^(n-2)=n*sign(y-x)*|x-y|^(n-1),
note the sign difference. With this correction you can take larger time steps, with correct linear interpolation probably even larger ones, to obtain the images
I changed the integration of the ODE to
t = linspace(0, 1000.0, 2000+1)
...
E_kin = E-total_energy([x0,y0,0,0])
init_cons = [[x0, y0, (2*E_kin-py**2)**0.5, py] for py in np.linspace(-10,10,8)]
outs = [ odeint(pqdot, con, t, atol=1e-9, rtol=1e-8) ) for con in init_cons[:8] ]
Obviously the number and parametrization of initial conditions may change.
The computation and display of the zero-crossings was changed to
def refine_crossing(a,b):
tf = -a[0]/a[2]
while abs(b[0])>1e-6:
b = odeint(pqdot, a, [0,tf], atol=1e-8, rtol=1e-6)[-1];
# Newton step using that b[0]=x(tf) and b[2]=x'(tf)
tf -= b[0]/b[2]
return [ b[1], b[3] ]
# Plot Poincare sections at x=0 and px>0
fig2 = figure(2)
for ii in xrange(8):
#subplot(4, 2, ii+1)
xcrossings = findcrossings(outs[ii][:,0], outs[ii][:,3])
ycrossings = [ refine_crossing(outs[ii][cross], outs[ii][cross+1]) for cross in xcrossings]
yints, pyints = array(ycrossings).T
plot(yints, pyints,'.')
ylabel("py")
xlabel("y")
title("Poincare section x = 0")
and evaluating the result of a longer integration interval
I have a function called func(mu, gamma) . For each combination of mu and gamma, the function will return a value, let's call it return_value.
Now I have set range for mu and gamma:
mu = np.linspace(0,1,100)
gamma = np.linspace(0,1,100)
Now we have 1e4 combinations and each combinations corresponds to a return_value. I want to plot a heatmap for return_value.
I have tried to use pcolor in Python. However, from the example in the documentation:
import matplotlib.pyplot as plt
import numpy as np
# make these smaller to increase the resolution
dx, dy = 0.15, 0.05
# generate 2 2d grids for the x & y bounds
y, x = np.mgrid[slice(-3, 3 + dy, dy),
slice(-3, 3 + dx, dx)]
z = (1 - x / 2. + x ** 5 + y ** 3) * np.exp(-x ** 2 - y ** 2)
# x and y are bounds, so z should be the value *inside* those bounds.
# Therefore, remove the last value from the z array.
z = z[:-1, :-1]
z_min, z_max = -np.abs(z).max(), np.abs(z).max()
because the defined function fun in my script can not take array as input, it does not work and I get this message if I follow the example:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Below is my code for func:
def fun(mu, gamma2):
Isolation_Ratio = []
kappa1 = gamma2
kappa2 = gamma2
gamma1 = gamma2
g0 = gamma2 + kappa2 + gamma1 + kappa1
gammag = kappa1/2. + gamma1/2.
gamma = gamma2/2. + kappa2/2.
for ii in range(len(rangedeltaw)):
deltaw = rangedeltaw[ii]
Forward_delta = forward_delta(mu, deltaw)
Backward_delta = backward_delta(mu, deltaw)
forward_root1, forward_root2, forward_root3 = forward_root(mu, deltaw)
test_D, backward_root1, backward_root2, backward_root3 = backward_root(mu, deltaw)
Root1.append(backward_root1)
Root2.append(backward_root2)
Root3.append(backward_root3)
root1.append(forward_root1)
root2.append(forward_root2)
root3.append(forward_root3)
if Forward_delta >= 0 and Backward_delta >= 0:
a2sq = [max([forward_root1.real, forward_root2.real, forward_root3.real])]
b1sq = [max([backward_root1.real, backward_root2.real, backward_root3.real])]
A2sq.append(max([forward_root1.real, forward_root2.real, forward_root3.real]))
B1sq.append(max([backward_root1.real, backward_root2.real, backward_root3.real]))
for ii in range(len(a2sq)):
for jj in range(len(b1sq)):
Isolation_Ratio.append(kappa2*a2sq[ii]/(kappa1*b1sq[jj]))
elif Forward_delta >= 0 and Backward_delta < 0:
a2sq = [max([forward_root1.real, forward_root2.real, forward_root3.real])]
b1sq = [backward_root1.real]
A2sq.append(max([forward_root1.real, forward_root2.real, forward_root3.real]))
B1sq.append(backward_root1.real)
for ii in range(len(a2sq)):
for jj in range(len(b1sq)):
Isolation_Ratio.append(kappa2*a2sq[ii]/(kappa1*b1sq[jj]))
elif Forward_delta < 0 and Backward_delta >= 0:
a2sq = [forward_root1.real]
b1sq = [max([backward_root1.real, backward_root2.real, backward_root3.real])]
A2sq.append(forward_root1.real)
B1sq.append(max([backward_root1.real, backward_root2.real, backward_root3.real]))
for ii in range(len(a2sq)):
for jj in range(len(b1sq)):
Isolation_Ratio.append(kappa2*a2sq[ii]/(kappa1*b1sq[jj]))
else:
A2sq.append(forward_root1.real)
B1sq.append(backward_root1.real)
Isolation_Ratio.append(kappa2*forward_root1.real/(kappa1*backward_root1.real))
x = Isolation_RangeDeltaw
y = Isolation_Ratio
return max(y)
So, first, how to obtain the heatmap. fun() is still not self-contained (forward_delta() etc are not defined), so I cannot execute it, and you didn't specify at which line the error occurs, but I can guess that the offender is
if Forward_delta >= 0 and Backward_delta >= 0:
meaning that forward_delta() etc functions work with arrays. By the look of it, it may be possible to fully vectorize the function, but it is a non-trivial task and is a question of its own (and if you ever ask it, make sure to make a self contained example). A simpler, although a less efficient solution is to just fill the heatmap value by value:
import matplotlib.pyplot as plt
import numpy
def fun(mu, gamma):
# your function
mu = numpy.linspace(0,1,100)
gamma = numpy.linspace(0,1,100)
# filling the heatmap, value by value
fun_map = numpy.empty((mu.size, gamma.size))
for i in range(mu.size):
for j in range(gamma.size):
fun_map[i,j] = fun(mu[i], gamma[j])
Now that you have the array, the second part of your question is how to plot it. pcolor() is used to visualize discreet arrays; imshow() suits your purpose better:
fig = plt.figure()
s = fig.add_subplot(1, 1, 1, xlabel='$\\gamma$', ylabel='$\\mu$')
im = s.imshow(
fun_map,
extent=(gamma[0], gamma[-1], mu[0], mu[-1]),
origin='lower')
fig.colorbar(im)
fig.savefig('t.png')
Note that in the array the X dimension is last (corresponds to gamma), but imshow puts the X dimension first.
The result for a simple function
def fun(mu, gamma):
return numpy.sin(mu) + numpy.cos(gamma)
will look like
I have 4-dimensional data, say for the temperature, in an numpy.ndarray.
The shape of the array is (ntime, nheight_in, nlat, nlon).
I have corresponding 1D arrays for each of the dimensions that tell me which time, height, latitude, and longitude a certain value corresponds to, for this example I need height_in giving the height in metres.
Now I need to bring it onto a different height dimension, height_out, with a different length.
The following seems to do what I want:
ntime, nheight_in, nlat, nlon = t_in.shape
nheight_out = len(height_out)
t_out = np.empty((ntime, nheight_out, nlat, nlon))
for time in range(ntime):
for lat in range(nlat):
for lon in range(nlon):
t_out[time, :, lat, lon] = np.interp(
height_out, height_in, t[time, :, lat, lon]
)
But with 3 nested loops, and lots of switching between python and numpy, I don't think this is the best way to do it.
Any suggestions on how to improve this? Thanks
scipy's interp1d can help:
import numpy as np
from scipy.interpolate import interp1d
ntime, nheight_in, nlat, nlon = (10, 20, 30, 40)
heights = np.linspace(0, 1, nheight_in)
t_in = np.random.normal(size=(ntime, nheight_in, nlat, nlon))
f_out = interp1d(heights, t_in, axis=1)
nheight_out = 50
new_heights = np.linspace(0, 1, nheight_out)
t_out = f_out(new_heights)
I was looking for a similar function that works with irregularly spaced coordinates, and ended up writing my own function. As far as I see, the interpolation is handled nicely and the performance in terms of memory and speed is also quite good. I thought I'd share it here in case anyone else comes across this question looking for a similar function:
import numpy as np
import warnings
def interp_along_axis(y, x, newx, axis, inverse=False, method='linear'):
""" Interpolate vertical profiles, e.g. of atmospheric variables
using vectorized numpy operations
This function assumes that the x-xoordinate increases monotonically
ps:
* Updated to work with irregularly spaced x-coordinate.
* Updated to work with irregularly spaced newx-coordinate
* Updated to easily inverse the direction of the x-coordinate
* Updated to fill with nans outside extrapolation range
* Updated to include a linear interpolation method as well
(it was initially written for a cubic function)
Peter Kalverla
March 2018
--------------------
More info:
Algorithm from: http://www.paulinternet.nl/?page=bicubic
It approximates y = f(x) = ax^3 + bx^2 + cx + d
where y may be an ndarray input vector
Returns f(newx)
The algorithm uses the derivative f'(x) = 3ax^2 + 2bx + c
and uses the fact that:
f(0) = d
f(1) = a + b + c + d
f'(0) = c
f'(1) = 3a + 2b + c
Rewriting this yields expressions for a, b, c, d:
a = 2f(0) - 2f(1) + f'(0) + f'(1)
b = -3f(0) + 3f(1) - 2f'(0) - f'(1)
c = f'(0)
d = f(0)
These can be evaluated at two neighbouring points in x and
as such constitute the piecewise cubic interpolator.
"""
# View of x and y with axis as first dimension
if inverse:
_x = np.moveaxis(x, axis, 0)[::-1, ...]
_y = np.moveaxis(y, axis, 0)[::-1, ...]
_newx = np.moveaxis(newx, axis, 0)[::-1, ...]
else:
_y = np.moveaxis(y, axis, 0)
_x = np.moveaxis(x, axis, 0)
_newx = np.moveaxis(newx, axis, 0)
# Sanity checks
if np.any(_newx[0] < _x[0]) or np.any(_newx[-1] > _x[-1]):
# raise ValueError('This function cannot extrapolate')
warnings.warn("Some values are outside the interpolation range. "
"These will be filled with NaN")
if np.any(np.diff(_x, axis=0) < 0):
raise ValueError('x should increase monotonically')
if np.any(np.diff(_newx, axis=0) < 0):
raise ValueError('newx should increase monotonically')
# Cubic interpolation needs the gradient of y in addition to its values
if method == 'cubic':
# For now, simply use a numpy function to get the derivatives
# This produces the largest memory overhead of the function and
# could alternatively be done in passing.
ydx = np.gradient(_y, axis=0, edge_order=2)
# This will later be concatenated with a dynamic '0th' index
ind = [i for i in np.indices(_y.shape[1:])]
# Allocate the output array
original_dims = _y.shape
newdims = list(original_dims)
newdims[0] = len(_newx)
newy = np.zeros(newdims)
# set initial bounds
i_lower = np.zeros(_x.shape[1:], dtype=int)
i_upper = np.ones(_x.shape[1:], dtype=int)
x_lower = _x[0, ...]
x_upper = _x[1, ...]
for i, xi in enumerate(_newx):
# Start at the 'bottom' of the array and work upwards
# This only works if x and newx increase monotonically
# Update bounds where necessary and possible
needs_update = (xi > x_upper) & (i_upper+1<len(_x))
# print x_upper.max(), np.any(needs_update)
while np.any(needs_update):
i_lower = np.where(needs_update, i_lower+1, i_lower)
i_upper = i_lower + 1
x_lower = _x[[i_lower]+ind]
x_upper = _x[[i_upper]+ind]
# Check again
needs_update = (xi > x_upper) & (i_upper+1<len(_x))
# Express the position of xi relative to its neighbours
xj = (xi-x_lower)/(x_upper - x_lower)
# Determine where there is a valid interpolation range
within_bounds = (_x[0, ...] < xi) & (xi < _x[-1, ...])
if method == 'linear':
f0, f1 = _y[[i_lower]+ind], _y[[i_upper]+ind]
a = f1 - f0
b = f0
newy[i, ...] = np.where(within_bounds, a*xj+b, np.nan)
elif method=='cubic':
f0, f1 = _y[[i_lower]+ind], _y[[i_upper]+ind]
df0, df1 = ydx[[i_lower]+ind], ydx[[i_upper]+ind]
a = 2*f0 - 2*f1 + df0 + df1
b = -3*f0 + 3*f1 - 2*df0 - df1
c = df0
d = f0
newy[i, ...] = np.where(within_bounds, a*xj**3 + b*xj**2 + c*xj + d, np.nan)
else:
raise ValueError("invalid interpolation method"
"(choose 'linear' or 'cubic')")
if inverse:
newy = newy[::-1, ...]
return np.moveaxis(newy, 0, axis)
And this is a small example to test it:
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d as scipy1d
# toy coordinates and data
nx, ny, nz = 25, 30, 10
x = np.arange(nx)
y = np.arange(ny)
z = np.tile(np.arange(nz), (nx,ny,1)) + np.random.randn(nx, ny, nz)*.1
testdata = np.random.randn(nx,ny,nz) # x,y,z
# Desired z-coordinates (must be between bounds of z)
znew = np.tile(np.linspace(2,nz-2,50), (nx,ny,1)) + np.random.randn(nx, ny, 50)*0.01
# Inverse the coordinates for testing
z = z[..., ::-1]
znew = znew[..., ::-1]
# Now use own routine
ynew = interp_along_axis(testdata, z, znew, axis=2, inverse=True)
# Check some random profiles
for i in range(5):
randx = np.random.randint(nx)
randy = np.random.randint(ny)
checkfunc = scipy1d(z[randx, randy], testdata[randx,randy], kind='cubic')
checkdata = checkfunc(znew)
fig, ax = plt.subplots()
ax.plot(testdata[randx, randy], z[randx, randy], 'x', label='original data')
ax.plot(checkdata[randx, randy], znew[randx, randy], label='scipy')
ax.plot(ynew[randx, randy], znew[randx, randy], '--', label='Peter')
ax.legend()
plt.show()
Following the criteria of numpy.interp, one can assign the left/right bounds to the points outside the range adding this lines after within_bounds = ...
out_lbound = (xi <= _x[0,...])
out_rbound = (_x[-1,...] <= xi)
and
newy[i, out_lbound] = _y[0, out_lbound]
newy[i, out_rbound] = _y[-1, out_rbound]
after newy[i, ...] = ....
If I understood well the strategy used by #Peter9192, I think the changes are in the same line. I've checked a little bit, but maybe some strange case could not work properly.
could you please help me with finding points of intersection in graphic
import numpy as np
import matplotlib.pyplot as plt
#interact
def foo(count=(1,10,1), t=slider(100,1000,100,default=100)):
plt.cla()
dt = 1/t
x = np.arange(1, step=dt)
xl = np.arange(1, step=.000001)
W = np.zeros(t, np.dtype(float))
#Iteration Logarithm
l = np.sqrt(2*xl*ln(ln(1/xl)))
plt.plot(xl, l,'r--')
plt.plot(xl, -l,'r--')
mu, sig = 0, 1
for ITER in range(1, count+1): #count of W[i] in plot
for i in range(1, len(W)):
W[i] = W[i-1] + np.random.normal(mu, sig) * np.sqrt(dt) #Wiener process
plt.plot(x,W)
plt.xlabel('t',fontsize=26)
plt.ylabel('W(t)',fontsize=26)
plt.grid(True)
#interact
def _dee(deep=slider(0.0001, .4, 0.001, default=.2)): #scale
plt.xlim(0, deep)
plt.ylim(-.5, .5)
plt.show()
I use https://cloud.sagemath.com
Can't realize, how to find points of graphic cross each other.
Thanks.
Although I'm not familiar with sage, getting intersection points given two sampled function should be easy - just calculate the difference between them, and there will be an intersection every time the sign changes.
step=0.1
x= np.arange(-5,5, step=step)
f1 = x**2 - 4
f2 = -x**2 + 4
dif= f2-f1
dif_sign= dif/np.abs(dif) #just the sign of the function
dif_sign_dif= np.diff(dif_sign) #places where the sign changes
change_idxs= np.where(dif_sign_dif!=0)[0] #indexes where the sign changes
print -5+change_idxs*step
output:
[-2. 2.]
Since you are adding brownian motion, you'll get "false positives" once in while, though.