Ive got test MRI data that I would like to make a 3D plot of. Right now I am visualising each slice individually though using the axes.imshow() function. Is there a 3d equivalent?
Taking the following example, is there anyway to get a black cube out of data in the following example, as opposed to just black square slices of it? That will solve my issue.
Example:
import numpy as np
import matplotlib.pyplot as plt
data = np.zeros((200,200,200))
slice_0 = data[0,:,:]
fig,axes = plt.subplots()
axes.imshow(slice_0.T, cmap="gray")
output
Related
this is more of a data visualisation issue. I got a 3 by 3 output from my calculations and I want to project the output on to a Seaborn chart for better visual effect. How do I do that? I have attached a random pic of how ideally I would like to see it below. Numbers inside the individual squares will be from my 3*3 array to be clear.
Hypothetical 3*3 array
opt = np.random.randint(1,10,9).reshape(3,3)
You might use seaborn.heatmap. Beyond providing data (2D array), set annot=True if you wish cells to be labeled, simple example:
import numpy as np
import seaborn as sns
data = np.arange(9).reshape(3,3)
ax = sns.heatmap(data, annot=True)
gives
I have the following simple code:
import numpy as np
import matplotlib.pyplot as plt
from scipy import linalg
for i in range(10):
M=np.array([[i**2,0],[0,i**3]]) # 2 x 2 matrix
eval,evec=np.linalg.eig(M)
# Plotting first and second eigenvalues
# Style 1
plt.plot(i,eval[0])
plt.plot(i,eval[1])
# Doesn't work
# Style 2
plt.plot(i,eval[0], '-r')
plt.plot(i,eval[1], '-b')
# Doesn't work
# Style 3
plt.plot(i,eval[0], 'ro-')
plt.plot(i,eval[1], 'bs')
# Does work
plt.xlabel('x')
plt.ylabel('y')
plt.savefig('plot.png')
plt.show()
While plotting with three different styles, only the third style (i.e. point or scatter plots) works successfully. Hence I have very limited customization options. Any way out?
Also, can these three differently styled plots be saved into three different files without creating separately three for-loops?
Output attached below.
Move the plotting outside the loop where computation occurs. In order to plot connected lines the plot function is expecting an array of values.
import numpy as np
import matplotlib.pyplot as plt
from scipy import linalg
yvals=[]
for i in range(10):
M=np.array([[i**2,0],[0,i**3]]) # 2 x 2 matrix
eval_,evec=np.linalg.eig(M)
yvals.append(eval_)
yvals=np.array(yvals)
xvals=np.array(range(10))
plt.plot(xvals,yvals[:,0],'-r')
plt.plot(xvals,yvals[:,1],'-b')
All of your plotting styles should work now.
If i want to color a square grid with different color in each grid cells, then it is possible in MATLAB with a simple call to imagesc command like here.
What if i want to color different cells in a grid like this:
Is this functionality available by default in either python or Matlab? I tried discretizing this grid with very small square cells. And then color each cell. That works. But it seems ordinary. Is there a smarter way to get his done?
In python, there is the builtin polar projection for the axes. This projection allows you to automatically use almost every plotting method in polar coordinates. In particular, you need to you pcolor or pcolormesh as follows
import numpy as np
from matplotlib import pyplot as plt
r = np.linspace(0,4,5)
theta = np.linspace(0,2*np.pi,10)
theta,r = np.meshgrid(theta,r)
values = np.random.rand(*(theta.shape))
ax = plt.subplot(111,polar=True)
ax.pcolor(theta,r,values)
plt.show()
Note that this will produce a plot like this
which is almost what you want. The obvious problem is that the patch vertices are joined by straight lines and not lines that follow the circle arc. You can solve this by making the angles array denser. Here is a posible way to do it.
import numpy as np
from matplotlib import pyplot as plt
r = np.linspace(0,4,5)
theta = np.linspace(0,2*np.pi,10)
values = np.random.rand(r.size,theta.size)
dense_theta = np.linspace(0,2*np.pi,100)
v_indeces = np.zeros_like(dense_theta,dtype=np.int)
i = -1
for j,dt in enumerate(dense_theta):
if dt>=theta[i+1]:
i+=1
v_indeces[j] = i
T,R = np.meshgrid(dense_theta,r)
dense_values = np.zeros_like(T)
for i,v in enumerate(values):
for j,ind in enumerate(v_indeces):
dense_values[i,j] = v[ind]
ax = plt.subplot(111,polar=True)
ax.pcolor(T,R,dense_values)
plt.show()
Which would produce
I am not aware of a way to do this in matlab but I googled around and found this that says it can produce pcolor plots in polar coordinates. You should check it out.
New to Python and just trying to accomplish what I think must be the simplest of tasks: plotting a basic 2D vector. However my online search has gotten me nowhere so I turn to stackoverflow with my very first question.
I Just want to plot a single 2D vector, let's call it my_vector. my_vector goes from (0,0) to (3,11).
What I have done is this:
from __future__ import print_function
import numpy as np
import pylab as pl
%pylab inline
x_cords = np.arange(4)
y_cords = np.linspace(0, 11, 4)
my_vector = vstack([x_cords, y_cords])
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(my_vector)
plt.show()
Which gives the following image (and totally not what I am after):
a very wrong plot
However I have found that
ax.plot(x_cords, y_cords)
instead of
ax.plot(my_vector)
gives me the plot I am looking for but then I don't have that single vector I am after.
So how does one correctly plot a basic 2D vector? Thank you and sorry if this has indeed been posted somewhere else...
You can also unpack your 2D vector
pl.plot(*my_vector)
Which is effectively just doing
pl.plot(x_cords, y_cords)
I know we can create simple 3-Dimensional spheres using matplotlib, an example of such a sphere is included in the documentation.
Now, we also have a warp method as part of the matplotlib module, an example of it's usage is here .
To warp a cylindrical image to the sphere. Is it possible to combine these methods to create a 3D rotatable earth? Unless my way of thinking about this problem is way off it seems that to be able to do this you would have to take the pixel data of the image and then plot every pixel using the sin and cosine expressions along the surface of the 3D sphere being created in the first example. Some examples of these cylindrical maps can be found here
I know alternative ways to do this are through maya and blender, but I am attempting to stay within matplotlib to do this, as I want to create this plot and then be able to plot geospatial data to the surface using an array of data.
Interesting question. I tried to basically follow the thinking outlined by #Skeletor, and map the image so that it can be shown with plot_surface:
import PIL
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
# load bluemarble with PIL
bm = PIL.Image.open('bluemarble.jpg')
# it's big, so I'll rescale it, convert to array, and divide by 256 to get RGB values that matplotlib accept
bm = np.array(bm.resize([d/5 for d in bm.size]))/256.
# coordinates of the image - don't know if this is entirely accurate, but probably close
lons = np.linspace(-180, 180, bm.shape[1]) * np.pi/180
lats = np.linspace(-90, 90, bm.shape[0])[::-1] * np.pi/180
# repeat code from one of the examples linked to in the question, except for specifying facecolors:
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = np.outer(np.cos(lons), np.cos(lats)).T
y = np.outer(np.sin(lons), np.cos(lats)).T
z = np.outer(np.ones(np.size(lons)), np.sin(lats)).T
ax.plot_surface(x, y, z, rstride=4, cstride=4, facecolors = bm)
plt.show()
Result:
Here what I made some hours ago:
First we import the needed libraries:
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import imageio
Secondly, we make the figures and stored them as png in our directory:
Note that I wrote range(0,330,20)
for i in range(0,330,20):
my_map = Basemap(projection='ortho', lat_0=0, lon_0=i, resolution='l', area_thresh=1000.0)
my_map.bluemarble()
my_map.etopo()
name=str(i)
path='/path/to/your/directory/'+name
plt.savefig(path+'.png')
plt.show()
plt.clf()
plt.cla()
plt.close()
And finally we can join all the images in an animated GIF:
images = []
for f in range(0,330,20):
images.append(imageio.imread("/path/to/your/directory/"+str(f)+".png"))
imageio.mimsave('movie.gif', images, duration=0.5)
and then enjoy the result:
I could imagine the following solution:
Using numpy.roll you could shift your array by one column (ore more) with each call. So you could load your image of the earth surface into a numpy array as a template and export the rotated image into a jpg. This you plot as shown in the warp example.