Error parsing XML rectilinear files that contain with an appended dataarray ending with 0
Paraview 5.9.1 will fail to parse a xml rectilinear file that contains a data array that ends with the number 0.0
.
The data array must be appended in binary (I have not tested base64) and must be followed by another appended
data array.
If the data array is the last array in the appended section then the file will parse successfully.
I am using a binary built from the arch linux community repos here if it helps.
I also have a simple python script (standard library only) generate a 3x3x3 grid to reproduce the issue:
import struct
def header(offset_1, offset_2):
return r"""<?xml version="1.0" encoding="UTF-8"?>
<VTKFile type="RectilinearGrid" version="1.0" byte_order="LittleEndian" header_type="UInt64">
<RectilinearGrid WholeExtent="1 3 1 3 1 3">
<Piece Extent="1 3 1 3 1 3">
<Coordinates>
<DataArray type="Float64" NumberOfComponents="1" Name="X" format="ascii">
1.0 2.0 3.0
</DataArray>
<DataArray type="Float64" NumberOfComponents="1" Name="Y" format="ascii">
1.0 2.0 3.0
</DataArray>
<DataArray type="Float64" NumberOfComponents="1" Name="Z" format="ascii">
1.0 2.0 3.0
</DataArray>
</Coordinates>
<PointData>
<DataArray type="Float64" NumberOfComponents="1" Name="array_a" format="appended" offset="{}" />
<DataArray type="Float64" NumberOfComponents="1" Name="array_b" format="appended" offset="{}" />
</PointData>
</Piece>
</RectilinearGrid>
<AppendedData encoding="raw">_""".format(offset_1, offset_2)
def footer():
return r"""
</AppendedData>
</VTKFile> """
def write_vtk(array_a, array_b, path):
with open(path, "w") as f:
f.write(header(0, len(array_b)*8))
# write the appended data section
with open(path, "ab") as f:
# for some reason paraview expects the first bytes after '_'
# to be ignored - I have not found this documented anywhere
# but inspecting the spreadsheet view shows this is true
f.write(struct.pack("d", 100))
for num in array_a:
float_bytes = struct.pack("d", num)
f.write(float_bytes)
for num in array_b:
float_bytes = struct.pack("d", num)
f.write(float_bytes)
# close the appended data section
with open(path, "a") as f:
f.write(footer())
def main():
total_points = 3**3
# generate 27 sample data points
array_a = [float(i) for i in range(0,total_points)]
array_b = [ float(i) for i in list(range(0,total_points))]
write_vtk(array_a, array_b, "good_vtk.vtk")
# change the final value for the first array (to be appended)
# to 0
# this causes paraview to fail to parse the file:
array_a[-1] = 0.0
write_vtk(array_a, array_b, "bad_vtk.vtk")
if __name__ == "__main__":
main()