I want to shade the surface and the contours of a specific function based on some constraint in the domain of the function. So far I have the following and I want to improve it.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import LinearLocator, FormatStrFormatter
plt.figure(figsize=(8, 6))
plt.axes(projection="3d")
xdata = np.linspace(-3, 3, 20000)
ydata = np.linspace(-3, 3, 20000)
X, Y = np.meshgrid(xdata, ydata)
Z1 = X ** 2 + Y ** 2
Z2 = Z1.copy()
Z3 = Z1.copy()
Z1[np.multiply(X, Y) > 3] = np.nan
Z2[np.multiply(X, Y) <= 3] = np.nan
Z3[np.multiply(X, Y) == 3] = np.nan
ax3d = plt.axes(projection='3d')
ax3d.plot_surface(X, Y, Z1, cmap='Greys', antialiased=True, vmin=-np.nanmin(Z1), vmax=np.nanmax(Z1))
ax3d.plot_surface(X, Y, Z2, cmap='YlGnBu', antialiased=True, vmin=-np.nanmin(Z2), vmax=np.nanmax(Z2))
ax3d.contourf(X, Y, Z1, zdir='z', offset=0, cmap='Greys')
ax3d.contourf(X, Y, Z2, zdir='z', offset=0, cmap='Greys')
ax3d.set_title('Surface Plot in Matplotlib')
ax3d.set_xlabel('X')
ax3d.set_ylabel('Y')
ax3d.set_zlabel('Z')
plt.show()
Could you please someone help to solve the following problems:
The surface is over-imposed by the contour surface.
There are some gaps in the surface.
The contours of the two constraints are not continuous.
Is it possible to plot a line in the border of the two surfaces and contours?
Any help is highly appreciated.
The code below makes the following changes:
creating a custom colormap combining the two existing colormaps
using a TwoSlopeNorm to have the separation at z=3
setting antialiased=False (otherwise matplotlib creates a plot of antialiased lines instead of polygons)
xdata and ydata with 300 steps
using rstride=1, cstride=1 so every x and every y will be considered; this makes the surface smoother (but takes more time)
calling plt.axes(...) only once to prevent a dummy subplot
calling contourf before plot_surface; due to the painter's algorithm, matplotlib only minimally supports 3D overlaps
import matplotlib.pyplot as plt
from matplotlib.colors import TwoSlopeNorm, ListedColormap
import numpy as np
xdata = np.linspace(-3, 3, 300)
ydata = np.linspace(-3, 3, 300)
X, Y = np.meshgrid(xdata, ydata)
Z1 = X ** 2 + Y ** 2
cmap1 = plt.get_cmap('Greys')
cmap2 = plt.get_cmap('YlGnBu')
cmap = ListedColormap(np.r_[cmap1(np.linspace(0, 1, 128)), cmap2(np.linspace(0, 1, 128))])
norm = TwoSlopeNorm(vmin=np.nanmin(Z1), vmax=np.nanmax(Z1), vcenter=3)
plt.figure(figsize=(8, 6))
ax3d = plt.axes(projection='3d')
ax3d.contourf(X, Y, Z1, zdir='z', offset=0, cmap=cmap, norm=norm)
ax3d.plot_surface(X, Y, Z1, cmap=cmap, antialiased=False, norm=norm, rstride=1, cstride=1)
ax3d.set_title('Surface Plot in Matplotlib')
ax3d.set_xlabel('X')
ax3d.set_ylabel('Y')
ax3d.set_zlabel('Z')
plt.show()
xdata = np.linspace(-3, 3, 1000)
ydata = np.linspace(-3, 3, 1000)
X, Y = np.meshgrid(xdata, ydata)
Z1 = X ** 2 + Y ** 2
Z2 = Z1.copy()
Z3 = Z1.copy()
Z2[np.multiply(X, Y) <= 3] = np.nan
Z3[np.multiply(X, Y) == 3] = np.nan
plt.figure(figsize=(8, 6))
ax3d = plt.axes(projection='3d')
ax3d.contourf(X, Y, Z1, zdir='z', offset=0, cmap='Greys')
ax3d.contourf(X, Y, Z2, zdir='z', offset=0, cmap='YlGnBu')
ax3d.plot_surface(X, Y, Z1, cmap='Greys', antialiased=True, vmin=-np.nanmin(Z1), vmax=np.nanmax(Z1), alpha=.5)
ax3d.plot_surface(X, Y, Z2, cmap='YlGnBu', antialiased=True, vmin=-np.nanmin(Z2), vmax=np.nanmax(Z2), alpha=.5)
ax3d.set_title('Surface Plot in Matplotlib')
ax3d.set_xlabel('X')
ax3d.set_ylabel('Y')
ax3d.set_zlabel('Z')
plt.show()
I want to draw a spin systems. I have the picture below. However, I want the quivers to be INSIDE the scatter circles and the "Main arrow" to be a bright one. Thus, how can I order three plots?
Thank You in advance!
Here is the code:
import matplotlib.pyplot as plt
from matplotlib import cm, colors
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
############################## A sphere #################################
r = 4
pi = np.pi
cos = np.cos
sin = np.sin
phi, theta = np.mgrid[0.0:pi:100j, 0.0:2.0*pi:100j]
x = r*sin(phi)*cos(theta)
y = r*sin(phi)*sin(theta)
z = r*cos(phi)
#Set colours and render
fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(x, y, z, rstride=1, cstride=1, color='red', alpha=0.6, linewidth=0)
############################ One arrow ########################
x1 = 0
y1 = 0
z1 = 0
dx1 = 0
dy1 = 0
dz1 = 2
ax.quiver(x1, y1, z1, dx1, dy1, dz1, pivot='middle', color="blue", linewidths=5.0,length=1.4)
ax.scatter(0, 0, 0,color="blue", s=800)
############################ Array of arrows ############################################
ax.set_xlim([-4,4])
ax.set_ylim([-4,4])
ax.set_zlim([-4,4])
ax.set_aspect("equal")
plt.tight_layout()
N = 5 # number of points - 5x5x5
scale = 0.4 # scale for the increment of an arrow
ax = fig.gca(projection='3d')
xx = np.linspace(-3.5, 3.5, N)
yy = np.linspace(-3.5, 3.5, N)
zz = np.linspace(-3.5, 3.5, N)
dxx = scale*np.random.rand(N)
dyy = scale*np.random.rand(N)
dzz = scale*np.random.rand(N)
x, y, z = np.meshgrid(yy, zz, xx)
dx, dy, dz = np.meshgrid(dxx, dyy, dzz)
ax.scatter(x, y, z,color="orange", s=200)
ax.quiver(x, y, z, dx, dy, dz, pivot='middle', length=1.6, color="blue")
plt.show()
I'm looking to plot a 2D probability distribution with one of its marginals in a single plot using Python and matplotlib. I'm almost there, but the line in the plot is always drawn in front of the surface, instead of being occluded properly. How do I fix this?
import numpy as np
import scipy.stats as stats
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
fig = plt.figure()
ax = fig.gca(projection='3d')
delta = 0.05
f = 0.5
X, Y = np.meshgrid(np.arange(-3.0, 3.0, delta),
np.arange(-3.0, 3.0, delta))
xy = np.hstack((X.flatten()[:, None], Y.flatten()[:, None]))
p1 = stats.multivariate_normal.pdf(xy, mean=[1, -1], cov=(np.eye(2) * 0.28 * f))
p2 = stats.multivariate_normal.pdf(xy, mean=[-1, 1], cov=(np.eye(2) * 0.5 * f))
p = 0.3 * p1 + 0.7 * p2
Z = p.reshape(len(X), len(X))
plt.plot(X[0, :], np.zeros(len(X)) + 3, np.sum(Z, 0) * 0.05) # , color='red')
ax.plot_surface(X, Y, Z, alpha=1.0, cmap='jet', linewidth=0.1, rstride=2, cstride=2)
ax.set_xlabel('Object colour')
ax.set_ylabel('Illumination colour')
ax.set_zlabel('Probability density')
ax.set_zlim(min(cont_offset, np.min(Z)), max(np.max(Z), cont_offset))
plt.show()
The built-in contour function at least gets the z-order right; if you don't want the full thing, you could cheat with a calculated Z. To start, replacing your call to plt.plot with this:
from matplotlib import cm
cset = ax.contour(X, Y, Z, zdir='y', offset=3, cmap='binary')
cset = ax.contour(X, Y, Z, zdir='x', offset=-3, cmap='Blues')
Faking up Z's for the contours, one way:
from matplotlib import cm
Zys = np.zeros_like(Z)
Zys[60,:] = Z.max(0)
cset = ax.contour(X, Y, Zys, zdir='y', offset=3, cmap='binary')
Zys = np.zeros_like(Z)
Zys[:,60] = Z.max(1)
cset = ax.contour(X, Y, Zys, zdir='x', offset=-3, cmap='Blues')
More ambitiously, somewhere in the contour code they're calculating the z-order...
I have a three columns catalogue of data and I would like to make a 3D plot of them plus the projection of each axis as a projected contour in the the plane of the other two axises. So far I could make the 3D plot using matplotlib which still doesn't show anything from the properties of the data.
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from numpy import *
data=loadtxt('test.cat')
X=data[:,0]
Y=data[:,1]
Z=data[:,2]
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(X, Y, Z, c='r', marker='.')
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()
How could I plot the projection of the data in each plane with colorbar as well?
hmm, indeed, difficult data to display. Maybe creating some slices along one axis and creating certain number 2D plots would be best. However 3D plots are fancy. I played a bit with the data resulting in one 3D plot as you did and a separate plot with the projections.
The colors of the points are according the missing axis
Added transparency to give an idea of density
Kept axes of both plots the same
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
data = np.loadtxt('test.cat', skiprows=1)
X=data[:,0]
Y=data[:,1]
Z=data[:,2]
plt.figure()
ax1 = plt.subplot(111, projection='3d')
ax1.scatter(X, Y, Z, c='b', marker='.', alpha=0.2)
ax1.set_xlabel('X - axis')
ax1.set_ylabel('Y - axis')
ax1.set_zlabel('Z - axis')
plt.figure()
ax2 = plt.subplot(111, projection='3d')
plt.hot()
cx = np.ones_like(X) * ax1.get_xlim3d()[0]
cy = np.ones_like(X) * ax1.get_ylim3d()[1]
cz = np.ones_like(Z) * ax1.get_zlim3d()[0]
ax2.scatter(X, Y, cz, c=Z, marker='.', lw=0, alpha=0.2)
ax2.scatter(X, cy, Z, c=-Y, marker='.', lw=0, alpha=0.2)
ax2.scatter(cx, Y, Z, c=X, marker='.', lw=0, alpha=0.2)
ax2.set_xlim3d(ax1.get_xlim3d())
ax2.set_ylim3d(ax1.get_ylim3d())
ax2.set_zlim3d(ax1.get_zlim3d())
ax2.set_xlabel('X - axis')
ax2.set_ylabel('Y - axis')
ax2.set_zlabel('Z - axis')
According to what you want to do you need to use the zdir parameter for the contour and contourf functions. Here an example:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = Axes3D(fig)
X = np.arange(-4, 4, 0.25)
Y = np.arange(-4, 4, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X ** 2 + Y ** 2)
Z = np.sin(R)
ax.contourf(X, Y, Z, zdir='x', offset=-4, cmap=plt.cm.hot)
ax.contour(X, Y, Z, zdir='x', offset=-4, colors='k')
ax.contourf(X, Y, Z, zdir='y', offset=4, cmap=plt.cm.hot)
ax.contour(X, Y, Z, zdir='y', offset=4, colors='k')
ax.contourf(X, Y, Z, zdir='z', offset=-1, cmap=plt.cm.hot)
ax.contour(X, Y, Z, zdir='z', offset=-1, colors='k')
plt.show()
With result:
Here's hoping I'm not shooting a mosquito with a [very ugly] cannon, I recently made a Binning_Array class for a school project and I think it might be able to help you:
import numpy as np
import matplotlib.pyplot as plt
import binning_array as ba
from mpl_toolkits.mplot3d import axes3d
data = np.loadtxt('test.cat')
X = data[:,0]
Y = data[:,1]
Z = data[:,2]
n_points = data.shape[0]
X_min = np.round(np.min(data[:,0])-0.5)
X_max = np.round(np.max(data[:,0])+0.5)
Y_min = np.round(np.min(data[:,1])-0.5)
Y_max = np.round(np.max(data[:,1])+0.5)
Z_min = np.round(np.min(data[:,2])-0.5)
Z_max = np.round(np.max(data[:,2])+0.5)
n_min_bins = 25
step = min([(X_max-X_min)/n_min_bins, (Y_max-Y_min)/n_min_bins, (Z_max-Z_min)/n_min_bins])
# Using three Binners
BinnerXY = ba.Binning_Array([[X_min, X_max, step],
[Y_min, Y_max, step]])
BinnerYZ = ba.Binning_Array([[Y_min, Y_max, step],
[Z_min, Z_max, step]])
BinnerXZ = ba.Binning_Array([[X_min, X_max, step],
[Z_min, Z_max, step]])
for point in data:
BinnerXY.add_value([point[0], point[1]])
BinnerXZ.add_value([point[0], point[2]])
BinnerYZ.add_value([point[1], point[2]])
fig = plt.figure()
ax = [fig.add_subplot(221, projection='3d'),
fig.add_subplot(222),
fig.add_subplot(223),
fig.add_subplot(224)]
# Plot 2D projections on the 3D graph
vmin = np.min([BinnerXZ.bin_min(), BinnerYZ.bin_min(), BinnerXY.bin_min()])
vmax = np.max([BinnerXZ.bin_max(), BinnerYZ.bin_max(), BinnerXY.bin_max()])
levels = np.linspace(vmin,vmax,20)
xs_c = np.arange(*BinnerXZ.limits[0])
zs_c = np.arange(*BinnerXZ.limits[1])
ZS_C, XS_C = np.meshgrid(zs_c,xs_c)
ax[0].contourf(X=XS_C, Y=BinnerXZ.bins, Z=ZS_C,
zdir='y', offset=Y_max,
vmin=vmin, vmax=vmax,
cmap=plt.cm.coolwarm, levels=levels,
alpha=0.5)
xs_c = np.arange(*BinnerXY.limits[0])
ys_c = np.arange(*BinnerXY.limits[1])
YS_C, XS_C = np.meshgrid(ys_c,xs_c)
ax[0].contourf(X=XS_C, Y=YS_C, Z=BinnerXY.bins,
zdir='z', offset=Z_min,
vmin=vmin, vmax=vmax,
cmap=plt.cm.coolwarm, levels=levels,
alpha=0.5)
ys_c = np.arange(*BinnerYZ.limits[0])
zs_c = np.arange(*BinnerYZ.limits[1])
ZS_C, YS_C = np.meshgrid(zs_c, ys_c)
ax[0].contourf(X=BinnerYZ.bins, Y=YS_C, Z=ZS_C,
zdir='x', offset=X_min,
vmin=vmin, vmax=vmax,
cmap=plt.cm.coolwarm, levels=levels,
alpha=0.5)
# Plot scatter of all data
ax[0].scatter(X, Y, Z, c='g', marker='.', alpha=0.2)
ax[0].set_xlabel(r"$x$")
ax[0].set_ylabel(r"$y$")
ax[0].set_zlabel(r"$z$")
max_range = max([X_max-X_min, Y_max-Y_min, Z_max-Z_min]) / 2.
pos = [(X_max+X_min)/2., (Y_max+Y_min)/2., (Z_max+Z_min)/2.]
ax[0].set_xlim(pos[0] - max_range, pos[0] + max_range)
ax[0].set_ylim(pos[1] - max_range, pos[1] + max_range)
ax[0].set_zlim(pos[2] - max_range, pos[2] + max_range)
# Plot 2D histograms
BinnerXZ.plot_2d_slice(fig=fig, ax=ax[1], xlabel=r"$x$", ylabel=r'$z$')
BinnerXY.plot_2d_slice(fig=fig, ax=ax[2], xlabel=r"$x$", ylabel=r'$y$')
BinnerYZ.plot_2d_slice(fig=fig, ax=ax[3], xlabel=r"$y$", ylabel=r'$z$')
plt.show()
You can also use only one Binner, but notice that you will get artifacts where the planes intersect:
# ...
# Using three Binners
# ...
# Using only one Binner (adds a small error! see comments!)
Binner = ba.Binning_Array([[X_min, X_max, step],
[Y_min, Y_max, step],
[Z_min, Z_max, step]])
for point in data:
Binner.add_value([point[0], point[1], Z_min])
Binner.add_value([point[0], Y_max-step, point[2]])
Binner.add_value([X_min, point[1], point[2]])
fig = plt.figure()
ax = [fig.add_subplot(221, projection='3d'),
fig.add_subplot(222),
fig.add_subplot(223),
fig.add_subplot(224)]
ax[0].scatter(X, Y, Z, c='g', marker='.', alpha=0.2)
Binner.plot_slices(others={0:X_min, 1:Y_max, 2:Z_min}, fig=fig, ax=ax)
plt.show()
The binning_array.py was made for a school project and is not entirely polished, but it's enough for what you want.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
class Binning_Array:
def __init__(self, limits=[[-1.,1.,1.],[-1.,1.,1.]]):
"""Create a new binning array.
The amount of given limits determines the dimension of the array,
although only 2 and 3D have been tested.
Each limit must be a list of start, stop and step for the
axis it represents (x, y or z)."""
self.limits = np.array(limits)
self._shape = []
for i in xrange(len(self.limits)):
self._shape.append((self.limits[i][1]-self.limits[i][0]) / \
float(self.limits[i][2]))
self._shape = tuple(self._shape)
self.dimensions = len(self._shape)
self.bins = np.zeros(self._shape)
self.outside = 0.
self._normalized = 1.
def __repr__(self):
"""Representation method. <<REVIEW>>"""
return "Binning Array! Hurray!"
def __getitem__(self, index):
"""Direct acess to read self.bins (use something like self[index])
Direct acess to write would be given by __setitem__
"""
return self.bins.__getitem__(index)
def position2index(self,position,axis=0):
"""Convert a given position to an index in axis.
If it is outside, it returns -1.
"""
if self.limits[axis][0] <= position < self.limits[axis][1]:
return int((position - self.limits[axis][0]) / self.limits[axis][2])
else: return -1
def index2position(self, index, axis=0):
"""Convert a given index to a position in axis.
If it is outisde, it returns -1.
"""
if 0 <= index < self._shape[axis]:
return self.limits[axis][0] + self.limits[axis][2] * index
else:
return -1
def add_value(self, position, value=1., verbose=False):
"""Add a given value to a specified position.
If verbose it returns a list with the axies at which the position
is outside the scope of this Binning_Array.
Not very efficient because of that (verbose was for debugging).
"""
indexs = []
outside = False
if verbose:
outs = []
for i in xrange(self.dimensions):
# using self.dimensions serves as a filter
# if position has non valid shape
index = self.position2index(position[i],i)
if index == -1:
if verbose:
outside = True
outs.append(i)
else:
self.outside += value / self._normalized
return None # nothing, as it is not verbose
else:
indexs.append(index)
if outside: # the only way to get here is if verbose is True...
self.outside += value / self._normalized
return outs # so I can just return outs...
else:
self.bins[tuple(indexs)] += value / self._normalized
if verbose:
return outs
def get_value(self, position, verbose=False):
"""Return the value at the specified position.
If verbose it alse returns a list with the axies at which the position
is outside the scope of this Binning_Array.
"""
indexs = []
outside = False
if verbose:
outs = []
for i in xrange(self.dimensions):
index = self.position2index(position[i],i)
if index == -1:
if verbose:
outside = True
outs.append[i]
else:
return self.outside
else:
indexs.append(index)
if outside: # the only way to get here is if verbose is True
return self.outside, outs # so I can just return outs...
else:
if verbose:
return self.bins[tuple(indexs)], outs
else:
return self.bins[tuple(indexs)]
def normalize(self, total=None):
"""Divide the entire array by the sum of its values (and outside).
Any value added after this will be normalized by the same factor.
"""
if total is None:
total = self.n_counts()
self.bins /= total
self.outside /= total
self.normalize *= total
def n_counts(self):
"""Return the number of counts."""
return np.sum(self.bins) + self.outside
def bin_max(self):
"""Return the value of the largest bin."""
return np.max(self.bins)
def bin_min(self):
"""Return the value of the largest bin."""
return np.min(self.bins)
def plot_2d_slice(self, cuts=[0,1], others={},
fig=None, ax=None, show=True, **kwargs):
"""Plot a 2D slice."""
x = min(cuts)
y = max(cuts)
xs = np.arange(self.limits[x][0],
self.limits[x][1] + self.limits[x][2],
self.limits[x][2])
ys = np.arange(self.limits[y][0],
self.limits[y][1] + self.limits[y][2],
self.limits[y][2])
index = []
title = ''
for i in xrange(self.dimensions):
if i in cuts:
appendix = slice(self._shape[i]+1)
else:
appendix = others.get(i,(self.limits[i][0]+
self.limits[i][1]) / 2.)
title += '%d:%.4e\t' % (i,appendix)
appendix = self.position2index(appendix,i)
index.append(appendix)
index = tuple(index)
if fig is None:
fig, ax = plt.subplots(1,1)
YS,XS = np.meshgrid(ys, xs)
graph = ax.pcolormesh (XS, YS, self.bins[index], cmap=plt.cm.coolwarm)
fig.colorbar(graph, ax=ax)
ax.axis('equal')
ax.set_xlim(self.limits[x][0], self.limits[x][1])
ax.set_ylim(self.limits[y][0], self.limits[y][1])
if 'xticks' in kwargs:
ax.set_xticks(kwargs['xticks'])
if 'yticks' in kwargs.keys():
ax.set_yticks(kwargs['yticks'])
if 'xlabel' in kwargs:
ax.set_xlabel(kwargs['xlabel'])
if 'ylabel' in kwargs:
ax.set_ylabel(kwargs['ylabel'])
if 'xlim' in kwargs:
ax.set_xlim(*kwargs['xlim'])
if 'ylim' in kwargs:
ax.set_ylim(*kwargs['ylim'])
if show:
fig.tight_layout()
fig.show()
def plot_slices(self, others={}, fig=None, ax=None,
show=True, projections=True):
index = []
pos = []
title = ''
for i in xrange(self.dimensions):
temp = others.get(i,(self.limits[i][0]+self.limits[i][1])/2.)
title += '%d:%.4e\t' % (i,temp)
pos.append(temp)
index.append(self.position2index(temp,i))
if self.dimensions == 3:
if fig is None:
fig = plt.figure()
if projections:
ax = [fig.add_subplot(221, projection='3d'),
fig.add_subplot(222),
fig.add_subplot(223),
fig.add_subplot(224)]
else:
ax = fig.add_subplot(111, projection='3d')
if projections:
xs = np.arange(self.limits[0][0],
self.limits[0][1] + self.limits[0][2],
self.limits[0][2])
ys = np.arange(self.limits[1][0],
self.limits[1][1] + self.limits[1][2],
self.limits[1][2])
zs = np.arange(self.limits[2][0],
self.limits[2][1] + self.limits[2][2],
self.limits[2][2])
xs_c = np.arange(*self.limits[0])
ys_c = np.arange(*self.limits[1])
zs_c = np.arange(*self.limits[2])
vmin = np.min(self.bins)
vmax = np.max(self.bins)
levels = np.linspace(vmin,vmax,20)
#graph 0 (3D)
ax[0].set_xlabel(r"$x$")
ax[0].set_ylabel(r"$y$")
ax[0].set_zlabel(r"$z$")
#ax[0].axis('equal') #not supported in 3D:
#http://stackoverflow.com/questions/13685386/\
#matplotlib-equal-unit-length-with-equal-aspect-ratio-z-axis-is-not-equal-to
max_range = max([xs[-1]-xs[0],ys[-1]-ys[0],zs[-1]-zs[0]]) / 2.
# x_mean = (xs[-1] + xs[0])/2.
# y_mean = (ys[-1] + ys[0])/2.
# z_mean = (zs[-1] +zs[0])/2.
ax[0].set_xlim(pos[0] - max_range, pos[0] + max_range)
ax[0].set_ylim(pos[1] - max_range, pos[1] + max_range)
ax[0].set_zlim(pos[2] - max_range, pos[2] + max_range)
# to understand holes in contour plot:
#http://stackoverflow.com/questions/18897950/\
#matplotlib-pyplot-contourf-function-introduces-holes-or-gaps-when-plotting-regul
# graph 1 (2D)
ZS, XS = np.meshgrid(zs,xs)
ZS_C, XS_C = np.meshgrid(zs_c,xs_c)
ax[1].pcolormesh(XS, ZS, self.bins[:,index[1],:],
vmin=vmin, vmax=vmax,
cmap=plt.cm.coolwarm)
ax[0].contourf(X=XS_C, Y=self.bins[:,index[1],:], Z=ZS_C,
zdir='y', offset=pos[1],
vmin=vmin, vmax=vmax,
cmap=plt.cm.coolwarm, levels=levels,
alpha=0.5)
ax[1].set_xlabel(r"$x$")
ax[1].set_ylabel(r"$z$")
ax[1].set_xlim(xs[0],xs[-1])
ax[1].set_ylim(zs[0],zs[-1])
ax[1].axis('equal')
# graph 2 (2D)
YS, XS = np.meshgrid(ys,xs)
YS_C, XS_C = np.meshgrid(ys_c,xs_c)
ax[2].pcolormesh(XS, YS, self.bins[:,:,index[2]],
vmin=vmin, vmax=vmax,
cmap=plt.cm.coolwarm)
ax[0].contourf(X=XS_C, Y=YS_C, Z=self.bins[:,:,index[2]],
zdir='z', offset=pos[2],
vmin=vmin, vmax=vmax,
cmap=plt.cm.coolwarm, levels=levels,
alpha=0.5)
ax[2].set_xlabel(r"$x$")
ax[2].set_ylabel(r"$y$")
ax[2].set_xlim(xs[0],xs[-1])
ax[2].set_ylim(ys[0],ys[-1])
ax[2].axis('equal')
# graph 3 (2D)
ZS, YS = np.meshgrid(zs, ys)
ZS_C, YS_C = np.meshgrid(zs_c, ys_c)
ax[3].pcolormesh(YS, ZS, self.bins[index[0],:,:],
vmin=vmin, vmax=vmax,
cmap=plt.cm.coolwarm)
ax[0].contourf(X=self.bins[index[0],:,:], Y=YS_C, Z=ZS_C,
zdir='x', offset=pos[0],
vmin=vmin, vmax=vmax,
cmap=plt.cm.coolwarm, levels=levels,
alpha=0.5)
ax[3].set_xlabel(r"$y$")
ax[3].set_ylabel(r"$z$")
ax[3].set_xlim(ys[0],ys[-1])
ax[3].set_ylim(zs[0],zs[-1])
ax[3].axis('equal')
else:
# update to draw a given slice, use it to plot eaxh axes above!
ax.plot(self.XS,self.YS,self.ZS)
ax.set_zlabel(r"$z$")
ax.set_xlabel(r"$x$")
ax.set_ylabel(r"$y$")
ax.axis('equal')
else:
if fig is None:
fig, ax = plt.subplots(1)
xs = np.arange(self.limits[0][0],
self.limits[0][1] + self.limits[0][2],
self.limits[0][2])
ys = np.arange(self.limits[1][0],
self.limits[1][1] + self.limits[1][2],
self.limits[1][2],)
YS, XS = np.meshgrid(ys, xs)
graph = ax.pcolormesh(XS, YS, self.bins, cmap=plt.cm.coolwarm)
fig.colorbar(graph)
ax.set_xlim(self.limits[0][0], self.limits[0][1])
ax.set_ylim(self.limits[1][0], self.limits[1][1])
ax.set_title('Energy Distribution')
ax.set_xlabel(r"$x$")
ax.set_ylabel(r"$y$")
ax.axis('equal')
if show:
fig.tight_layout()
fig.show()
return fig, ax
If anything on the code is wrong or bugged please say so and I will edit the above (the school project was already graded, so you won't be doing my homework).
Also, if anything is less than clear please say so I add comments or explanations as needed.