VTK RectilinearGrid#
.vtr read + write eager
Summary of the specification#
.vtr is one of the VTK XML serial formats. A <VTKFile type="RectilinearGrid"> root wraps a piece whose extent is declared as six integer indices, and whose geometry is three independent coordinate arrays - one per axis - rather than an explicit point list. Data arrays live in <PointData> and <CellData> and may be stored inline as ASCII, inline as base64, or appended as a single raw block referenced by byte offset, optionally zlib-compressed.
Specification at a glance#
root |
<VTKFile type=”RectilinearGrid” version=”1.0” byte_order=”…”> |
geometry |
<Coordinates> with three <DataArray>, one per axis |
extent |
WholeExtent / Extent as six integers: x0 x1 y0 y1 z0 z1 |
storage |
format=”ascii” | “binary” (base64) | “appended” with offsets |
compression |
optional vtkZLibDataCompressor header |
Reading#
import polyxios as px
mesh = px.read("model.vtr")
mesh.vertices # (n, 3)
mesh.element_types # element groups found in the file
Writing#
px.write(mesh, "out.vtr")
This codec takes no format-specific options.
Quirks worth knowing#
A tag group has no set of its own in this format, so it travels as one
PointDataorCellDatacolumn of ones and zeros namedpolyxios_tag_<group>. An entity in two groups is named by both columns, which a format spelling one reference per entity cannot say. On the way in, a column with that name holding whole numbers is read back as the group; one holding anything else stays an attribute, since a member rounded into place names the wrong entity.<FieldData>is the mesh’s own metadata rather than any point’s or cell’s: it is read from the dataset element and from a<Piece>alike, and written back fromglobal_attrs. A key both levels spell is the dataset’s, which is the file’s own answer for the mesh where a piece’s is one piece’s. The block holds arrays and nothing else, so a scalar written from one comes back as a one-element array, and every axis past the first is a component.<FieldData>holds aStringarray beside its numeric ones, so aglobal_attrsvalue that is text - a name, a title, a solver’s own label - is written as one and comes back the string it was; a list of strings is one array of several tuples. A value that is neither numbers nor text - a mapping, a ragged list - is dropped with a warning naming the key.The
vtr_*grid entries are spelled from the grid itself on the way out, so they never travel as field data; every otherglobal_attrsentry does.The implied point grid is expanded to explicit vertices on read, so a rectilinear file behaves like any other mesh downstream.
Appended and base64 payloads are decoded eagerly, and
lazy=TrueraisesLazyReadErrorrather than pretending otherwise - the XML container has no seekable layout for mmap.Multi-component attributes declare and honour
NumberOfComponents, so an(n, 3)vector survives a round trip rather than coming back as3nrows.Binary arrays are written in the type their
<DataArray>declares, so an integer attribute stays an integer one.An extent flat along an axis - an image one voxel deep - is a sheet of quads, and one flat along two axes is a run of lines. Only a fully three-dimensional extent expands to hexahedra; reading a flat one as a grid of no cells leaves every
CellDataarray belonging to nothing.The writer holds a lattice and nothing else, and says so rather than spelling a file its own reader refuses. The extent is read off the cells, and the three coordinate arrays are then read off the vertices a stride at a time - so an axis that runs downwards keeps its direction rather than being sorted round under its own point data. A mesh whose vertices are not that lattice expanded, in the order the file reads them back, raises
CodecError; so do cells that are not the grid’s own, which the file carries no connectivity for and would drop with theirCellData. Write a VTK StructuredGrid for points that are not a lattice, or a VTK UnstructuredGrid for an arbitrary mesh.A mesh with no vertices writes the extent VTK spells an empty grid with,
0 -1 0 -1 0 -1, and reads back as a mesh with none.An extent that ends before it starts on any axis holds no points, so it holds no cells either -
0 -1 0 2 0 2reads as an empty mesh rather than as four quads whose corners name points the file never spelled.The extent counts the planes and the coordinate arrays spell them, and nothing in the file makes the two agree. An array of a different length raises
CodecErrornaming its axis: the cells, the offsets and everyPointDataarray are sized off the extent, so a longer one used to expand into a mesh whose connectivity covered part of itself and whose attributes covered none of it. Every axis is asked, including one the extent gives no plane at all - the point count is a product and goes to zero on such an axis, but the vertices are built from the coordinates, so a file spelling one anyway came back as a mesh the extent called empty. An axis the file leaves no array for at all takes its one plane at zero, which is how a 2-D grid writes its z.The extent of the file a mesh was read from travels with it, so a block that did not begin at zero is written back at the indices it stood on rather than slid to the origin - which is what a
.pvtrassembling it next to its neighbours reads. It is checked against the mesh at the point of writing rather than trusted: one a transform has moved the mesh out from under is re-derived from the cells.
See also
Supported formats - the full format table.