translated matlab code into python, but python is way slower - python

So I've been starting to use python recently, and i am working on a project of calculating wind exposure. I've managed my code in matlab and it runs very fast(can be done in 3 minutes), but after I translated my code into python, i am getting the same result but it takes 3hours to finish it's job. I really need a hand on checking what's causing such a huge difference...
So here's my python code. I can give out my matlab code if anyone need it.
from netCDF4 import Dataset, num2date
import numpy as np
import matplotlib.pyplot as plt
from scipy import interpolate
#import pylab as py
#input data
dem = Dataset('comparearea_fill.nc','r')
lon = np.array(dem.variables['lon'])
lat = np.array(dem.variables['lat'])
DEM = np.array(dem.variables['elevation'])
carea = Dataset('carea.nc','r')
u = np.array(carea.variables['u10'])
v = np.array(carea.variables['v10'])
mu = np.mean(u, axis=0)
mv = np.mean(v, axis=0)
x = np.linspace(1,21,21)
y = np.linspace(1,11,11)
newu = interpolate.interp2d(x, y, mu, kind='cubic')
newv = interpolate.interp2d(x, y, mv, kind='cubic')
spu = newu(lon,lat)
spv = newv(lon,lat)
A = np.zeros((4951,9451))
B = np.zeros((4951,9451))
for i in range(100,4850):
for j in range(100,9350):
for n in range(20):
A[i,j] = (DEM[i,j]-np.max(DEM[np.floor(n*spv[i,j]).astype(int),j-np.floor(n*spu[i,j]).astype(int)]))/DEM[i,j]
if A[i,j] < 0:
A[i,j] = 0
B[i,j] = (DEM[i,j]-np.max(DEM[i-np.ceil(n*spv[i,j]).astype(int),j-np.ceil(n*spu[i,j]).astype(int)]))/DEM[i,j]
if B[i,j] < 0:
B[i,j] = 0
C = A+B
plt.contourf(lon,lat,C); plt.colorbar()
here the mu and mv are the monthly average of the u and v wind, while the spu and spv are the spline interpulated u and v wind to fit the resolution of my dem data set.

Related

Need help to convert the following R code to Python

I need help in converting the following R code in Python. Particularly with the matrix function from R (variable W), I find it difficult to convert it to Python as my only idea would be to use np.random.uniform() but don't know whether that works. Can anyone help me? Thanks!!
set.seed(1)
n = 100;
p = 400;
Z= runif(n)-1/2;
W = matrix(runif(n*p)-1/2, n, p);
beta = 1/seq(1:p)^2; # approximately sparse beta
#beta = rnorm(p)*.2 # dense beta
gX = exp(4*Z)+ W%*%beta; # leading term nonlinear
X = cbind(Z, Z^2, Z^3, W ); # polynomials in Zs will be approximating exp(4*Z)
Y = gX + rnorm(n); #generate Y
plot(gX,Y, xlab="g(X)", ylab="Y") #plot V vs g(X)
print( c("theoretical R2:", var(gX)/var(Y)))
var(gX)/var(Y); #theoretical R-square in the simulation example
Something like this?
import numpy as np
from matplotlib import pyplot as plt
n,p = 100,400
Z,W = np.random.rand(n)-1/2, np.random.rand(n,p)-1/2
beta =np.ones(p)/np.arange(1,1+p)**2
gX = np.exp(4*Z) + np.matmul(W,beta)
Y = gX + np.random.rand(n)
plt.scatter(gX,Y); plt.xlabel("g(X)"); plt.ylabel("Y");
gX.var()/Y.var()

Having problems with scipy.integrate.solve_ivp

I am trying to use scipy.integrate.solve_ivp to calculate the solutions to newton's gravitation equation for my n body simulation, however I am confused how the function is passed into solve_ivp. I have the following code:
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import solve_ivp
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
G = 6.67408e-11
m_sun = 1988500e24
m_jupiter = 1898.13e24
m_earth = 5.97219e24
au = 149597870.700e3
v_factor = 1731460
year = 31557600.e0
init_s = np.array([-6.534087946884256E-03*au, 6.100454846284101E-03*au, 1.019968145073305E-04*au, -6.938967653087248E-06*v_factor, -5.599052606952444E-06*v_factor, 2.173251724105919E-07*v_factor])
init_j = np.array([2.932487231769548E+00*au, -4.163444383137574E+00*au, -4.833604407653648E-02*au, 6.076788230491844E-03*v_factor, 4.702729516645153E-03*v_factor, -1.554436340872727E-04*v_factor])
variables_s = init_s
variables_j = init_j
N = 2
tStart = 0e0
t_End = 25*year
Nt = 2000
dt = t_End/Nt
temp_end = dt
t=tStart
domain = (t, temp_end)
planetsinit = np.vstack((init_s, init_j))
planetspos = planetsinit[:,0:3]
mass = np.vstack((1988500e24, 1898.13e24))
def weird_division(n, d):
return n / d if d else 0
variables_save = np.zeros((N,6,Nt))
variables_save[:,:,0] = planetsinit
pos_s = planetspos[0]
pos_j = planetspos[1]
while t < t_End:
t_index = int(weird_division(t, dt))
for index in range(len(planetspos)):
for otherindex in range(len(planetspos)):
if index != otherindex:
x1_p1, x2_p1, x3_p1 = planetsinit[index, 0:3]
x1_p2, x2_p2, x3_p2 = planetsinit[otherindex, 0:3]
m = mass[otherindex]
def f_grav(t, y):
x1_p1, x2_p1, x3_p1, v1_p1, v2_p1, v3_p1 = y
x1_diff = x1_p1 - x1_p2
x2_diff = x2_p1 - x2_p2
x3_diff = x3_p1 - x3_p2
dydt = [v1_p1,
v2_p1,
v3_p1,
-(x1_diff)*G*m/((x1_diff)**2+(x2_diff)**2+(x3_diff)**2)**(3/2),
-(x2_diff)*G*m/((x1_diff)**2+(x2_diff)**2+(x3_diff)**2)**(3/2),
-(x3_diff)*G*m/((x1_diff)**2+(x2_diff)**2+(x3_diff)**2)**(3/2)]
return dydt
solution = solve_ivp(fun=f_grav, t_span=domain, y0=planetsinit[index])
planetsinit[index] = solution['y'][0:6, -1]
variables_save[index,:,t_index] = solution['y'][0:6, -1]
planetspos[index] = planetsinit[index][0:3]
t += dt
temp_end += dt
domain = (t,temp_end)
pos_s = variables_save[0,0:3,:]
pos_j = variables_save[1,0:3,:]
plt.plot(variables_save[0,0:3,:][0], variables_save[0,0:3,:][1])
plt.plot(variables_save[1,0:3,:][0], variables_save[1,0:3,:][1])
The code above works very nicely and produces a stable orbit. However when I calculate the acceleration outside the function and feed that through into the f_grav function, something goes wrong and produces an orbit which is no longer stable. However I am perplexed as I don't know why the data is different as to be it seems like that I have passed through the exactly same inputs. Which leads me to think that maybe its the way the the function f_grav is interpolated by the solve_ivp integrator? To calculate the acceleration outside all I do is change the following code in the loop to:
x1_p1, x2_p1, x3_p1 = planetsinit[index, 0:3]
x1_p2, x2_p2, x3_p2 = planetsinit[otherindex, 0:3]
m = mass[otherindex]
x1_diff = x1_p1 - x1_p2
x2_diff = x2_p1 - x2_p2
x3_diff = x3_p1 - x3_p2
ax = -(x1_diff)*G*m/((x1_diff)**2+(x2_diff)**2+(x3_diff)**2)**(3/2)
ay = -(x2_diff)*G*m/((x1_diff)**2+(x2_diff)**2+(x3_diff)**2)**(3/2)
az = -(x3_diff)*G*m/((x1_diff)**2+(x2_diff)**2+(x3_diff)**2)**(3/2)
def f_grav(t, y):
x1_p1, x2_p1, x3_p1, v1_p1, v2_p1, v3_p1 = y
dydt = [v1_p1,
v2_p1,
v3_p1,
ax,
ay,
az]
return dydt
solution = solve_ivp(fun=f_grav, t_span=domain, y0=planetsinit[index])
planetsinit[index] = solution['y'][0:6, -1]
variables_save[index,:,t_index] = solution['y'][0:6, -1]
planetspos[index] = planetsinit[index][0:3]
As I said I don't know why different orbits are produces which are shown below and any hints as to why or how to solve it would me much appreciated. To clarify why I can't use the working code as it is, as when more bodies are involved I aim to sum the accelerations contribution of all the other planets which isn't possible this way where the acceleration is calculated in the function itself.
Sorry for the large coding chunks but I did feel it was appropriate as then it could be run and the problem itself is clearer.
Both have the same time period, dt, however the orbit on the left is stable and the one on the right is not

Implementing the metropolis-hasting algorithm

Over the past few weeks I have been trying to understand MCMC and the Metropolis-Hastings, but I have failed every time I tried to implement it.
So I am trying to use the metropolis-Hastings algorithm to get the Boltzmann distribution from the uniform distribution, but it is not working.
Here is a summary of what I am doing:
I draw a random number form the uniform distribution m.
I draw another random number form the uniform distribution n.
I set dU = n-m.
If dU < 0, I accept dU, set m = n , and repeat.
If dU > 0, I calculate w = exp(-b*dU), where b is 1/kT, and draw a random number form the uniform distribution r.
If w > r, I accept dU, set m = n, and repeat.
7 If w < r, I reject dU, set m = m, and repeat.
I am a beginner to this field and to python, so I am not sure if the code wrong or the algorithm is wrong ( probably both.)
My code is attached below. Thank you.
import random
%matplotlib inline
import numpy as np
import scipy
import matplotlib.pyplot as plt
from scipy import stats
k = 1.38064852 * 10**(-23)
t = 298
b = 1/(t*k) U = []
m = np.random.uniform(0, 1)
for j in range(100000):
n = np.random.uniform(0, 1)
du = n-m
if du<0:
U.append(du)
m = n
elif du > 0:
w = np.exp(-b*du)
r = np.random.uniform(0, 1)
if w > r:
U.append(du)
m = n
else:
U.append(du)
m = m
Your problem are twofold. One is you sample new energy ('n=random()') as dimensionless quantity, which contradicts everything else you're doing (your temperature is in Kelvin, kB is in J/K etc). And second, using values like 1023 and inverse are not good in physical simulations - you'd better be somewhere within 0...1 range and rescale later. Below I made code which works in electron-volts, sample new energy in eV as well, and produced something which resembles the truth.
import numpy as np
import matplotlib.pyplot as plt
kB = 1.0/11600. # eV/K
T = 300 # K
b = 1.0/(kB * T) # inverse temperature, eV^-1
np.random.seed(76543217) # for reproducibility
N = 100000
EE = np.empty(N+1) # energy
DE = np.empty(N+1) # delta energy
Ei = 1.0 # initial energy, 1eV
EE[0] = Ei
DE[0] = 0.0
for k in range(N):
E = np.random.random()/b # sample energy, in eV
dE = E - Ei
if dE < 0.0:
Ei = E
EE[k+1] = Ei
DE[k+1] = dE
elif dE > 0.0:
w = np.exp(-b*dE)
r = np.random.random()
if w > r:
Ei = E
EE[k+1] = Ei
DE[k+1] = dE
else:
EE[k+1] = Ei
DE[k+1] = 0.0
x = np.linspace(0, N+1, num=N+1)
print(EE[N-30:])
print(np.mean(EE[N-1000:]))
print(np.mean(EE[N-2000:]))
fig, ax = plt.subplots(1, 1)
ax.plot(x[N-1000:], EE[N-1000:], 'r-', lw=5, alpha=0.6, label='Energy')
ax.plot(x[N-1000:], DE[N-1000:], 'go', lw=5, alpha=0.6, label='Delta Energy')
plt.show()
printed are two last mean values for 1000 and 2000 samples, look thermalized to me
0.010188070423940562
0.010666101150488673
and graph for E/dE

3D plot of a generated 2D matrix

I've written a code for my school project. The u and v matrices are generated already. I've made a 2D contour, but I wish to plot u and v in 3D.
import numpy as np
#import matplotlib.pyplot as plt
#inputs
m = 40
n = 20
Uinf = 2
delX = 0.05
delY = 0.05
nu = 0.8e-2
u= np.zeros((m+1,n))
v= np.zeros((m+1,n))
#intializing boundry conditions
u[:,0] = v[:,0] = v[:,n-1] = v[0,:] = 0
u[:,n-1] = u[0,:] = Uinf
#main program
for i in range(0,m):
for j in range(1,n-1):
a = (nu*delX) / (u[i,j]*delY**2)
b = (v[i,j]*delX) / (2*u[i,j]*delY)
u[i+1,j] = (a-b)*u[i,j+1]+(1-2*a)*u[i,j]+(a+b)*u[i,j-1]
v[i+1,j] = v[i+1,j-1]-(delY/(2*delX))*(u[i+1,j]-u[i,j]+u[i+1,j-1]-u[i,j-1])
I have to mention that I don't wanna generate an arbitrary function; u[i,j] and v[i,j] are present.
Thanks!

Python plotting loop - where is my memory going?

I have the following loop which plots a figure and then saves it onto disk, repeated iteratively 120 times. Python's RAM use initially is around 2.2GB (Data and SeaP arrays are 120x721x1440) so quite large to start. However RAM use increases on each loop iteration, so much so that by quarter of the way through (i = 30) RAM use is 7.9GB and rising. Is there a memory leak? Or a way I can prevent this increasing, I see no reason as to why it should be increasing - code is trivial. Code in the loop in question below.
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np
from scipy.ndimage.filters import minimum_filter, maximum_filter
Lon = np.linspace(-180,180,1440)
Lat = np.linspace(-90,90,721)
Lon,Lat = np.meshgrid(Lon,Lat)
m = Basemap(projection='laea',width=10000000,height=6500000,resolution ='l',lat_ts=50,lat_0=55,lon_0=-25)
X, Y = m(Lon, Lat)
def Make_SLP(PRMSL,X,Y,Cont_Int,window=30):
mn = minimum_filter(PRMSL, size=window, mode='wrap')
mx = maximum_filter(PRMSL, size=window, mode='wrap')
local_min, local_max = np.nonzero(PRMSL == mn), np.nonzero(PRMSL == mx)
clevs = np.arange(900,1100.,4.)
csl = m.contour(X,Y,PRMSL,np.arange(950,1050,Cont_Int),colors='k',linewidths=0.3)
xlows = X[local_min]; xhighs = X[local_max]
ylows = Y[local_min]; yhighs = Y[local_max]
lowvals = PRMSL[local_min]; highvals = PRMSL[local_max]
xyplotted = []
# don't plot if there is already a L or H within dmin meters.
yoffset = 0.022*(m.ymax-m.ymin)
dmin = yoffset
for x,y,p in zip(xlows, ylows, lowvals):
if x < m.xmax and x > m.xmin and y < m.ymax and y > m.ymin:
dist = [np.sqrt((x-x0)**2+(y-y0)**2) for x0,y0 in xyplotted]
if not dist or min(dist) > dmin:
plt.text(x,y,'L',fontsize=16,fontweight='bold',
ha='center',va='center',color='b',clip_on=True)
plt.text(x,y-yoffset,repr(int(p)),fontsize=9,
ha='center',va='top',color='b',
bbox = dict(boxstyle="square",ec='None',fc=(1,1,1,0.5)),clip_on=True)
xyplotted.append((x,y))
# plot highs as red H's, with max pressure value underneath.
xyplotted = []
for x,y,p in zip(xhighs, yhighs, highvals):
if x < m.xmax and x > m.xmin and y < m.ymax and y > m.ymin:
dist = [np.sqrt((x-x0)**2+(y-y0)**2) for x0,y0 in xyplotted]
if not dist or min(dist) > dmin:
plt.text(x,y,'H',fontsize=16,fontweight='bold',
ha='center',va='center',color='r',clip_on=True)
plt.text(x,y-yoffset,repr(int(p)),fontsize=9,
ha='center',va='top',color='r',
bbox = dict(boxstyle="square",ec='None',fc=(1,1,1,0.5)),clip_on=True)
xyplotted.append((x,y))
return plt
for i in range(0,100):
plt = Make_SLP(np.random.rand(721,1440)*1000,X,Y,10,window=30)
print i

Categories