save and write a .vtk polydata file - python

I used this puyhon code to convert nifti file to .vtk polydata meshes
import itk
import vtk
input_filename = '/home/nour/Bureau/7ans/244/whatIneed/244seg_pve_2.nii.gz'
reader=itk.ImageFileReader[itk.Image[itk.UC,3]].New()
reader.SetFileName(input_filename)
reader.Update()
itkToVtkFilter = itk.ImageToVTKImageFilter[itk.Image[itk.UC,3]].New()
itkToVtkFilter.SetInput(reader.GetOutput())
myvtkImageData = itkToVtkFilter.GetOutput()
print("myvtkImageData")
and for saving and writing the .vtk file I used
writer = vtk.vtkPolyDataWriter()
writer.SetInputData()
writer.SetFileName("/home/nour/Bureau/7ans/244/whatIneed/Output.vtk")
writer.Write()
and here the error :
ERROR: In /work/standalone-x64-build/VTK-source/Common/ExecutionModel/vtkDemandDrivenPipeline.cxx, line 809
vtkCompositeDataPipeline (0x4d9cac0): Input for connection index 0 on input port index 0 for algorithm vtkPolyDataWriter(0x4de3ea0) is of type vtkImageData, but a vtkPolyData is required.
I was wondering as to what would be a good way of writing a vtk Polydata file.
thanks

You need to transform your image (regular grid) into a polygonal mesh to be able to save it as a .vtk file.
For 2D meshes, this can be done using the vtkExtractSurface filter.
Another solution would be to use another format (.vtk is a legacy format):
If you want to save a regular grid, you can use the vtkXMLImageDataWriter, that uses the .vti extension.
If you want a unstructured mesh, you can use the vtkXMLPolyDataWriter, that uses the .vtp extension and gives a polygonal mesh. You can also use the vtkXMLUnstructuredGridWriter, that uses the .vtu extension and can contain 3D cells.

Images and polygonal meshes are fundamentally different types of data. You can't just cast an image into a mesh.
To get a mesh you would need to do some type of iso-surface extraction. Typically you would select some image intensity as the value of your surface, and then you would use an algorithm such as Marching Cubes to create a mesh of that value.
In VTK you can use the vtkContourFilter to create a mesh from an image. There are a number of examples on the VTK Example web site that show how to use the filter. Here is one:
https://lorensen.github.io/VTKExamples/site/Python/ImplicitFunctions/Sphere/

thank you very much. So as I understand :
1 reading nifti file (segmented file)
2 apply itktovtkfilter
3 creating meshes (using the vtkContourFilter)
4 and finaly convert it to polydata and save it to .vtk file
that's right ??

Related

Converting VTK image (.vti) data to VTK poly (.vtp) data

I'm trying to take some VTK image data generated from a 3-D numpy array and convert it into poly data so it can be read by a package that only takes .vtp as an input format. I chose to use the marching cubes algorithm to take my point/node data as input and give poly data as an output. The data is segmented into two phases (0 = black, 255 = white), so only one contour is necessary. I tried using the vtkPolyDataReader class to create an object for the vtkMarchingCubes class, then using vtkPolyDataWriter to take the contoured marching cubes object and save it as a VTP file:
import vtk
input = 'mydata.vti'
reader = vtk.vtkPolydataReader()
reader.SetFileName(input)
reader.Update()
contour = vtk.vtkMarchingCubes()
contour.SetInputConnection(reader.GetOutputPort())
contour.SetValue(0, 128.)
contour.Update()
writer = vtk.vtkPolyDataWriter()
writer.SetInputData(contour.GetOutput())
writer.SetFileName('mydata.vtp')
writer.Update()
writer.Write()
When I run the code, it takes much less time than it ought to (the input file is about 2 GB), and the VTP file the code creates is less than 1 KB. I've been banging my head against a wall over this and poring over the VTK documentation and some provided examples, but I can't figure out what I've done wrong.
To read a .vtki file you need to use vtk.vtkXMLImageDataReader. You are trying to read an image file with a vtk.vtkPolyDataReader, which is designed for reading surface meshes.

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

Extending dimensions of netCDF file using NCO

Is there a NCO or netCDF4 command that can be used to extend the lat-lon dimensions of netCDF file.
E.g. I have a netCDF file with foll. dimensons:
dimensions(sizes): time(10), var(1), latitude(1674), longitude(4320)
I want to extend the latitude dimension to cover the entire globe i.e. instead of 1674 it should be 2160. Is there a way to do that? The new cells should be assigned a user-specified value say 0.0
You could generate a new grid of the size you want and then remap your original data to that grid with ncremap. It's a fairly sophisticated feature but then so is what you want to do :). Or you could open your file in ncap2, define new dimensions of the sizes above, and then use hyperslab subscripting to copy your original data into a corner of your new array, then use ncks to extract only the new fields/dimensions from that file.

Reading ascii vtk file in python and converting it to numpy array

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

Where to begin? Using x,y,z data to display a building lot

I used a builders' level to get x,y,z coordinates on a 110' x 150' building lot.
They are not in equally spaced rows and columns, but are randomly placed.
I have found a lot of info on mapping and I'm looking forward to learning about GIS. And how to use the many free software utilities out there.
Where should I start?
Now the data is in a csv file format, but I could change that.
It seems that I want to get the information I have into a "shapefile" or a raster format.
I supose I could look up the formats and do this, but it seems that I havn't come accross the proper utility for this part of the process.
Thank You Peter
You can convert your coordinate into a shapefile to display them in QGIS, ArcMAP, or similar GIS programs. You probably want a polygon shapefile.
One easy way to do this is with the PySAL
>>> import pysal
>>> coords = [(0,0), (10,0), (10,10), (0,10), (0,0)]
>>> pts = map(pysal.cg.Point, coords)
>>> polygon = pysal.cg.Polygon(pts)
>>> shp = pysal.open('myPolygon.shp','w')
>>> shp.write(polygon)
>>> shp.close()
Note: pysal currently doesn't support (Z coordinates) but there are plenty of similar libraries that do.
Also notice the first and last point are the same, indicating a closed polygon.
If your X,Y,Z coordinates are GPS coordinates you'll be able to align your data with other GIS data easily by telling the GIS what projection your data is in (WGS84, UTM Zone #, etc). If your coordinates are in local coordinates (not tied to a grid like UTM, etc) you'll need to "Georeference" you coordinates in order to align them with other data.
Finally using the ogr2ogr command you can easilly export your data from shapefile to other formats like KML,
ogr2ogr -f KML myPolygon.kml myPolygon.shp
You can convert a CSV file into any OGR supported format. All you need is a header file for the CSV file.
Here you have an example:
<ogrvrtdatasource>
<ogrvrtlayer name="bars">
<srcdatasource>bars.csv</srcdatasource>
<geometrytype>wkbPoint</geometrytype>
<layersrs>EPSG:4326</layersrs>
<geometryfield encoding="PointFromColumns" x="longitude" y="latitude">
</geometryfield>
</ogrvrtlayer>
</ogrvrtdatasource>
In the datasource field you set the CSV file name.
In your case, you have points, so the example is ok.
The field layersrs indicates the projection of the coordinates. If you have longitude and latitude, this one is ok.
The geometryfields must contain the x and y properties, that define the columns in the CSV file that containt the coordinates. The CSV file must have a first line defining the field names.
Save the file with a .vrt extension.
Once you have this, use the ogr2ogr program, which you have if GDAL is installed.
If you want to convert the file to a Shapefile, just type in a console:
ogr2ogr -f "ESRI Shapefile" bars.shp bars.vrt
If your question is what to do with the data, you can check the gdal_grid utility program, which converts scattered data (as yours) to raster data. You can use the CSV with the vrt header file as the input, without changing the format.

Categories

Resources