New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Transform slice() output to 2D numpy array #89
Comments
Check out the first post in this thread: #70 as long as the normal is oriented with the cartesian axial directions then it is a breeze. Otherwise, you'd have to rotate the slice |
Also, if you want a 2D array, the mesh that you are slicing must be rectilinear (ie. a |
Thanks for the comments! I do have the |
What exactly is your goal with the 2D array? Because as soon as you tilt the slice, it will have non-rectangular geometries that can’t be well translated to a 2d grid (array). Maybe some insight will help me find a better solution for you? Sent with GitHawk |
We have a 3D volume image data and then we would like to get some 2D slicing plane images out of it for some image analysis tasks. Something like this. |
@bcjiang, #101 (comment) has a routine for resampling planar data to a rectilinear grid which will give you a 2D array. Thing is, you have to project the arbitrarily oriented plane to an axial plane. A workaround would be to create a structured grid around your slice like so. no matter what though, you have to resample the slice because of the irregular geometries. and during that resampling, you have to make a choice about resolution. import pyvista as pv
from pyvista import examples
import numpy as np
import matplotlib.pyplot as plt
normal = np.array([1, 1, 0.5])
slc = examples.load_uniform().slice(normal=(1,1,0.5))
slc.plot(show_grid=True, show_edges=True) # Make structured grid
x = np.linspace(0, 20)
y = np.linspace(0, 20)
z = np.array([0])
plane = pv.StructuredGrid(*np.meshgrid(x,y,z))
# rotate and translate grid to be ontop of the slice
vx = np.array([0., 0., 1.])
direction = normal / np.linalg.norm(normal)
vx -= vx.dot(direction) * direction
vx /= np.linalg.norm(vx)
vy = np.cross(direction, vx)
rmtx = np.array([vx, vy, direction])
plane.points = plane.points.dot(rmtx)
plane.points -= plane.center
plane.points += slc.center
# resample the data
sampled = plane.sample(slc, )
# Fill bad data
sampled["Spatial Cell Data"][~sampled["vtkValidPointMask"].astype(bool)] = np.nan
# plot the 2D array
array = sampled["Spatial Cell Data"].reshape(sampled.dimensions[0:2])
plt.pcolormesh(array) |
Thanks! I just saw the comment, I will try that. |
@bcjiang, I had to do this today to make some figures of slices using MPL and made a better version of this into a helper function: def slice_to_array(slc, normal, origin, name, ni=50, nj=50):
"""Converts a PolyData slice to a 2D NumPy array.
It is crucial to have the true normal and origin of
the slicing plane
Parameters
----------
slc : PolyData
The slice to convert.
normal : tuple(float)
the normal of the original slice
origin : tuple(float)
the origin of the original slice
name : str
The scalar array to fetch from the slice
ni : int
The resolution of the array in the i-direction
nj : int
The resolution of the array in the j-direction
"""
# Make structured grid
x = np.linspace(slc.bounds[0], slc.bounds[1], ni)
y = np.linspace(slc.bounds[2], slc.bounds[3], nj)
z = np.array([0])
plane = pv.StructuredGrid(*np.meshgrid(x,y,z))
# rotate and translate grid to be ontop of the slice
vx = np.array([0., 0., 1.])
direction = normal / np.linalg.norm(normal)
vx -= vx.dot(direction) * direction
vx /= np.linalg.norm(vx)
vy = np.cross(direction, vx)
rmtx = np.array([vx, vy, direction])
plane.points = plane.points.dot(rmtx)
plane.points -= plane.center
plane.points += origin
# resample the data
sampled = plane.sample(slc, tolerance=slc.length*0.5)
# Fill bad data
sampled[name][~sampled["vtkValidPointMask"].view(bool)] = np.nan
# plot the 2D array
array = sampled[name].reshape(sampled.dimensions[0:2])
return array |
This is pretty helpful! Thanks a lot for the update. |
Hello, Using several slices and performing the 2D np transform would be an sub optimal option due to multiple sampling. Thanks for any advice. |
@BobHeidsieck, please open a new issue. |
I was trying to obtain a cross-section image from a 3D volume using the slice() method with normal vector input, but the output of slice() method is an object of <class 'pyvista.core.pointset.PolyData'>. I'm wondering if there is way to efficiently transform the output to a 2D numpy array data?
The text was updated successfully, but these errors were encountered: