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.
Related
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/
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.
I am having trouble contouring some data in matplotlib. I am trying to plot a vertical cross-section of temperature that I sliced from a 3d field of temperature.
My temperature array (T) is of size 50*300 where 300 is the number of horizontal levels which are evenly spaced. However, 50 is the number of vertical levels that are: a) non-uniformly spaced; and b) have a different starting level for each vertical column. As in there are always 50 vertical levels, but sometimes they span from 100 - 15000 m, and sometimes from 300 - 20000 m (due to terrain differences).
I also have a 2d array of height (Z; same shape as T), a 1d array of horizontal location (LAT), and a 1d array of terrain height (TER).
I am trying to get a similar plot to one like here in which you can see the terrain blacked out and the data is contoured around it.
My first attempt to plot this was to create a meshgrid of horizontal distance and height, and then contourf temperature with those arguments as well. However numpy.meshgrid requires 1d inputs, and my height is a 2d variable. Doing something like this only begins contouring upwards from the first column:
ax1 = plt.gca()
z1, x1 = np.meshgrid(LAT, Z[:,0])
plt.contourf(z1, x1, T)
ax1.fill_between(z1[0,:], 0, TER, facecolor='black')
Which produces this. If I use Z[:,-1] in the meshgrid, it contours underground for columns to the left, which obviously I don't want. What I really would like is to use some 2d array for Z in the meshgrid but I'm not sure how to go about that.
I've also looked into the griddata function but that requires 1D inputs as well. Anyone have any ideas on how to approach this? Any help is appreciated!
For what I understand your data is structured. Then you can directly use the contourf or contour option in matplotlib. The code you present have the right idea but you should use
x1, z1 = np.meshgrid(LAT, Z[:,0])
plt.contourf(x1, Z, T)
for the contours. I have an example below
import numpy as np
import matplotlib.pyplot as plt
L, H = np.pi*np.mgrid[-1:1:100j, -1:1:100j]
T = np.cos(L)*np.cos(2*H)
H = np.cos(L) + H
plt.contourf(L, H, T, cmap="hot")
plt.show()
Look that the grid is generated with the original bounding box, but the plot is made with the height that has been transformed and not the initial one. Also, you can use tricontour for nonstructured data (or in general), but then you will need to generate the triangulation (that in your case is straightforward).
This must be possible but I am unsure as to how to approach it.
I have a geographical domain, with a set number of lat and lons. Using these, I am able to plot a simple Basemap of the domain:
fp_mhd = name.footprints('path/to/file')
domain_lon = fp_mhd.lon
domain_lat = fp_mhd.lat
### Construct Basemap ###
m = Basemap(resolution='c',projection='gall',
llcrnrlat=(np.min(domain_lat)),
urcrnrlat=(np.max(domain_lat)),
llcrnrlon=(np.min(domain_lon)),
urcrnrlon=(np.max(domain_lon)))
What I need is someway of distinguishing countries from oceans within this domain, and returning the results as an array i.e. 1s for land and 0s for ocean (though these values don't matter). The array needs to be 2-D where each point corresponds to a specific lat and lon. So say there were 100 lats and 200 lons, there would be 20000 1s and 0s. I wondered if there was some way to convert the Basemap object to an array, but failed to achieve this. Is it possible?
Thanks in advance!
Have a look at the following function. You should be able to extract the mask as it returns a numpy masked array.
.mask returns a Boolean array.
mpl_toolkits.basemap.maskoceans(lonsin, latsin, datain, inlands=True,
resolution='l', grid=5)
returns a masked array the same shape as datain with “wet” points
masked.
Basemap documentation
Numpy Masked Array Documentation
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