1313except ImportError :
1414 pass
1515
16- from vtkmodules .vtkIOXML import vtkXMLReader , vtkXMLWriter
17-
1816from vtkmodules .vtkCommonCore import (
17+ vtkVersion ,
1918 vtkPoints ,
2019 vtkStringArray ,
2120 vtkLookupTable ,
2221)
22+
23+ if has_vtkhdf := (np .lib .NumpyVersion (vtkVersion .GetVTKVersion ()) >= '9.4.0' ):
24+ from vtkmodules .vtkIOHDF import vtkHDFReader , vtkHDFWriter
25+
2326from vtkmodules .vtkCommonDataModel import (
2427 vtkDataSet ,
2528 vtkCellArray ,
3336 vtkDataSetWriter ,
3437)
3538from vtkmodules .vtkIOXML import (
39+ vtkXMLWriter ,
3640 vtkXMLImageDataReader ,
3741 vtkXMLImageDataWriter ,
3842 vtkXMLRectilinearGridReader ,
@@ -135,6 +139,7 @@ def __eq__(self,
135139
136140
137141 def copy (self ):
142+ """Return a deep copy."""
138143 if isinstance (self .vtk_data ,vtkImageData ):
139144 dup = vtkImageData ()
140145 elif isinstance (self .vtk_data ,vtkUnstructuredGrid ):
@@ -143,8 +148,6 @@ def copy(self):
143148 dup = vtkPolyData ()
144149 elif isinstance (self .vtk_data ,vtkRectilinearGrid ):
145150 dup = vtkRectilinearGrid ()
146- else :
147- raise TypeError
148151
149152 dup .DeepCopy (self .vtk_data )
150153
@@ -153,7 +156,7 @@ def copy(self):
153156
154157 @property
155158 def comments (self ) -> list [str ]:
156- """Return the comments. """
159+ """Comments in vtkdata """ # noqa: D415
157160 field_data = self .vtk_data .GetFieldData ()
158161 for a in range (field_data .GetNumberOfArrays ()):
159162 if field_data .GetArrayName (a ) == 'comments' :
@@ -170,7 +173,7 @@ def comments(self,
170173 Parameters
171174 ----------
172175 comments : sequence of str
173- Comments.
176+ Comments to assign to vtkdata .
174177 """
175178 s = vtkStringArray ()
176179 s .SetName ('comments' )
@@ -181,19 +184,19 @@ def comments(self,
181184
182185 @property
183186 def N_points (self ) -> int :
184- """Number of points in vtkdata. """
187+ """Number of points in vtkdata""" # noqa: D415
185188 return self .vtk_data .GetNumberOfPoints ()
186189
187190
188191 @property
189192 def N_cells (self ) -> int :
190- """Number of cells in vtkdata. """
193+ """Number of cells in vtkdata""" # noqa: D415
191194 return self .vtk_data .GetNumberOfCells ()
192195
193196
194197 @property
195198 def labels (self ):
196- """Labels of datasets. """
199+ """Labels of datasets""" # noqa: D415
197200 labels = {}
198201
199202 cell_data = self .vtk_data .GetCellData ()
@@ -348,46 +351,55 @@ def load(fname: Union[str, Path],
348351 ----------
349352 fname : str or pathlib.Path
350353 Filename to read.
351- Valid extensions are .vti, .vtu, .vtp, .vtr, and .vtk.
354+ Valid extensions are .vti, .vtu, .vtp, .vtr, vtkhdf, and .vtk.
352355 dataset_type : {'ImageData', 'UnstructuredGrid', 'PolyData', 'RectilinearGrid'}, optional
353356 Name of the vtkDataSet subclass when opening a .vtk file.
354357
355358 Returns
356359 -------
357360 loaded : damask.VTK
358361 VTK-based geometry from file.
362+
363+ Notes
364+ -----
365+ Loading VTKHDF files requires VTK 9.4 or later and presently supports
366+ PolyData, UnstructuredGrid, and ImageData. Loading ImageData is untested
367+ because VTK does not yet provide the functionality to write ImageData
368+ into VTKHDF format.
359369 """
360370 if not Path (fname ).expanduser ().is_file (): # vtk has a strange error handling
361371 raise FileNotFoundError (f'file "{ fname } " not found' )
372+
362373 if (ext := Path (fname ).suffix ) == '.vtk' or dataset_type is not None :
363- vtk_reader = vtkGenericDataObjectReader ()
364- vtk_reader .SetFileName (str (Path (fname ).expanduser ()))
374+ reader_legacy = vtkGenericDataObjectReader ()
375+ reader_legacy .SetFileName (str (Path (fname ).expanduser ()))
376+ reader_legacy .Update ()
365377 if dataset_type is None :
366- raise TypeError ('dataset type for *.vtk file not given' )
367- vtk_reader .Update ()
368- if dataset_type .lower ().endswith (('imagedata' , 'image_data' )):
369- vtk_data = vtk_reader .GetStructuredPointsOutput ()
370- elif dataset_type .lower ().endswith (('unstructuredgrid' , 'unstructured_grid' )):
371- vtk_data = vtk_reader .GetUnstructuredGridOutput ()
372- elif dataset_type .lower ().endswith (('polydata' , 'poly_data' )):
373- vtk_data = vtk_reader .GetPolyDataOutput ()
374- elif dataset_type .lower ().endswith (('rectilineargrid' , 'rectilinear_grid' )):
375- vtk_data = vtk_reader .GetRectilinearGridOutput ()
376- else :
377- raise TypeError (f'unknown dataset type "{ dataset_type } " for vtk file' )
378+ raise TypeError ('missing dataset type for legacy VTK file' )
379+ dtl = dataset_type .lower ()
380+ vtk_data = (
381+ reader_legacy .GetStructuredPointsOutput () if dtl .endswith (('imagedata' , 'image_data' )) else
382+ reader_legacy .GetUnstructuredGridOutput () if dtl .endswith (('unstructuredgrid' , 'unstructured_grid' )) else
383+ reader_legacy .GetPolyDataOutput () if dtl .endswith (('polydata' , 'poly_data' )) else
384+ reader_legacy .GetRectilinearGridOutput () if dtl .endswith (('rectilineargrid' , 'rectilinear_grid' )) else
385+ None
386+ )
387+ if vtk_data is None :
388+ raise TypeError (f'unsupported VTK dataset type "{ dataset_type } "' )
378389 else :
379- xml_reader : Optional [ vtkXMLReader ] = (
390+ reader = (
380391 vtkXMLImageDataReader () if ext == '.vti' else
381392 vtkXMLUnstructuredGridReader () if ext == '.vtu' else
382393 vtkXMLPolyDataReader () if ext == '.vtp' else
383394 vtkXMLRectilinearGridReader () if ext == '.vtr' else
395+ vtkHDFReader () if (ext == '.vtkhdf' and has_vtkhdf ) else
384396 None
385397 )
386- if xml_reader is None :
387- raise TypeError (f'unknown file extension "{ ext } "' )
388- xml_reader .SetFileName (str (Path (fname ).expanduser ()))
389- xml_reader .Update ()
390- vtk_data = xml_reader .GetOutputAsDataSet ()
398+ if reader is None :
399+ raise TypeError (f'unsupported VTK file extension "{ ext } "' )
400+ reader .SetFileName (str (Path (fname ).expanduser ()))
401+ reader .Update ()
402+ vtk_data = reader .GetOutputAsDataSet ()
391403
392404 return VTK (vtk_data )
393405
@@ -431,8 +443,7 @@ def save(self,
431443 vtkXMLRectilinearGridWriter () if isinstance (self .vtk_data , vtkRectilinearGrid ) else
432444 None
433445 )
434- if writer is None :
435- raise TypeError (f'unknown vtk_data type "{ type (self .vtk_data )} "' )
446+ assert writer is not None
436447
437448 default_ext = '.' + writer .GetDefaultFileExtension ()
438449 ext = Path (fname ).suffix
@@ -456,6 +467,33 @@ def save(self,
456467 writer .Write ()
457468
458469
470+ def save_VTKHDF (self ,
471+ fname : Union [str , Path ]):
472+ """
473+ Save as VTKHDF file.
474+
475+ Parameters
476+ ----------
477+ fname : str or pathlib.Path
478+ Filename to write.
479+
480+ Notes
481+ -----
482+ Saving as VTKHDF file requires VTK 9.4 or later and only supports
483+ PolyData and UnstructuredGrid.
484+ """
485+ if not has_vtkhdf :
486+ raise NotImplementedError ('save as VTKHDF requires VTK 9.4 or later' )
487+ if not isinstance (self .vtk_data , (vtkPolyData , vtkUnstructuredGrid )):
488+ raise TypeError (f'unsupported vtk_data type "{ type (self .vtk_data )} "' )
489+
490+ writer = vtkHDFWriter ()
491+ ext = Path (fname ).suffix
492+ writer .SetFileName (str (Path (fname ).expanduser ())+ ('.vtkhdf' if '.vtkhdf' != ext else '' ))
493+ writer .SetInputData (self .vtk_data )
494+ writer .Write ()
495+
496+
459497 def set (self ,
460498 label : Optional [str ] = None ,
461499 data : Union [None , np .ndarray , np .ma .MaskedArray ] = None ,
0 commit comments