Plotting inequalities in Python - python

I want to shade the area of the XY plane where Y<18 x^2.
This is my code:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-.25, .25, 25)
y = np.linspace(0, 1, 20)
X,Y = np.meshgrid(x, y)
Z = masqarr(1,X, Y)
plt.imshow( (Y< 18*X**2).astype(float) ,
extent=(X.min(),X.max(),Y.min(),Y.max()),origin="lower", cmap="Greys", alpha = 0.3, aspect='auto', interpolation = 'hanning');
However, the output I get produces a plot with plateau as in:
How can I gat a proper smooth plot?

This is a resolution problem, you are defining your axes with too few poitns. I tried this:
import numpy as np
import matplotlib.pyplot as plt
resolution = 200
x = np.linspace(-.25, .25, resolution)
y = np.linspace(0, 1, resolution)
X,Y = np.meshgrid(x, y)
plt.imshow( (Y< 18*X**2).astype(float) ,
extent=(X.min(),X.max(),Y.min(),Y.max()),origin="lower", cmap="Greys", alpha = 0.3, aspect='auto', interpolation = 'hanning');
plt.show()
resolution = 25
resolution = 100
resolution = 200

Related

Can we put a flat heatmap on a 3D axis?

Can we plot a straight heatmap on a 3D axis? The heatmap is as follows:
I am able to get a 3D elevation map, but I am not looking for that. I just want this straight lying on a 3D axis.
Code:
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from scipy import interpolate
excel_data_df = pd.read_excel('test.xlsx')
X= excel_data_df['x'].tolist()
Y= excel_data_df['y'].tolist()
Z= excel_data_df['z'].tolist()
X = np.array(X)
Y = np.array(Y)
Z = np.array(Z)
# Flatten trial dataset to meet your requirement:
x = X.ravel()
y = Y.ravel()
z = Z.ravel()
# Resampling on as square grid with given resolution:
resolution = 8
xlin = np.linspace(min(x), max(x), resolution)
ylin = np.linspace(min(y), max(y), resolution)
Xlin, Ylin = np.meshgrid(xlin, ylin)
# Linear multi-dimensional interpolation:
interpolant = interpolate.NearestNDInterpolator([r for r in zip(x, y)], z)
Zhat = interpolant(Xlin.ravel(), Ylin.ravel()).reshape(Xlin.shape)
cmap = 'jet'
# Render and interpolate again if necessary:
fig, axe = plt.subplots()
axe.imshow(Zhat, origin="lower", cmap=cmap, interpolation='bicubic',extent=[min(x),max(x),min(y),max(y)])
plt.xticks(np.arange(min(x), max(x)+1, 1.0))
plt.yticks(np.arange(min(y), max(y)+1, 1.0))
axe.grid(True, linewidth=0.3, color='w')
norm = matplotlib.colors.Normalize(vmin = min(z), vmax = max(z), clip = False)
plt.colorbar(plt.cm.ScalarMappable(cmap = cmap, norm=norm))
plt.show()

How to normalize colorbar in Python?

I want to adjust colobar scale from my current figure1 to the desired figure2 !!
My colorbar scale range is -1 to 1, but I want it in exponential form and for that I tried levels = np.linspace(-100e-2,100e-2) as well, but it also doesn't give the desired scale2
import xarray as xr
import numpy as np
import matplotlib.pyplot as plt
ds = xr.open_dataset('PL_Era_Tkt.nc')
wp = ds.w.mean(dim=['longitude','latitude']).plot.contourf(x='time',cmap='RdBu',add_colorbar=False,extend='both')
wpcb = plt.colorbar(wp)
wpcb.set_label(label='Pa.s${^{-1}}$',size=13)
plt.gca().invert_yaxis()
plt.title('Vertical Velocity',size=15)
My current scale
My desired scale
Since the data is not presented, I added normalized color bars with the data from the graph sample here. I think the color bar scales will also be in log format with this setup. Please note that the data used is not large, so I have not been able to confirm this.
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.ticker as ticker
import numpy as np
plt.style.use('seaborn-white')
def f(x, y):
return np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
x = np.linspace(0, 5, 50)
y = np.linspace(0, 5, 40)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
fig, ax = plt.subplots()
ax.contourf(X, Y, Z, 20, cmap='RdGy')
cmap = mpl.cm.RdGy
norm = mpl.colors.Normalize(vmin=-1, vmax=1.0)
fig.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=cmap),
ax=ax, orientation='vertical', label='Some Units', extend='both', ticks=ticker.LogLocator())
plt.show()

How to rescale a plot in a subplot with matplotlib

I have 4 subplots with a different 3D plot with a colorbar.
I want to plot a XY view of my 3D plot, remove the x,y,z axis and resize my plot to use all the space available in the subplot such that the XY view has the same height as the colorbar. I can remove the axis but I do not know how to resize the image. I attached a working code to illustrate this.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.tri as mtri
import matplotlib
import numpy as np
# Create 3D function
n_radii = 8
n_angles = 36
radii = np.linspace(0.125, 1.0, n_radii)
angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)[..., np.newaxis]
x = np.append(0, (radii*np.cos(angles)).flatten())
y = np.append(0, (radii*np.sin(angles)).flatten())
z = np.sin(-x*y)
fig = plt.figure()
for ii in range(1, 4):
#Plot
# ============================================================================
ax = fig.add_subplot(2,2, ii, projection='3d')
cs =ax.plot_trisurf(x, y, z, linewidth=0.2, antialiased=True)
ax.view_init(90, 0)
plt.title(ii)
# ax.axis('off')
plt.grid(b=None)
# Create color bar
# ============================================================================
norm = matplotlib.colors.Normalize(vmin = 0, vmax = 1, clip = False)
m = plt.cm.ScalarMappable(norm=norm)
m.set_array([])
plt.colorbar(m)
plt.tight_layout()
plt.show()
#plt.savefig("test.pdf",bbox_inches='tight')
Any idea how can I do this?
I have added
plt.gca().set_axis_off()
plt.axis([0.6 * x for x in plt.axis()])
to your code which hides the axes and sets the view to 60% of its previous value. The result looks like this:
Full code:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.tri as mtri
import matplotlib
import numpy as np
# Create 3D function
n_radii = 8
n_angles = 36
radii = np.linspace(0.125, 1.0, n_radii)
angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)[..., np.newaxis]
x = np.append(0, (radii*np.cos(angles)).flatten())
y = np.append(0, (radii*np.sin(angles)).flatten())
z = np.sin(-x*y)
fig = plt.figure()
for ii in range(1, 4):
#Plot
# ============================================================================
ax = fig.add_subplot(2,2, ii, projection='3d')
cs =ax.plot_trisurf(x, y, z, linewidth=0.2, antialiased=True)
ax.view_init(90, 0)
plt.title(ii)
# ax.axis('off')
plt.grid(b=None)
# Create color bar
# ============================================================================
norm = matplotlib.colors.Normalize(vmin = 0, vmax = 1, clip = False)
m = plt.cm.ScalarMappable(norm=norm)
m.set_array([])
plt.colorbar(m)
plt.gca().set_axis_off()
plt.axis([0.6 * x for x in plt.axis()])
plt.tight_layout()
plt.show()
#plt.savefig("test.pdf",bbox_inches='tight')

Plot normal distribution in 3D

I am trying to plot the comun distribution of two normal distributed variables.
The code below plots one normal distributed variable. What would the code be for plotting two normal distributed variables?
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.mlab as mlab
import math
mu = 0
variance = 1
sigma = math.sqrt(variance)
x = np.linspace(-3, 3, 100)
plt.plot(x,mlab.normpdf(x, mu, sigma))
plt.show()
It sounds like what you're looking for is a Multivariate Normal Distribution. This is implemented in scipy as scipy.stats.multivariate_normal. It's important to remember that you are passing a covariance matrix to the function. So to keep things simple keep the off diagonal elements as zero:
[X variance , 0 ]
[ 0 ,Y Variance]
Here is an example using this function and generating a 3D plot of the resulting distribution. I add the colormap to make seeing the curves easier but feel free to remove it.
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import multivariate_normal
from mpl_toolkits.mplot3d import Axes3D
#Parameters to set
mu_x = 0
variance_x = 3
mu_y = 0
variance_y = 15
#Create grid and multivariate normal
x = np.linspace(-10,10,500)
y = np.linspace(-10,10,500)
X, Y = np.meshgrid(x,y)
pos = np.empty(X.shape + (2,))
pos[:, :, 0] = X; pos[:, :, 1] = Y
rv = multivariate_normal([mu_x, mu_y], [[variance_x, 0], [0, variance_y]])
#Make a 3D plot
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(X, Y, rv.pdf(pos),cmap='viridis',linewidth=0)
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_zlabel('Z axis')
plt.show()
Giving you this plot:
Edit the method used below was deprecated in Matplotlib v2.2 and removed in v3.1
A simpler version is available through matplotlib.mlab.bivariate_normal
It takes the following arguments so you don't need to worry about matrices
matplotlib.mlab.bivariate_normal(X, Y, sigmax=1.0, sigmay=1.0, mux=0.0, muy=0.0, sigmaxy=0.0)
Here X, and Y are again the result of a meshgrid so using this to recreate the above plot:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.mlab import bivariate_normal
from mpl_toolkits.mplot3d import Axes3D
#Parameters to set
mu_x = 0
sigma_x = np.sqrt(3)
mu_y = 0
sigma_y = np.sqrt(15)
#Create grid and multivariate normal
x = np.linspace(-10,10,500)
y = np.linspace(-10,10,500)
X, Y = np.meshgrid(x,y)
Z = bivariate_normal(X,Y,sigma_x,sigma_y,mu_x,mu_y)
#Make a 3D plot
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(X, Y, Z,cmap='viridis',linewidth=0)
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_zlabel('Z axis')
plt.show()
Giving:
The following adaption to #Ianhi's code above returns a contour plot version of the 3D plot above.
import matplotlib.pyplot as plt
from matplotlib import style
style.use('fivethirtyeight')
import numpy as np
from scipy.stats import multivariate_normal
#Parameters to set
mu_x = 0
variance_x = 3
mu_y = 0
variance_y = 15
x = np.linspace(-10,10,500)
y = np.linspace(-10,10,500)
X,Y = np.meshgrid(x,y)
pos = np.array([X.flatten(),Y.flatten()]).T
rv = multivariate_normal([mu_x, mu_y], [[variance_x, 0], [0, variance_y]])
fig = plt.figure(figsize=(10,10))
ax0 = fig.add_subplot(111)
ax0.contour(X, Y, rv.pdf(pos).reshape(500,500))
plt.show()
While the other answers are great, I wanted to achieve similar results while also illustrating the distribution with a scatter plot of the sample.
More details can be found here: Python 3d plot of multivariate gaussian distribution
The results looks like:
And is generated using the following code:
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from scipy.stats import multivariate_normal
# Sample parameters
mu = np.array([0, 0])
sigma = np.array([[0.7, 0.2], [0.2, 0.3]])
rv = multivariate_normal(mu, sigma)
sample = rv.rvs(500)
# Bounds parameters
x_abs = 2.5
y_abs = 2.5
x_grid, y_grid = np.mgrid[-x_abs:x_abs:.02, -y_abs:y_abs:.02]
pos = np.empty(x_grid.shape + (2,))
pos[:, :, 0] = x_grid
pos[:, :, 1] = y_grid
levels = np.linspace(0, 1, 40)
fig = plt.figure()
ax = fig.gca(projection='3d')
# Removes the grey panes in 3d plots
ax.xaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
ax.yaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
ax.zaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
# The heatmap
ax.contourf(x_grid, y_grid, 0.1 * rv.pdf(pos),
zdir='z', levels=0.1 * levels, alpha=0.9)
# The wireframe
ax.plot_wireframe(x_grid, y_grid, rv.pdf(
pos), rstride=10, cstride=10, color='k')
# The scatter. Note that the altitude is defined based on the pdf of the
# random variable
ax.scatter(sample[:, 0], sample[:, 1], 1.05 * rv.pdf(sample), c='k')
ax.legend()
ax.set_title("Gaussian sample and pdf")
ax.set_xlim3d(-x_abs, x_abs)
ax.set_ylim3d(-y_abs, y_abs)
ax.set_zlim3d(0, 1)
plt.show()

Probability surface plot matplotlib

I have 2d values of x and y which span from x - [ 1 , 5 ] and y - [0.1 - 0.5]
How can I plot the 3d surface where the axis are x , y and P(y) in matplotlib ?
I found out the code for doing so in matlab on net but I am unable to understand it and consequently convert it into matplotlib... ( the range of values is completely different for below written code as to what I require )
mu = [1 -1]; Sigma = [.9 .4; .4 .3];
[X1,X2] = meshgrid(linspace(-1,3,25)', linspace(-3,1,25)');
X = [X1(:) X2(:)];
p = mvnpdf(X, mu, Sigma);
surf(X1,X2,reshape(p,25,25));
Can someone help me out in doing the exact same thing for matplotlib ( plot_surface perhaps ? )
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.mlab as mlab
import numpy as np
def P(X, Y):
return mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
fig = plt.figure()
ax = fig.gca(projection = '3d')
jet = plt.get_cmap('jet')
x = np.linspace(-2, 2, 60)
y = np.linspace(-2, 2, 60)
X, Y = np.meshgrid(x, y)
Z = P(X, Y)
surf = ax.plot_surface(X, Y, Z, rstride = 1, cstride = 1, cmap = jet, linewidth = 0)
ax.set_zlim3d(0, Z.max())
plt.show()
yields

Categories