Plot 3D mesh using 3D numpy array and 2D numpy array - python

I have a 3D numpy array Lattice[][][], and a 2D numpy array Trajectory[][].
I want the indices i/j/k of Lattice to be the coordinate axes and the value contained in the tensor element to be plotted as a colored dot, making a 3D mesh maybe
and I want to plot Trajectory where the Trajectory[p][0]/[1]/[2] contains the coordinates, and the index p is the iteration number - so this I want to plot as a 3D line, hopefully inside the mesh. I have no idea from where to start, is it possible in matplotlib?

You could definetly use matplotlib. Check this link: https://matplotlib.org/2.0.2/mpl_toolkits/mplot3d/tutorial.html
But you could also try a different package, like Plotly: https://plotly.com/python/3d-charts/

Related

Pyvista plotting 3D numpy array, always blank

I am trying to plot a 3D numpy array (256 x 256 x 256) as essentially an array of points, which should be colored by their value. I keep getting something like this
if I multiply by data by 1000, I get this:
My data is a 3D np array composed of slices, and the slices look like this:
There are about 50 or so slices, so the 3D visualization should be showing a sphere. I can visualize the slices just fine
My code is a modified example of this example: https://docs.pyvista.org/examples/02-plot/volume.html using the technique given here in this link to make a pyvista.UniformGrid object out of a 3D numpy array: https://docs.pyvista.org/examples/00-load/create-uniform-grid.html
def plot_3d_pyvista(self):
import pyvista as pv
values = self.reconstructed_source_3D
# Create the spatial reference
grid = pv.UniformGrid()
# Set the grid dimensions: shape because we want to inject our values on the
# POINT data
grid.dimensions = values.shape
# Edit the spatial reference
#grid.origin = (1, 1, 1) # The bottom left corner of the data set
#grid.spacing = (1, 1, 1) # These are the cell sizes along each axis
# Add the data values to the cell data
grid.point_data["values"] = values.flatten(order="F")
p = pv.Plotter()
p.add_volume(grid)
p.show()
If I use a sphere, eg, a 3D numpy array of zeros with only the center spherical elements set to 1, I get something like this which clearly shows a sphere but is way too transparent:
Alternatively, if anyone knows a way using a different package to plot a volume like this, I could use that. I just need a way to visualize what the 3D looks like.

Mapping values from NP ARRAY to STL

Recently i was struggling trying to take the pixel values of a 3D volume (np array) using specific space coordinate of a STL object.
The STL object is spatially overlapped with the 3D volume but the latter has no coordinate and so i don't know how to pick pixel values corresponding to the STL coordinates.
Any idea?
If the STL object is truly in the 3d volume's coordinate space, then you can simply STL's coordinate as an index to lookup the value from the 3d array. This lookup does nearest neighbor interpolation of the 3d image. For better looking results you'd want to do linear (or even cubic) interpolation of the nearby pixels.
In most 3d imaging tasks, those coordinate spaces do not align. So there is a transform to go from world space to 3d volume space. But if all you have is a 3d numpy array, then there is no transformation information.
Update:
To index into the 3d volume take the X, Y, Z coordinates of your point from the STL object and convert them into integer value I, J, K. Then lookup in the numpy array using I,J,K as indices: np_array[K][J][I]. I think you have to reverse the order of the indices because of the array ordering numpy uses.
When you way 3d array and the STL align in python, how are you showing that? The original DICOM or Nifti certainly have world coordinate transformations in the metadata.

plot 2d irregular array in 3d

I am attempting to plot 2d arrays on nonlinear surfaces in in a 3d plot. I have 2d arrays, where every column has an associated x, and y coordinate. Rows correspond to depth slices. I need to plot these 2d arrays in 3d space on a surface which has variable x and y coordinates. I have attempted using mayavi.imshow, but do not see a way to show the 2d array as an image on an irregular surface.
Example data:
x = np.linspace(100,120,50)
y = np.random.randint(50,60,x.shape)
z = np.arange(20)
data = np.random.rand(x.shape[0],y.shape[0])
# plot with mayavi
mlab.imshow(data)
mlab.show()
My goal is to be able to display this array in 3d space using the x,y,z values for each sample in my array. I am open to an plotting suggestions. originally attempted doing this in matplotlib, but was also unable to display my array on an irregular surface.

Fermi Surface Plots

Essentially I am trying to do a Fermi Surface plot, in 2D. i.e. a 2D cut of f(n,vec_k)=e_f for some plane in K-space, with interpolation. Specifically, I have a numpy array: Eigen, with shape,
Eigen.shape = (100,100,100,10), where the first three indices are over the vector vec_k, and the third is the band index 'n'. How to get a cut through an arbitrary surface Eigen == e_f, where e_f is a scalar number?
This is generally solved using a marching cube algorithm. You should look into contour3d() function of MLab here: http://docs.enthought.com/mayavi/mayavi/auto/mlab_helper_functions.html#mayavi.mlab.contour3d. THis does exactly what you want.
contour3d(Eigen[:,:,:, bandNo], contours=e_f)
should do it for you. You can also specify a number of surfaces for all bands like so:
for bandNo in range(totalBands):
contour3d(Eigen[:,:,:, bandNo], contours=[eF1, eF2, eF3], opacity=0.4)
You should get plots like these: http://docs.enthought.com/mayavi/mayavi/_images/enthought_mayavi_mlab_contour3d1.jpg

Create 2D projection of 3D matrix in python

Short version: I have a NxNxN matrix full of different values. I want to create a 2D projection of it looking exactly like this: http://tinyurl.com/bellfkn (3D if possible too!)
Long version: I have made a density matrix of dimension NxNxN with the following loop:
ndim = 512
massmat = np.zeros((ndim,ndim,ndim))
for i in range(0,npoints):
massmat[int(x1[i]),int(y1[i]),int(z1[i])] = massmat[int(x1[i]),int(y1[i]),int(z1[i])] + mpart
densemat = massmat/volumeofcell
massmat is a numpy array.
So basically I now have a NxNxN matrix with certain cells containing in this case, a density (units of g/cm^3). Is there a way to turn this into a 2D projection - a side-on view of the densities with a colorbar indicating dense areas and less dense areas?
In Matlab I would just do:
imageArray2Dmesh = mean(densemat, 3);
figure
sc(imageArray2Dmesh, 'pink')
And it gives me a density projection - I'd like to do the same but in Python. Is there a way to view the whole NxNxN matrix in a 3D projection too? Just like the link but in 3D. That would be great.
You can use a very similar code in numpy and matplotlib:
import numpy as np
import pylab as plt
imageArray2Dmesh = np.mean(mesh_reshape, axis=2);
plt.figure()
plt.pcolor(imageArray2Dmesh, cmap = ,cmap=plt.cm.pink)
plt.colorbar()
plt.show()
you have a couple of more command, but this is just due to different approaches for the grafics in matlab and matplotlib (hint: in the long run, the matplotlib way is way better)
If you want the project from another direction just change the axis parameter (remember that python has the indices from 0 and not from 1 like matlab).
For a projection from a generic direction...well, that is quite more difficult.
By the way, if you need to look at some 3D data I strongly suggest you to lose some time to explore mayavi. It's still a python library, and it's really powerful for 3d imaging:
http://docs.enthought.com/mayavi/mayavi/auto/examples.html

Categories

Resources