Python3.0 Mayavi rotating cube glyph - mayavi

Using mayavi points3d and using cube to plot the image. Is there a way to rotate a cube to certain orientation during the plot?
mlab.figure(2)
mlab.points3d(GrainsFile[:,6],GrainsFile[:,7],GrainsFile[:,8],GrainsFile[:,11])

I had to search the Mayavi code for this one. Once I found that those cube are a GlyphSource, I found some transformation operation in one of its methods:
import numpy
from mayavi import mlab
def test_points3d():
t = numpy.linspace(0, 4 * numpy.pi, 20)
x = numpy.sin(2 * t)
y = numpy.cos(t)
z = numpy.cos(2 * t)
s = 2 + numpy.sin(t)
points = mlab.points3d(x, y, z, s, colormap="viridis", scale_factor=.25,
mode='cube')
# rotate 45° on Z
points.glyph.glyph_source._trfm.transform.rotate_z(45)
test_points3d()

Related

matplotib 3D figure showing surface plus contours with parts hidden correctly?

I would like to draw a surface and some of its iso-z contours, using the plot_surface and contour3D functions of mplot3D. Here is an example (I would like to use it to illustrate Lagrange points in physics) :
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
epsilon, r1 = 0.3, 1
r2 = epsilon*r1
Omega2 = 1/(r1*pow(r1+r2, 2))
u = np.linspace(-2, 2, 100)
x , y = np.meshgrid(u, u)
z = -epsilon/np.sqrt(np.power(x-r1, 2)+ np.power(y, 2)) - 1/np.sqrt(np.power(x+r2, 2)+ np.power(y, 2)) - 0.5*Omega2*(np.power(x, 2) + np.power(y, 2))
z = np.clip(z, -3, 0)
ax.plot_surface(x, y, z, rstride=1, cstride=1, antialiased=True, color="whitesmoke")
ax.contour3D(x, y, z+0.01, levels=np.arange(-2, -1, 0.1))
plt.show()
In the resulting plot, the contours do not show properly :
Image obtained by the code
and as the figure is interactively rotated, they randomly appear and disappear, with a wrong estimation of what part should be hidden by the surface :
Example of figure obtained by interactive rotation
This had been noticed before 4 years ago but no solution had been suggested. Hence my questions :
is it still, 4 years after, considered as a limitation of the plotting capabilities of matplolib ? And is there an alternative way, using some other graphical library ?

Discrete Color Bar with Tick labels in between colors

I am trying to plot some data with a discrete color bar. I was following the example given (https://gist.github.com/jakevdp/91077b0cae40f8f8244a) but the issue is this example does not work 1-1 with different spacing. For example, the spacing in the example in the link is for only increasing by 1 but my data is increasing by 0.5. You can see the output from the code I have.. Any help with this would be appreciated. I know I am missing something key here but cant figure it out.
import matplotlib.pylab as plt
import numpy as np
def discrete_cmap(N, base_cmap=None):
"""Create an N-bin discrete colormap from the specified input map"""
# Note that if base_cmap is a string or None, you can simply do
# return plt.cm.get_cmap(base_cmap, N)
# The following works for string, None, or a colormap instance:
base = plt.cm.get_cmap(base_cmap)
color_list = base(np.linspace(0, 1, N))
cmap_name = base.name + str(N)
return base.from_list(cmap_name, color_list, N)
num=11
x = np.random.randn(40)
y = np.random.randn(40)
c = np.random.randint(num, size=40)
plt.figure(figsize=(10,7.5))
plt.scatter(x, y, c=c, s=50, cmap=discrete_cmap(num, 'jet'))
plt.colorbar(ticks=np.arange(0,5.5,0.5))
plt.clim(-0.5, num - 0.5)
plt.show()
Not sure what version of matplotlib/pyplot introduced this, but plt.get_cmap now supports an int argument specifying the number of colors you want to get, for discrete colormaps.
This automatically results in the colorbar being discrete.
By the way, pandas has an even better handling of the colorbar.
import numpy as np
from matplotlib import pyplot as plt
plt.style.use('ggplot')
# remove if not using Jupyter/IPython
%matplotlib inline
# choose number of clusters and number of points in each cluster
n_clusters = 5
n_samples = 20
# there are fancier ways to do this
clusters = np.array([k for k in range(n_clusters) for i in range(n_samples)])
# generate the coordinates of the center
# of each cluster by shuffling a range of values
clusters_x = np.arange(n_clusters)
clusters_y = np.arange(n_clusters)
np.random.shuffle(clusters_x)
np.random.shuffle(clusters_y)
# get dicts like cluster -> center coordinate
x_dict = dict(enumerate(clusters_x))
y_dict = dict(enumerate(clusters_y))
# get coordinates of cluster center for each point
x = np.array(list(x_dict[k] for k in clusters)).astype(float)
y = np.array(list(y_dict[k] for k in clusters)).astype(float)
# add noise
x += np.random.normal(scale=0.5, size=n_clusters*n_samples)
y += np.random.normal(scale=0.5, size=n_clusters*n_samples)
### Finally, plot
fig, ax = plt.subplots(figsize=(12,8))
# get discrete colormap
cmap = plt.get_cmap('viridis', n_clusters)
# scatter points
scatter = ax.scatter(x, y, c=clusters, cmap=cmap)
# scatter cluster centers
ax.scatter(clusters_x, clusters_y, c='red')
# add colorbar
cbar = plt.colorbar(scatter)
# set ticks locations (not very elegant, but it works):
# - shift by 0.5
# - scale so that the last value is at the center of the last color
tick_locs = (np.arange(n_clusters) + 0.5)*(n_clusters-1)/n_clusters
cbar.set_ticks(tick_locs)
# set tick labels (as before)
cbar.set_ticklabels(np.arange(n_clusters))
Ok so this is the hack I found for my own question. I am sure there is a better way to do this but this works for what I am doing. Feel free to suggest a better way to do this.
import numpy as np
import matplotlib.pylab as plt
def discrete_cmap(N, base_cmap=None):
"""Create an N-bin discrete colormap from the specified input map"""
# Note that if base_cmap is a string or None, you can simply do
# return plt.cm.get_cmap(base_cmap, N)
# The following works for string, None, or a colormap instance:
base = plt.cm.get_cmap(base_cmap)
color_list = base(np.linspace(0, 1, N))
cmap_name = base.name + str(N)
return base.from_list(cmap_name, color_list, N)
num=11
plt.figure(figsize=(10,7.5))
x = np.random.randn(40)
y = np.random.randn(40)
c = np.random.randint(num, size=40)
plt.scatter(x, y, c=c, s=50, cmap=discrete_cmap(num, 'jet'))
cbar=plt.colorbar(ticks=range(num))
plt.clim(-0.5, num - 0.5)
cbar.ax.set_yticklabels(np.arange(0.0,5.5,0.5))
plt.show()
For some reason I cannot upload the image associated with the code above. I get an error when uploading so not sure how to show the final example. But simply I set the color bar axes for tick labels for a vertical color bar and passed in the labels I want and it produced the correct output.

Picking a new color for each contour component in matplotlib

Sometimes a specific contour level has several components. For instance:
import numpy as np
import matplotlib.pyplot as plt
delta = 1./100
x = np.arange(-2.0, 3.0, delta)
y = np.arange(-3.0, 3.0, delta)
X, Y = np.meshgrid(x, y)
Z = Y * Y - X * X * X + X
plt.figure()
CS = plt.contour(X, Y, Z, [0])
How do I color each component using its own color?
I found a way to do it! :) But it's hacky, so I'll leave my answer un-accepted until someone comes up with a better way to do it. Here is my solution (matplotlib 1.4.3).
As noted in the comments, what I asked is not something that matplotlib.contour knows how to do. But after investigating the code a little bit I came up with a solution that works and isn't too bad.
Behind the scenes, a class called QuadContourSet is used to store all the contour paths in "line collections", one line collection per level. The line collections are styled all together.
My idea was to subclass this class and replace the function _get_allsegs_and_allkinds with a function that separates the line collections to one line collection per component, instead of per-level. This is hacky so I named it HackyContourSet but it's good enough for my purposes.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import contour
class HackyContourSet(contour.QuadContourSet):
def _get_allsegs_and_allkinds(self):
allkinds = None
allsegs = []
for level in self.levels:
nlist = self.Cntr.trace(level)
nseg = len(nlist) // 2
segs = nlist[:nseg]
# Original code: allsegs.append(segs) - put all level segments in a
# collection. New code: Put each segment in a separate collection.
for seg in segs:
allsegs.append([seg])
# The following line is needed to make QuadContourSet think there are
# more levels, so it would actually draw the additional collections.
self.levels = [0] * len(allsegs)
return allsegs, allkinds
####################
delta = 1./100
x = np.arange(-2.0, 3.0, delta)
y = np.arange(-3.0, 3.0, delta)
X, Y = np.meshgrid(x, y)
Z = Y * Y - X * X * X + X
plt.figure()
plt.cla()
axes = plt.gca()
CS = HackyContourSet(axes, X, Y, Z, [0], colors=list('rb'))

matplotlib tripcolor: mesh grid is showing up when i'm changing the alpha parameter

I'm trying to change the opacity of a tripcolor garph. Setting the alpha parameter is changing the opacity but is also showing up the mesh grid. I think that this is happening because the alpha parameter is not changing the opacity of the edges too. I tried to set edgecolor='none' but this is not solving my problem. Is there a way of changing the opacity without displaying the mesh grid?
"""
Pseudocolor plots of unstructured triangular grids.
"""
import matplotlib.pyplot as plt
import matplotlib.tri as tri
import numpy as np
import math
# Creating a Triangulation without specifying the triangles results in the
# Delaunay triangulation of the points.
# First create the x and y coordinates of the points.
n_angles = 36
n_radii = 8
min_radius = 0.25
radii = np.linspace(min_radius, 0.95, n_radii)
angles = np.linspace(0, 2*math.pi, n_angles, endpoint=False)
angles = np.repeat(angles[...,np.newaxis], n_radii, axis=1)
angles[:,1::2] += math.pi/n_angles
x = (radii*np.cos(angles)).flatten()
y = (radii*np.sin(angles)).flatten()
z = (np.cos(radii)*np.cos(angles*3.0)).flatten()
# Create the Triangulation; no triangles so Delaunay triangulation created.
triang = tri.Triangulation(x, y)
# Mask off unwanted triangles.
xmid = x[triang.triangles].mean(axis=1)
ymid = y[triang.triangles].mean(axis=1)
mask = np.where(xmid*xmid + ymid*ymid < min_radius*min_radius, 1, 0)
triang.set_mask(mask)
# Illustrate Gouraud shading.
plt.figure()
plt.gca().set_aspect('equal')
plt.tripcolor(triang, z, shading='gouraud', cmap=plt.cm.rainbow, alpha=0.5, edgecolor='none')
plt.colorbar()
plt.title('tripcolor of Delaunay triangulation, gouraud shading')
plt.show()
Thank you very much for your time,
Dorin
you can try it with: " edgecolors='k', linewidth=0.0 " so this can set the linewidth to zero, which makes the line disapp

Plotting date data with pcolor

I have data like this:
dates = ['1874-05-02', '1874-05-03', '1874-05-04',
'1874-05-05', '1874-05-06','1874-05-07']
data1 = ['-7.000', '7.000', '2.000', '11.600', '13.500', '-13.500']
data2 = ['0.000', '25.000', '0.000', '75.000', '12.000', '22.000']
and I need to draw a diagram where dates are on x-axis and data1 on y-axis. Data2 is needed to draw dots in diagram and they should all be in differend colours corresponding their values. So how can I do this with pcolor or pcolormesh?
Here is an example-code I found from http://matplotlib.org/examples/pylab_examples/pcolor_demo.html and I was wondering could I get anything like this out with my data? Here is another link to demonstrate what I'm supposed to do: https://dl.dropboxusercontent.com/u/47527320/diagram.jpg. Can I get a diagram like this with pcolor?
import matplotlib.pyplot as plt
import numpy as np
dx, dy = 0.15, 0.05
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)
z = z[:-1, :-1]
z_min, z_max = -np.abs(z).max(), np.abs(z).max()
plt.subplot(2, 2, 1)
plt.pcolor(x, y, z, cmap='RdBu', vmin=z_min, vmax=z_max)
plt.title('pcolor')
plt.axis([x.min(), x.max(), y.min(), y.max()])
plt.colorbar()
plt.show()
A scatter plot will give what you describe.
import numpy as np
import pylab as plt
import datetime
dt = datetime.datetime
dates = [dt(1874,05,02), dt(1874,05,03), dt(1874,05,04), dt(1874,05,05), dt(1874,05,06),dt(1874,05,07)]
data1 = [-7.000, 7.000, 2.000, 11.600, 13.500, -13.500]
data2 = [0.000, 25.000, 0.000, 75.000, 12.000, 22.000]
plt.scatter(dates, data1, c=data2, s=400)
plt.show()
There was some discussion in the comments about needing 2D data, but I think that was due to lack of clarity of what you were looking for. The types of plots in your mpl example link and your sketch are completely different in nature. Take a look through the mpl gallery page and you'll see that the ones like your sketch (and that also match the structure of your data well) are using a scatter plot.
There are lots of options here for how to handle the dates and colors, but this should get you started.