Changing axis values with imshow and showing data points - python

I would like to properly change the axes so I can see the values of the x and y components of the two frequencies. I have two sets of code: the first shows the proper data but the axes are wrong, the second shows the proper axes but my two data points are not showing.
First code:
from scipy.fft import fft2, fftshift
import numpy as np
import matplotlib.pyplot as plt
from skimage.filters import window
from scipy.fftpack import fftfreq
k = np.linspace(0,4.76*10,2400)
kx,ky = np.meshgrid(k, k)
x1 = 0.3
y1 = 0.4
x2 = 0.3
y2 = 1
z = 0.05*np.cos(2*np.pi*kx*x1 + 2*np.pi*ky*y1) + 0.05*np.cos(2*np.pi*kx*x2 + 2*np.pi*ky*y2)
wz = z * window('hann', z.shape)
zf = np.abs(fftshift(fft2(wz)))[1200:, 1200:]
plt.figure(1)
plt.axis([0,100, 0,100])
plt.imshow(zf)
plt.show()
And the results are:
The second code:
from scipy.fft import fft2, fftshift
import numpy as np
import matplotlib.pyplot as plt
from skimage.filters import window
from scipy.fftpack import fftfreq
k = np.linspace(0,4.76*10,2400)
kx,ky = np.meshgrid(k, k)
x1 = 0.3
y1 = 0.4
x2 = 0.3
y2 = 1
z = 0.05*np.cos(2*np.pi*kx*x1 + 2*np.pi*ky*y1) + 0.05*np.cos(2*np.pi*kx*x2 + 2*np.pi*ky*y2)
wz = z * window('hann', z.shape)
zf = np.abs(fftshift(fft2(wz)))[1200:, 1200:]
fig, ax = plt.subplots()
ax.set(xlim=(0, 2), ylim=(0, 2))
f = fftfreq(len(k), np.diff(k)[0])
ax.imshow(zf,extent=[0,f[:k.size//2][-1], 0 , f[:k.size//2][-1]])
plt.show()

You need to change the origin in the second example:
ax.imshow(zf, origin='lower', extent=[0,f[:k.size//2][-1], 0 , f[:k.size//2][-1]])

Related

Equation with Matplotlib

How can i do this equation with library Matplotlib?
f(x) = exp(sqrt(x))/2 - sqrt(x**3)/5 + 2
import matplotlib as plt
import numpy as np
import math
fig, (ax1) = plt.subplots(nrows=2)
x = np.linspace(-3, 3, 100)
ax1.plot(x, 0.5.np.exp)
plt.show()
This represents your equation, but please double check it.
import math
e1 = lambda x: 0.5 * math.exp(-1 * math.sqrt(x)) - (0.2 * math.sqrt(x^3)) + 2
e1(1) # 1.901097008111102

Matplotlib animation with time-dependent parameter

I am new using python and I would like to ask you a problem that I have with my current code. I am solving a partial differential equation (1D in space) and I want to make an animation at each time for the given numerical solution, but I don't want to save all the arrays of the solution at each time (because this is not efficient)
For simplicity I just show you the analytical solution of the differential equation.
I have tried to make a plot for each time steep trying to make an animation, but as I have read in other places it's not too much efficient due to the plt.pause()
import numpy as np
import math
from matplotlib import pyplot as plt
pi = math.pi
xmin = 0.0
xmax = 10.0
N = 100 #number of points
x = np.arange(xmin, xmax , (xmax-xmin)/N)
def solution(t):
p = np.exp(-x**2/(4*k*t))/(np.sqrt(4.*pi*k*t))
return p
t_final = 10.0
t_initial = 0.0
t = t_initial
dt = 0.1
k = 1.0
while t<t_final:
t +=dt
pp = solution(t)
plt.ion()
plt.xlabel('x')
plt.ylabel('P')
plt.plot(x, pp, 'r-',label = "t=%s" % t)
plt.legend(loc='upper right')
plt.draw()
plt.pause(10**(-20))
plt.show()
plt.clf()
Do you know how can be re-implemented my code to make an animation (and save it) without save the data ?
Here is how to use FuncAnimation to generate the desired animation
import numpy as np
import math
from matplotlib import pyplot as plt
pi = math.pi
xmin = 0.0
xmax = 10.0
N = 100 #number of points
x = np.arange(xmin, xmax , (xmax-xmin)/N)
t_initial = 0.0
t_final = 10.0
dt = 0.1
k = 1.0
fig, ax = plt.subplots()
ax.set_xlabel('x')
ax.set_ylabel('P')
plotLine, = ax.plot(x, np.zeros(len(x))*np.NaN, 'r-')
plotTitle = ax.set_title("t=0")
ax.set_ylim(0,1.)
ax.set_xlim(xmin,xmax)
def solution(t):
p = np.exp(-x**2/(4*k*t))/(np.sqrt(4.*pi*k*t))
return p
def animate(t):
pp = solution(t)
plotLine.set_ydata(pp)
plotTitle.set_text(f"t = {t:.1f}")
#ax.relim() # use if autoscale desired
#ax.autoscale()
return [plotLine,plotTitle]
ani = animation.FuncAnimation(fig, func=animate, frames=np.arange(t_initial, t_final+dt, dt), blit=True)
plt.show()
This way uses a library I wrote, celluloid. With it I only had to change a handful of lines from your code: mainly the few calls with celluloid and changing the legend creation slightly.
import numpy as np
import math
from matplotlib import pyplot as plt
from celluloid import Camera
pi = math.pi
xmin = 0.0
xmax = 10.0
N = 100 #number of points
x = np.arange(xmin, xmax , (xmax-xmin)/N)
def solution(t):
p = np.exp(-x**2/(4*k*t))/(np.sqrt(4.*pi*k*t))
return p
t_final = 10.0
t_initial = 0.0
t = t_initial
dt = 0.1
k = 1.0
fig = plt.figure()
camera = Camera(fig)
plt.xlabel('x')
plt.ylabel('P')
while t<t_final:
t +=dt
pp = solution(t)
line = plt.plot(x, pp, 'r-')
plt.legend(line, ['t={:.1f}'.format(t)], loc='upper right')
camera.snap()
animation = camera.animate()
animation.save('animation.mp4')

Low to adjust the limit of my `colorbar`

I was wondering how could I reset the limit of my colorbar, such that it has axis from 0 to 16 instead of 0 to 14.
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
from scipy.io import netcdf
import numpy as np
import os
fig = plt.figure(figsize=(16,6))
map=Basemap(projection='merc',llcrnrlat=-21.25,urcrnrlat=21.25,\
llcrnrlon=1.25,urcrnrlon=358.75,resolution='c')
map.drawcoastlines()
os.chdir( '/Users/wenyuz/Documents/')
f = netcdf.netcdf_file('precip.mon.mean.nc', 'r')
lon = f.variables['lon']
lat = f.variables['lat']
precip = f.variables['precip']
precip_tm=np.mean(precip[1:,27:45,:],0)
print np.shape(precip_tm)
delta = 2.5
long_west=1.25
long_east=358.75
lat_south=21.25
lat_north=-21.25
x = np.arange(long_west, long_east+delta, delta)
y = np.arange(lat_south, lat_north-delta, -delta)
X1, Y1=np.meshgrid(x,y)
X, Y = map(X1, Y1)
CS = map.contourf(X, Y, precip_tm,cmap=plt.cm.gist_ncar,vmin=0,vmax=16);
cbar = map.colorbar(CS,location="bottom")
cbar.set_clim(0, 16)
cbar.set_label('mm')
plt.title('GPCP: 1979-2008')
f.close()
somehow, if I replace map.contourf with map.pcolormesh it works to rest the colorbar limit.

missing wedge in matplotlib contourf plot

I'm trying to plot a contour plot in matplotlib and I keep getting a missing "wedge". The following example illustrates what I'm trying to do.
import numpy as np
import matplotlib.pyplot as plt
ph_cut = 0.05
nphi = 13
phi = np.linspace(ph_cut,2*np.pi-ph_cut, nphi)
nr = 50
rmax=1
rr = np.linspace(0, rmax, nr)
PH, RR = np.meshgrid(phi,rr)
X = RR * np.cos(PH)
Y = RR * np.sin(PH)
Z = np.sin(PH)
nlev = 13
levels=np.linspace(-1, 1, nlev)
cs=plt.contourf(X,Y,Z, levels)
plt.colorbar(cs)
plt.show()
The wedge between -ph_cut and ph_cut is never filled. Is there no way for matplotlib to interpolate across? Strictly speaking, this region is no different and has no less information than the corresponding pi-ph_cut to pi+ph_cut... I tried searching around but could not find any solution.
Just don't leave out the cut:
import numpy as np
import matplotlib.pyplot as plt
ph_cut = 0.05
nphi = 13
phi = np.linspace(0,2*np.pi, nphi)
nr = 50
rmax=1
rr = np.linspace(0, rmax, nr)
PH, RR = np.meshgrid(phi,rr)
X = RR * np.cos(PH)
Y = RR * np.sin(PH)
Z = np.sin(PH)
nlev = 13
levels=np.linspace(-1, 1, nlev)
cs=plt.contourf(X,Y,Z, levels)
plt.colorbar(cs)
plt.show()

How to plot normal distribution

Given a mean and a variance is there a simple function call which will plot a normal distribution?
import matplotlib.pyplot as plt
import numpy as np
import scipy.stats as stats
import math
mu = 0
variance = 1
sigma = math.sqrt(variance)
x = np.linspace(mu - 3*sigma, mu + 3*sigma, 100)
plt.plot(x, stats.norm.pdf(x, mu, sigma))
plt.show()
I don't think there is a function that does all that in a single call. However you can find the Gaussian probability density function in scipy.stats.
So the simplest way I could come up with is:
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
# Plot between -10 and 10 with .001 steps.
x_axis = np.arange(-10, 10, 0.001)
# Mean = 0, SD = 2.
plt.plot(x_axis, norm.pdf(x_axis,0,2))
plt.show()
Sources:
http://www.johndcook.com/distributions_scipy.html
http://docs.scipy.org/doc/scipy/reference/stats.html
http://telliott99.blogspot.com/2010/02/plotting-normal-distribution-with.html
Use seaborn instead
i am using distplot of seaborn with mean=5 std=3 of 1000 values
value = np.random.normal(loc=5,scale=3,size=1000)
sns.distplot(value)
You will get a normal distribution curve
If you prefer to use a step by step approach you could consider a solution like follows
import numpy as np
import matplotlib.pyplot as plt
mean = 0; std = 1; variance = np.square(std)
x = np.arange(-5,5,.01)
f = np.exp(-np.square(x-mean)/2*variance)/(np.sqrt(2*np.pi*variance))
plt.plot(x,f)
plt.ylabel('gaussian distribution')
plt.show()
Unutbu answer is correct.
But because our mean can be more or less than zero I would still like to change this :
x = np.linspace(-3 * sigma, 3 * sigma, 100)
to this :
x = np.linspace(-3 * sigma + mean, 3 * sigma + mean, 100)
I believe that is important to set the height, so created this function:
def my_gauss(x, sigma=1, h=1, mid=0):
from math import exp, pow
variance = pow(sigma, 2)
return h * exp(-pow(x-mid, 2)/(2*variance))
Where sigma is the standard deviation, h is the height and mid is the mean.
To:
plt.close("all")
x = np.linspace(-20, 20, 101)
yg = [my_gauss(xi) for xi in x]
Here is the result using different heights and deviations:
I have just come back to this and I had to install scipy as matplotlib.mlab gave me the error message MatplotlibDeprecationWarning: scipy.stats.norm.pdf when trying example above. So the sample is now:
%matplotlib inline
import math
import matplotlib.pyplot as plt
import numpy as np
import scipy.stats
mu = 0
variance = 1
sigma = math.sqrt(variance)
x = np.linspace(mu - 3*sigma, mu + 3*sigma, 100)
plt.plot(x, scipy.stats.norm.pdf(x, mu, sigma))
plt.show()
you can get cdf easily. so pdf via cdf
import numpy as np
import matplotlib.pyplot as plt
import scipy.interpolate
import scipy.stats
def setGridLine(ax):
#http://jonathansoma.com/lede/data-studio/matplotlib/adding-grid-lines-to-a-matplotlib-chart/
ax.set_axisbelow(True)
ax.minorticks_on()
ax.grid(which='major', linestyle='-', linewidth=0.5, color='grey')
ax.grid(which='minor', linestyle=':', linewidth=0.5, color='#a6a6a6')
ax.tick_params(which='both', # Options for both major and minor ticks
top=False, # turn off top ticks
left=False, # turn off left ticks
right=False, # turn off right ticks
bottom=False) # turn off bottom ticks
data1 = np.random.normal(0,1,1000000)
x=np.sort(data1)
y=np.arange(x.shape[0])/(x.shape[0]+1)
f2 = scipy.interpolate.interp1d(x, y,kind='linear')
x2 = np.linspace(x[0],x[-1],1001)
y2 = f2(x2)
y2b = np.diff(y2)/np.diff(x2)
x2b=(x2[1:]+x2[:-1])/2.
f3 = scipy.interpolate.interp1d(x, y,kind='cubic')
x3 = np.linspace(x[0],x[-1],1001)
y3 = f3(x3)
y3b = np.diff(y3)/np.diff(x3)
x3b=(x3[1:]+x3[:-1])/2.
bins=np.arange(-4,4,0.1)
bins_centers=0.5*(bins[1:]+bins[:-1])
cdf = scipy.stats.norm.cdf(bins_centers)
pdf = scipy.stats.norm.pdf(bins_centers)
plt.rcParams["font.size"] = 18
fig, ax = plt.subplots(3,1,figsize=(10,16))
ax[0].set_title("cdf")
ax[0].plot(x,y,label="data")
ax[0].plot(x2,y2,label="linear")
ax[0].plot(x3,y3,label="cubic")
ax[0].plot(bins_centers,cdf,label="ans")
ax[1].set_title("pdf:linear")
ax[1].plot(x2b,y2b,label="linear")
ax[1].plot(bins_centers,pdf,label="ans")
ax[2].set_title("pdf:cubic")
ax[2].plot(x3b,y3b,label="cubic")
ax[2].plot(bins_centers,pdf,label="ans")
for idx in range(3):
ax[idx].legend()
setGridLine(ax[idx])
plt.show()
plt.clf()
plt.close()
import math
import matplotlib.pyplot as plt
import numpy
import pandas as pd
def normal_pdf(x, mu=0, sigma=1):
sqrt_two_pi = math.sqrt(math.pi * 2)
return math.exp(-(x - mu) ** 2 / 2 / sigma ** 2) / (sqrt_two_pi * sigma)
df = pd.DataFrame({'x1': numpy.arange(-10, 10, 0.1), 'y1': map(normal_pdf, numpy.arange(-10, 10, 0.1))})
plt.plot('x1', 'y1', data=df, marker='o', markerfacecolor='blue', markersize=5, color='skyblue', linewidth=1)
plt.show()
For me, this worked pretty well if you are trying to plot a particular pdf
theta1 = {
"a": 0.5,
"cov" : 1,
"mean" : 0
}
x = np.linspace(start = 0, stop = 1000, num = 1000)
pdf = stats.norm.pdf(x, theta1['mean'], theta1['cov']) + theta2['a']
sns.lineplot(x,pdf)

Categories

Resources