InsightSoftwareConsortium / ITKPythonPackage

A setup script to generate ITK Python Wheels
https://itkpythonpackage.readthedocs.io
Apache License 2.0
64 stars 22 forks source link

Unable to read VTK meshes from web, 3DSlicer and Python VTK #281

Closed neurolabusc closed 1 month ago

neurolabusc commented 1 month ago

I have ITK 5.4.0 installed on my MacOS computer. I am using a binary 'cow.vtk' mesh created by 3D Slicer cow.vtk.zip as well as an ASCII version from here.

I am trying to run this example but it is unable to read these files.

mesh = itk.meshread('cow.vtk')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/itk/support/extras.py", line 1459, in meshread
    reader.Update()
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/itk/ITKCommonBasePython.py", line 3111, in Update
    return _ITKCommonBasePython.itkProcessObject_Update(self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: /Users/svc-dashboard/D/P/ITKPythonPackage/ITK-source/ITK/Modules/IO/MeshBase/src/itkMeshIOBase.cxx:89:
ITK ERROR: VTKPolyDataMeshIO(0x6000010d4000): Unknown component type: 
>>> mesh = itk.meshread('cow.ASCII.vtk')
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/itk/support/template_class.py", line 525, in __getitem__
    this_item = self.__template__[key]
                ~~~~~~~~~~~~~~~~~^^^^^
KeyError: (<class 'itk.itkVectorPython.itkVectorF3'>, 3)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/itk/support/extras.py", line 1458, in meshread
    reader = TemplateReaderType.New(**kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/itk/support/template_class.py", line 671, in New
    return self._NewMeshReader(itk.MeshFileReader, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/itk/support/template_class.py", line 255, in _NewMeshReader
    MeshType = itk.Mesh[PixelType, dimension]
               ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/itk/support/template_class.py", line 529, in __getitem__
    raise itk.TemplateTypeError(self, key)
itk.support.extras.TemplateTypeError: itk.Mesh is not wrapped for input type `itk.Vector[itk.F,3], int`.

To limit the size of the package, only a limited number of
types are available in ITK Python. To print the supported
types, run the following command in your python environment:

    itk.Mesh.GetTypes()

Possible solutions:
* If you are an application user:
** Convert your input image into a supported format (see below).
** Contact developer to report the issue.
* If you are an application developer, force input images to be
loaded in a supported pixel type.

    e.g.: instance = itk.Mesh[itk.SS, int].New(my_input)

* (Advanced) If you are an application developer, build ITK Python yourself and
turned to `ON` the corresponding CMake option to wrap the pixel type or image
dimension you need. When configuring ITK with CMake, you can set
`ITK_WRAP_${type}` (replace ${type} with appropriate pixel type such as
`double`). If you need to support images with 4 or 5 dimensions, you can add
these dimensions to the list of dimensions in the CMake variable
`ITK_WRAP_IMAGE_DIMS`.

Supported input types:

itk.SS
itk.UC
itk.US
itk.F
itk.D
itk.Array[itk.D]
itk.SS
itk.UC
itk.US
itk.F
itk.D
itk.Array[itk.D]
itk.SS
itk.UC
itk.US
itk.F
itk.D
itk.Array[itk.D]
itk.D
itk.D
itk.D

The VTK library does open these meshes, but my attempts to save and reopen with ITK also failed, claiming there is no CONNECTIVITY keyword despite the fact the file clearly lists CONNECTIVITY vtktypeint64

>>> import vtk
>>> 
>>> reader = vtk.vtkPolyDataReader()
>>> reader.SetFileName('cow.vtk')
>>> reader.Update()
>>> # Write it as an ASCII VTK file which might be more compatible with ITK
>>> writer = vtk.vtkPolyDataWriter()
>>> writer.SetFileName('cow_ascii.vtk')
>>> writer.SetInputData(reader.GetOutput())
>>> writer.SetFileTypeToASCII()
>>> writer.Write()
>>> import itk
>>> mesh = itk.meshread('cow_ascii.vtk')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/itk/support/extras.py", line 1459, in meshread
    reader.Update()
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/itk/ITKCommonBasePython.py", line 3111, in Update
    return _ITKCommonBasePython.itkProcessObject_Update(self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: /Users/svc-dashboard/D/P/ITKPythonPackage/ITK-source/ITK/Modules/IO/MeshVTK/src/itkVTKPolyDataMeshIO.cxx:1135:
ITK ERROR: VTKPolyDataMeshIO(0x6000010c0000): Expected CONNECTIVITY keyword in the VTK file
>>> 
thewtex commented 1 month ago

I am trying to run this example but it is unable to read these files.

This version should work: https://data.kitware.com/#item/5aa18c268d777f06857863fd

I was able to reproduce the traceback received with the one that you created. It seems that there is not currently support for the type used in ITK Python.

The itkwasm-mesh-io package did succeed in reading it.

>>> from itkwasm_mesh_io import read_mesh
>>>
>>> from rich import print
>>> m = read_mesh('cow.vtk')
>>> print(m)
Mesh(
    meshType=MeshType(
        dimension=3,
        pointComponentType='float32',
        pointPixelComponentType='int8',
        pointPixelType='Scalar',
        pointPixelComponents=0,
        cellComponentType='uint32',
        cellPixelComponentType='int8',
        cellPixelType='Scalar',
        cellPixelComponents=0
    ),
    name='Mesh',
    numberOfPoints=4792,
    points=array([ 3.6288500e-01,  2.1545650e-01, -1.3835599e-01, ...,
       -1.0299051e+00,  2.0851559e-05,  5.5096006e-01], dtype=float32),
    numberOfPointPixels=0,
    pointData=array([], dtype=int8),
    numberOfCells=5804,
    cells=array([   4,    3,    2, ..., 4581, 4582, 4791], dtype=uint32),
    cellBufferSize=29020,
    numberOfCellPixels=5804,
    cellData=array([], dtype=int8)
)
>>>
neurolabusc commented 1 month ago

Closing issue, as it does read the VTK cow you attached, even if it fails on other valid VTK files. This is curious, as it succeeds on a mesh that mixes quads and triangles, yet fails on geometrically simpler meshes of pure triangles.