I have an exisiting vtk file (of a FE mesh, regular hexahedron mesh) and I would like to add a data set to this that I have in Python. Specifically, I would like to add this numpy data set to each node and then visualize it in ParaView.
Any tips on how I can get started on this?
VTK (and by extension ParaView) has great NumPy integration facilities. For a wonderful overview on these, please see the blog post series starting with Improved VTK – numpy integration].
The important parts are:
You need to wrap your VTK data object in an adapter class
You add your NumPy array to the wrapped data set
Sketching this out, you can write:
import vtk
from vtk.numpy_interface import dataset_adapter as dsa
dataSet = ...
numpyArray = ...
adaptedDataSet = dsa.WrapDataObject(dataSet)
dataSet.PointData.append(numpyArray, 'arrayname')
If your data were instead associated with cells rather than points, you would change that last line to
dataSet.CellData.append(numpyArray, 'arrayname')
You'll have to be sure that the order of the data in the NumPy array matches the order of points in the hexahedron mesh.
Now, how do you do this in ParaView? You can add a Programmable Filter. The Python environment in which the script set on the Programmable Filter is executed already does this wrapping for you, so you can simplify the script above to:
# Shallow copy the input data to the output
output.VTKObject.ShallowCopy(inputs[0].VTKObject)
# Define the numpy array
numpyArray = ...
# Add the numpy array as a point data set
output.PointData.append(numpyArray, 'arrayName')
In the script above, output is a wrapped copy of the dataset produced by the Programmable Filter, saving you from having to do the wrapping manually. You do need to shallow copy the input object to the output as the script shows.
Thanks for your assistance. Here is how I solved my problem:
import vtk
from vtk.numpy_interface import dataset_adapter as dsa
# Read in base vtk
fileName = "Original.vtk"
reader = vtk.vtkUnstructuredGridReader()
reader.SetFileName(fileName)
reader.Update()
mesh = reader.GetOutput()
# Add data set and write VTK file
meshNew = dsa.WrapDataObject(mesh)
meshNew.PointData.append(NewDataSet, "new data")
writer = vtk.vtkUnstructuredGridWriter()
writer.SetFileName("New.vtk")
writer.SetInputData(meshNew.VTKObject)
writer.Write()
Related
I'm moving my first steps into vtk and I'm quite struggling given the lack of documentation.
I've got a .vtk file which is a vtkDataSet type object I haven't created. I would need to export the content of it and convert it to a 3D numpy matrix, customise it and its tensor and write everything in a vtkDataSet object and .vtk file.
What I've ended up so far is save the coordinates, which is not what I need, of the points into a numpy array using vtk.util.numpy_support vtk_to_numpy. However, I'd need a 3D numpy matrix representing the volume rendering of it.
Speaking about the tensor, I figured out how and where to save my 9-elements tensor into the file. I'm just not sure on how to set it properly to be related to the points.
The last step, which is 3D numpy array to vtk, looks feasible using numpy.ravel and numpy_to_vtk from vtk.util.numpy_support.
Here's some code I'm using as a test:
# reader for mrtrix vtk file
reader = vtk.vtkDataSetReader()
file_name = 'my_file.vtk'
reader.SetFileName(file_name)
reader.Update()
# get the vtkDataArray
data_set = reader.GetOutput()
# these are the coordinates of the points
# I'd need the 3D numpy volume rendering matrix instead
point_array = data_set.GetPoints().GetData()
# test tensor
# I'd need to save a tensor for every element of the 3D numpy matrix
tensor = numpy_to_vtk(np.zeros([data_set.GetNumberOfPoints(), 9]))
tensor.SetName('Tensors_')
point_data = data_set.GetPointData()
point_data.SetAttribute(tensor, 4)
This may be useful in your case:
https://github.com/marcomusy/vedo/blob/master/vedo/examples/volumetric/numpy2volume1.py
and retrieve the numpy object with e.g.
print('numpy array from Volume:', vol.getPointArray().shape)
I need to extract the raster (stored as a numpy array) from a file. Following the very popular OGR Cookbook, I am reading in an OGR layer (geojson) and then rasterizing the vectors. I read that array using GDAL's ReadAsArray() function. That all works fine, and I can do all sorts of numpy things to it. However, GDAL automatically writes out the GDAL dataset I create because its automatically de-referenced once the program ends. I don't need/want this file to be output because its useless to have on disk, I just need the data in memory. How can you prevent this from happening?
I've tried not calling the FlushCache() function, but the file still gets output in the end.
Code:
...
# Create the destination data source
target = gdal.GetDriverByName('GTiff').Create(output_raster_path, source_raster.RasterXSize, source_raster.RasterYSize, 1, gdal.GDT_UInt16)
target.SetGeoTransform(source_raster.GetGeoTransform())
target.SetProjection(source_raster.GetProjection())
band = target.GetRasterBand(1)
band.SetNoDataValue(no_data_value)
gdal.RasterizeLayer(target, [1], source_layer, options=["ATTRIBUTE=BuildingID"])
raster = band.ReadAsArray()
return raster
Afterwards, once the program completes, a geotiff is written to output_raster_path, which I had just set as "temp.tif".
You can use In-Memory Driver for things like that.
mem_drv = gdal.GetDriverByName('MEM')
target = mem_drv.Create('', source_raster.RasterXSize, source_raster.RasterYSize, 1, gdal.GDT_UInt16)
I have a huge grid in *.pvd format. I would like to ensure some cells size specification have been respected when building said grid. To do so, I should get a cell data array with (dx,dy,dz)
I first tried to check this in Paraview with very little success. Then I resolved to export the mesh in various format (vtk, vtu, ex2) and import things into python using the vtk module, as in the code below. Unfortunately, the size of the mesh forbids it and I get various error messages stating "Unable to allocate n cells of size x".
import vtk
reader = vtk.vtkXMLUnstructuredGridReader()
reader.SetFileName("my_mesh.vtu")
reader.Update()
Finally, in Paraview there is a python-shell that allows me to open the grid file in either pvd or vtk format:
>>> from paraview.simple import *
>>> my_vtk = OpenDataFile("my_mesh.vtk")
>>> print dir(my_vtk)
Despite my browsing the methods and attribute of this reader object, I remain clueless about where to fetch any geometry information on the grid. I also browsed through the simple module documentation and I can't really wrap my head around it.
So how can one retrieve information regarding the geometry of cells from a paraview.servermanager.LegacyVTKReader object?
Any clue about how to achieve this with through the paraview GUI, or any kludge to load the vtk object into python vtk despite the memory issue is also very welcome. Sorry for such a hazy question, but I don't really know where to get started...
You can use GetClientSideObject() (see here) to get a VTK object in the Paraview Python shell. After that you can use all the regular VTK Python functions. For example, you can write the following in the Paraview Python shell
>>> from paraview.simple import *
>>> currentSelection = GetActiveSource()
>>> readerObj = currentSelection.GetClientSideObject()
>>> unstructgrid = readerObj.GetOutput()
>>> firstCell = unstructgrid.GetCell(0)
>>> cellPoints = firstCell.GetPoints()
Alternatively, you can use Programmable Filter in ParaView. This allows access to full VTK python module and even NumPy or other modules. You can enter following script in the script window of the programmable filter:
import vtk as v
import numpy as np
inp = self.GetUnstructuredGridInput()
cells = inp.GetCells()
cells.InitTraversal()
cellPtIds = v.vtkIdList()
lenArr = v.vtkDoubleArray()
lenArr.SetNumberOfComponents(3)
lenArr.SetName('CellSize')
while cells.GetNextCell( cellPtIds ):
pts = []
for i in range( cellPtIds.GetNumberOfIds() ):
ptCoords = inp.GetPoint( cellPtIds.GetId(i) )
pts.append( ptCoords )
pts = np.array( pts )
dx = np.max(pts[:,0]) - np.min(pts[:,0])
dy = np.max(pts[:,1]) - np.min(pts[:,1])
dz = np.max(pts[:,2]) - np.min(pts[:,2])
lenArr.InsertNextTuple3(dx, dy, dz)
out = self.GetUnstructuredGridOutput()
out.ShallowCopy( inp )
out.GetCellData().AddArray( lenArr )
In Paraview when you select the 'ProgrammableFilter1' icon in your pipeline, a new cell data array will be available to you from the drop-down as shown in the screenshot below. You can modify the script above to save the data to file to analyze externally.
This information is visible in the Information Tab.
So instead of storing every data we have in yet another format to make it displayable by ParaView, I wanted to use the python interface ParaView offers to directly load our data from our current file format and display it.
To test this out I wanted to create a simple ProgrammableSource filter that outputs a vtkImageData and fill it with some data.
I encountered three issues:
First, the data is not displayed (not even as an outline representation)
I could not find a way to set the values without looping
I did not find a good online source that could help me
Here is what I have so far. No complaints from ParaView, but also nothing is rendered.
import numpy as np
import vtk
import vtk.util.numpy_support as ns
img = self.GetImageDataOutput()
img.SetDimensions(3,4,5)
img.AllocateScalars(vtk.VTK_DOUBLE, 1)
dims = img.GetDimensions()
img.SetOrigin(0,0,0)
img.SetSpacing(0.55, 0.55, 0.55)
for z in range(dims[2]):
for y in range(dims[1]):
for x in range(dims[0]):
img.SetScalarComponentFromDouble(x,y,z,0, 1.0*x*y*z)
NOTE: If it is easier to use the python shell of ParaView directly instead of the ProgrammableSource, this would also be ok.
For defining vtkImageData output with the Programmable Source, one also has to take care of setting some information in the RequestInformation phase of the pipeline execution. Insert the following into the Script (RequestInformation) property:
from paraview import util
op = self.GetOutput()
util.SetOutputWholeExtent(self, [0, 2, 0, 3, 0, 4])
This information was adapted from information available at http://www.paraview.org/Wiki/Python_Programmable_Filter.
I have a vtk file that contains UNSTRUCTURED POINTS datasets. It has several datasets inside (fields, currents, densities).
I would like to load this file in python and convert every dataset to the numpy array to plot it with matplotlib. How to do this?
Without having an example of your file, it's hard to give a precise answer. But from what I know about vtk files, they can contain either ASCII or binary data after a 4 line header.
If the data in the vtk is ASCII, then
np.loadtxt(filename, skiplines=4)
should work. Again, the structure of your file could make this tricky if you have a bunch of different fields.
If the data is in binary, you will need to use something like
filename.read()
struct.unpack()
or
np.fromfile()
The solution is given by vtk_to_numpy function from the VTK package. It is used along a Vtk grid reader depending on the grid format (structured or unstructured): vtkXMLUnstructuredGridReader is a good choice in your case.
A sample code would look like:
from vtk import *
from vtk.util.numpy_support import vtk_to_numpy
# load a vtk file as input
reader = vtk.vtkXMLUnstructuredGridReader()
reader.SetFileName("my_input_data.vtk")
reader.Update()
#The "Temperature" field is the third scalar in my vtk file
temperature_vtk_array = reader.GetOutput().GetPointData().GetArray(3)
#Get the coordinates of the nodes and their temperatures
nodes_nummpy_array = vtk_to_numpy(nodes_vtk_array)
temperature_numpy_array = vtk_to_numpy(temperature_vtk_array)
x,y,z= nodes_nummpy_array[:,0] ,
nodes_nummpy_array[:,1] ,
nodes_nummpy_array[:,2]
(...continue with matplotlib)
A longer version with matplotib plotting can be found in this thread: VTK to Maplotlib using Numpy