VTK : how to read grid cells' lenth, width and height? - python

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.

Related

SaveData in Paraview python is not saving the file

I used one stl file to split the stl using Paraview. I traced the method using python trace in paraview.
Now, I used the code in python to run it. It runs perfectly, but it does not save the splitted mesh as needed. The code is used as per the trace obtained from paraview. Below is the snipped of the code where SaveData is used to save the file. How to save stl file?
import sys #sys- append path
import numpy as np
ParaViewBuildPath = "/home/ParaView-5.7.0/"
sys.path.append(ParaViewBuildPath + "lib/")
sys.path.append(ParaViewBuildPath + "lib/python3.7/site-packages")
sys.path.append(ParaViewBuildPath + "lib/python3.7/site-packages/vtkmodules")
from paraview.simple import *
import vtk
# find source
mesh176_rightstl = FindSource('mesh176_right.stl')
generateSurfaceNormals1 = GenerateSurfaceNormals(Input=mesh176_rightstl)
# Properties modified on generateSurfaceNormals1
generateSurfaceNormals1.FeatureAngle = 15.0
# create a new 'Connectivity'
connectivity1 = Connectivity(Input=generateSurfaceNormals1)
# create a new 'Threshold'
threshold1 = Threshold(Input=connectivity1)
#threshold1.Scalars = ['POINTS', 'RegionId']
# Properties modified on threshold1
threshold1.ThresholdRange = [10.0, 982.0]
# create a new 'Extract Surface'
extractSurface1 = ExtractSurface(Input=threshold1)
# save data
SaveData('surf176.stl', proxy=extractSurface1, FileType='Ascii')
I have addressed the error I am facing from the line "generateSurfaceNormals1".
[paraview ]vtkDemandDrivenPipeline:713 ERR| vtkPVCompositeDataPipeline (0x556f782fe7c0): Input port 0 of algorithm vtkPPolyDataNormals(0x556f7a16b2a0) has 0 connections but is not optional.
How to overcome this error?
Any leads will be appreciated.
Regards,
Sunag R A.
The error message means that mesh176_rightstl is None, so the FindSource does not find anything. Is the source name correct ? Is the data correctly loaded ?
As an error raised, the script stops and SaveData is not called. But its syntax is correct.
Minimal code to test stl writer:
s = Sphere()
SaveData('sphere.stl', proxy = s, FileType='Ascii')
It correctly produces the stl file with ParaView 5.9
edit
You should uncomment the line
#threshold1.Scalars = ['POINTS', 'RegionId']
Because pipeline is not executed until you ask for (e.g. with the SaveData), no default array can be found when you created the Threshold.

Python: Read vtk file, add data set then write vtk

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()

How to write a ProgrammableSource filter to display a numpy array as a vtkImageData in ParaView?

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.

How can I write a velocity field to a VTI image with anaconda Python?

I am trying to write a VTK Image Data file (.vti) with python. For my python coding I am using the Anaconda distribution. I am using the evtk package, which has the ability to write a vtk file.
The data I need to write is a velocity for which I have the 3d X,Y,Z and U,V,W 3d arrays. I have found some sample code which uses the evtk package to write a .vti file.(http://www.vtk.org/Wiki/VTK/Writing_VTK_files_using_python)
The problem is that the sample code and built in functions only take scalar point or cell data. So I am able to write a file with scalars, but I need it to have the data as vectors.
I am digging through the actual package files and trying to find a solution or tools to code one.I would extremely appreciate if somebody had suggestions or solutions to give me a hand.
I enclose the test code I have written from info on the wiki just in case I am missing a way of inputing to the function, but I fear I am going to need to start from scratch.
Thanks in advance
(removed the code since the one bellow is more recent)
Managed to write an unstructured file (.vtu), but I would really like to be a able to write an Image Data file.(Found the following link helpful during the process. http://www.aero.iitb.ac.in/~prabhu/tmp/python_cep07/course_handouts/viz3d_handout.pdf)
Thanks again in advance
I attach the code to see if anybody has any suggestions.
from tvtk.api import tvtk, write_data
import numpy as N
##Generation of data
#array of x,y,z coordinates
[Z,Y,X] = N.mgrid[-2.:2+1, -2.:2+1, -2.:2+1]
#array of zeros to add the u,v,w components
[W,V,U] = N.zeros_like([Z,Y,X],dtype=float)
#loop through data to have correct format
points = N.array([N.zeros(3) for i in range(len(Z)*len(Z[0])*len(Z[0][0]))])
velF = N.zeros_like(points)
c=0
for k in range(len(Z)):
for j in range(len(Z[0])):
for i in range(len(Z[0][0])):
#coordinates of point
x = X[k][j][i]
y = Y[k][j][i]
z = Z[k][j][i]
points[c] = N.array([x,y,z])
#test velocity field
u = k -2.
v = 0.
w = 0.
velF[c] = N.array([u,v,w])
#update counter
c = c+1
##Generate and write the vtk file
Ugrid = tvtk.UnstructuredGrid()
Ugrid.points = points
Ugrid.point_data.vectors = velF
Ugrid.point_data.vectors.name = 'velocity'
write_data(Ugrid, 'vtktest.vtu')
If you want to write the unstructured grids using evtk, here you can find a full demo with point and cell data (both vector and scalar fields): https://gist.github.com/dromanov/0fb8bacff5342a56a690.
Description of the technique and explanations are here: http://spikard.blogspot.ru/2015/07/visualization-of-unstructured-grid-data.html.
Good luck!

How to write manipulated raster values to ASCII grid with GDAL?

I am trying to manipulate raster values in a grid (ASCII Grid) with GDAL. But before proceeding with this, I have trouble writing the new values into the file. I get these error messages when slopeband.WriteArray(s) is called.
ERROR 6: slope.asc, band 1: WriteBlock() not supported for this dataset.
ERROR 1: slope.asc, band 1: An error occured while writing a dirty block
I'm sorry if this is very basic, but I'm still new to python and GDAL in particular. I use GDAL 1.9.0 on Mac OS X 10.6.8 and Python 2.7. Thank you!
import numpy
import gdal
import gdalconst
dgm = gdal.Open("DGM_10_MR.asc", gdalconst.GA_ReadOnly)
driver = dgm.GetDriver()
geotransform = dgm.GetGeoTransform()
band = dgm.GetRasterBand(1)
data = band.ReadAsArray()
cols = dgm.RasterXSize
rows = dgm.RasterYSize
slope = driver.CreateCopy("slope.asc", dgm)
slope = None
dgm = None
slope = gdal.Open("slope.asc", gdalconst.GA_Update)
slope.SetGeoTransform(geotransform)
slopeband = slope.GetRasterBand(1)
s = slopeband.ReadAsArray()
for y in range(rows):
for x in range(cols):
s[y, x] = 0.0
slopeband.WriteArray(s)
slopeband.FlushCache()
del s
dgm = None
slope = None
print "done"
Unfortunately, GDAL cannot read and write to the same degrees across all filetypes. Arc ASCII grid happens to be one of those filetypes that GDAL cannot write to. As your error message says: WriteBlock() not supported for this dataset., so you can't write to Arc ASCII grids.
As alternative, you could convert your existing ASCII dataset to a different filetype, one that GDAL more fully spports such as GeoTiff. To convert filetypes, you could use the gdal_translate command-line program like so:
gdal_translate -of GTiff DGM_10_R.asc DGM_10_R.tif
I was able to reproduce your errors on my computer, and simply changing the filetype fixes the errors.

Categories

Resources