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
Related
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.
Can anyone suggest a way, in python or a general tool in linux maybe to convert an obj into a .mat file?
I have some code like:
import eigen_solver as es
import scipy.io as sio
# load mesh
model = 'sphere4.mat'
mat = sio.loadmat(model)
V, F = mat['V'], mat['F']
But the meshes I want to use are in .obj format.
I'm not 100% sure how easy would be to write this from scratch, but I guess should be somehow straightforward, but if there's a tool I'd like to use it.
By obj I mean https://en.wikipedia.org/wiki/Wavefront_.obj_file
By mat I mean the matlab .mat format.
You can simply use meshio to read in the obj file directly.
pip install meshio
import meshio
mesh = meshio.read("foo.obj")
# mesh.points, mesh.cells, etc.
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()
I have a large 40 mb (about 173,397 lines) .dat file filled with binary data (random symbols). It is an astronomical photograph. I need to read and display it with Python. I am using a binary file because I will need to extract pixel value data from specific regions of the image. But for now I just need to ingest it into Python. Something like the READU procedure in IDL. Tried numpy and matplotlib but nothing worked. Suggestions?
You need to know the data type and dimensions of the binary file. For example, if the file contains float data, use numpy.fromfile like:
import numpy as np
data = np.fromfile(filename, dtype=float)
Then reshape the array to the dimensions of the image, dims, using numpy.reshape (the equivalent of REFORM in IDL):
im = np.reshape(data, dims)
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.