Source code for pyvista.utilities.reader

"""Fine-grained control of reading data files."""
from abc import ABC, abstractmethod
from dataclasses import dataclass
from functools import wraps
import os
import pathlib
from typing import Any, Callable, List, Union
from xml.etree import ElementTree

import numpy as np

import pyvista
from pyvista import _vtk
from pyvista.utilities import abstract_class, wrap

from .fileio import _get_ext_force, _process_filename

HDF_HELP = 'https://kitware.github.io/vtk-examples/site/VTKFileFormats/#hdf-file-formats'


[docs]def get_reader(filename, force_ext=None): """Get a reader for fine-grained control of reading data files. Supported file types and Readers: +----------------+---------------------------------------------+ | File Extension | Class | +================+=============================================+ | ``.bmp`` | :class:`pyvista.BMPReader` | +----------------+---------------------------------------------+ | ``.cas`` | :class:`pyvista.FluentReader` | +----------------+---------------------------------------------+ | ``.case`` | :class:`pyvista.EnSightReader` | +----------------+---------------------------------------------+ | ``.cgns`` | :class:`pyvista.CGNSReader` | +----------------+---------------------------------------------+ | ``.dat`` | :class:`pyvista.TecplotReader` | +----------------+---------------------------------------------+ | ``.dcm`` | :class:`pyvista.DICOMReader` | +----------------+---------------------------------------------+ | ``.dem`` | :class:`pyvista.DEMReader` | +----------------+---------------------------------------------+ | ``.facet`` | :class:`pyvista.FacetReader` | +----------------+---------------------------------------------+ | ``.foam`` | :class:`pyvista.POpenFOAMReader` | +----------------+---------------------------------------------+ | ``.g`` | :class:`pyvista.BYUReader` | +----------------+---------------------------------------------+ | ``.gif`` | :class:`pyvista.GIFReader` | +----------------+---------------------------------------------+ | ``.glb`` | :class:`pyvista.GLTFReader` | +----------------+---------------------------------------------+ | ``.gltf`` | :class:`pyvista.GLTFReader` | +----------------+---------------------------------------------+ | ``.hdf`` | :class:`pyvista.HDFReader` | +----------------+---------------------------------------------+ | ``.img`` | :class:`pyvista.DICOMReader` | +----------------+---------------------------------------------+ | ``.inp`` | :class:`pyvista.AVSucdReader` | +----------------+---------------------------------------------+ | ``.jpg`` | :class:`pyvista.JPEGReader` | +----------------+---------------------------------------------+ | ``.jpeg`` | :class:`pyvista.JPEGReader` | +----------------+---------------------------------------------+ | ``.hdr`` | :class:`pyvista.HDRReader` | +----------------+---------------------------------------------+ | ``.mha`` | :class:`pyvista.MetaImageReader` | +----------------+---------------------------------------------+ | ``.mhd`` | :class:`pyvista.MetaImageReader` | +----------------+---------------------------------------------+ | ``.nhdr`` | :class:`pyvista.NRRDReader` | +----------------+---------------------------------------------+ | ``.nrrd`` | :class:`pyvista.NRRDReader` | +----------------+---------------------------------------------+ | ``.obj`` | :class:`pyvista.OBJReader` | +----------------+---------------------------------------------+ | ``.p3d`` | :class:`pyvista.Plot3DMetaReader` | +----------------+---------------------------------------------+ | ``.ply`` | :class:`pyvista.PLYReader` | +----------------+---------------------------------------------+ | ``.png`` | :class:`pyvista.PNGReader` | +----------------+---------------------------------------------+ | ``.pnm`` | :class:`pyvista.PNMReader` | +----------------+---------------------------------------------+ | ``.pts`` | :class:`pyvista.PTSReader` | +----------------+---------------------------------------------+ | ``.pvd`` | :class:`pyvista.PVDReader` | +----------------+---------------------------------------------+ | ``.pvti`` | :class:`pyvista.XMLPImageDataReader` | +----------------+---------------------------------------------+ | ``.pvtk`` | :class:`pyvista.VTKPDataSetReader` | +----------------+---------------------------------------------+ | ``.pvtr`` | :class:`pyvista.XMLPRectilinearGridReader` | +----------------+---------------------------------------------+ | ``.pvtu`` | :class:`pyvista.XMLPUnstructuredGridReader` | +----------------+---------------------------------------------+ | ``.res`` | :class:`pyvista.MFIXReader` | +----------------+---------------------------------------------+ | ``.segy`` | :class:`pyvista.SegYReader` | +----------------+---------------------------------------------+ | ``.sgy`` | :class:`pyvista.SegYReader` | +----------------+---------------------------------------------+ | ``.slc`` | :class:`pyvista.SLCReader` | +----------------+---------------------------------------------+ | ``.stl`` | :class:`pyvista.STLReader` | +----------------+---------------------------------------------+ | ``.tif`` | :class:`pyvista.TIFFReader` | +----------------+---------------------------------------------+ | ``.tiff`` | :class:`pyvista.TIFFReader` | +----------------+---------------------------------------------+ | ``.tri`` | :class:`pyvista.BinaryMarchingCubesReader` | +----------------+---------------------------------------------+ | ``.vti`` | :class:`pyvista.XMLImageDataReader` | +----------------+---------------------------------------------+ | ``.vtk`` | :class:`pyvista.VTKDataSetReader` | +----------------+---------------------------------------------+ | ``.vtm`` | :class:`pyvista.XMLMultiBlockDataReader` | +----------------+---------------------------------------------+ | ``.vtmb`` | :class:`pyvista.XMLMultiBlockDataReader` | +----------------+---------------------------------------------+ | ``.vtp`` | :class:`pyvista.XMLPolyDataReader` | +----------------+---------------------------------------------+ | ``.vtr`` | :class:`pyvista.XMLRectilinearGridReader` | +----------------+---------------------------------------------+ | ``.vts`` | :class:`pyvista.XMLStructuredGridReader` | +----------------+---------------------------------------------+ | ``.vtu`` | :class:`pyvista.XMLUnstructuredGridReader` | +----------------+---------------------------------------------+ Parameters ---------- filename : str The string path to the file to read. force_ext : str, optional An extension to force a specific reader to be chosen. Returns ------- pyvista.BaseReader A subclass of :class:`pyvista.BaseReader` is returned based on file type. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_human(load=False) >>> filename.split("/")[-1] # omit the path 'Human.vtp' >>> reader = pyvista.get_reader(filename) >>> reader # doctest: +ELLIPSIS XMLPolyDataReader('.../Human.vtp') >>> mesh = reader.read() >>> mesh # doctest: +ELLIPSIS PolyData ... >>> mesh.plot(color='tan') """ ext = _get_ext_force(filename, force_ext) try: Reader = CLASS_READERS[ext] except KeyError: raise ValueError(f"`pyvista.get_reader` does not support a file with the {ext} extension") return Reader(filename)
[docs]@abstract_class class BaseReader: """The Base Reader class. The base functionality includes reading data from a file, and allowing access to the underlying vtk reader. See :func:`pyvista.get_reader` for an example using a built-in subclass. Parameters ---------- path : str Path of the file to read. """ _class_reader: Any = None def __init__(self, path): """Initialize Reader by setting path.""" self._reader = self._class_reader() self._filename = None self._progress_bar = False self._progress_msg = None self.__directory = None self._set_defaults() self.path = path self._set_defaults_post() def __repr__(self): """Representation of a Reader object.""" return f"{self.__class__.__name__}('{self.path}')"
[docs] def show_progress(self, msg=None): """Show a progress bar when loading the file. Parameters ---------- msg : str, optional Progress bar message. Defaults to ``"Reading <file base name>"``. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cavity(load=False) >>> reader = pyvista.OpenFOAMReader(filename) >>> reader.show_progress() """ self._progress_bar = True if msg is None: msg = f"Reading {os.path.basename(self.path)}" self._progress_msg = msg
[docs] def hide_progress(self): """Hide the progress bar when loading the file. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cavity(load=False) >>> reader = pyvista.OpenFOAMReader(filename) >>> reader.hide_progress() """ self._progress_bar = False
@property def reader(self): """Return the vtk Reader object. Returns ------- pyvista.BaseReader An instance of the Reader object. """ if self._reader is None: # pragma: no cover raise NotImplementedError return self._reader @property def path(self) -> str: """Return or set the filename or directory of the reader. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_human(load=False) >>> reader = pyvista.XMLPolyDataReader(filename) >>> reader.path # doctest:+SKIP '/home/user/.local/share/pyvista/examples/Human.vtp' """ if self._filename is not None: return self._filename return self.__directory @path.setter def path(self, path: str): if os.path.isdir(path): self._set_directory(path) elif os.path.isfile(path): self._set_filename(path) else: raise FileNotFoundError(f"Path '{path}' is invalid or does not exist.") def _set_directory(self, directory): """Set directory and update reader.""" self._filename = None self.__directory = directory self.reader.SetDirectoryName(directory) self._update_information() def _set_filename(self, filename): """Set filename and update reader.""" # Private method since changing file type requires a # different subclass. self.__directory = None self._filename = filename self.reader.SetFileName(filename) self._update_information()
[docs] def read(self): """Read data in file. Returns ------- pyvista.DataSet PyVista Dataset. """ from pyvista.core.filters import _update_alg # avoid circular import _update_alg(self.reader, progress_bar=self._progress_bar, message=self._progress_msg) data = wrap(self.reader.GetOutputDataObject(0)) if data is None: # pragma: no cover raise RuntimeError("Failed to read file.") data._post_file_load_processing() return data
def _update_information(self): self.reader.UpdateInformation() def _set_defaults(self): """Set defaults on reader, if needed.""" pass def _set_defaults_post(self): """Set defaults on reader post setting file, if needed.""" pass
[docs]class PointCellDataSelection: """Mixin for readers that support data array selections. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_backward_facing_step(load=False) >>> filename.split("/")[-1] # omit the path 'foam_case_0_0_0_0.case' >>> reader = pyvista.get_reader(filename) >>> reader # doctest: +ELLIPSIS EnSightReader('.../foam_case_0_0_0_0.case') >>> reader.cell_array_names ['v2', 'nut', 'k', 'nuTilda', 'p', 'omega', 'f', 'epsilon', 'U'] >>> reader.point_array_names [] >>> reader.all_cell_arrays_status # doctest: +NORMALIZE_WHITESPACE {'v2': True, 'nut': True, 'k': True, 'nuTilda': True, 'p': True, 'omega': True, 'f': True, 'epsilon': True, 'U': True} >>> reader.disable_all_cell_arrays() >>> reader.enable_cell_array('U') >>> mesh = reader.read() # MultiBlock mesh >>> mesh[0].array_names ['U'] """ @property def number_point_arrays(self): """Return the number of point arrays. Returns ------- int """ return self.reader.GetNumberOfPointArrays() @property def point_array_names(self): """Return the list of all point array names. Returns ------- list[str] """ return [self.reader.GetPointArrayName(i) for i in range(self.number_point_arrays)]
[docs] def enable_point_array(self, name): """Enable point array with name. Parameters ---------- name : str Point array name. """ self.reader.SetPointArrayStatus(name, 1)
[docs] def disable_point_array(self, name): """Disable point array with name. Parameters ---------- name : str Point array name. """ self.reader.SetPointArrayStatus(name, 0)
[docs] def point_array_status(self, name): """Get status of point array with name. Parameters ---------- name : str Point array name. Returns ------- bool Whether reading the cell array is enabled. """ if self.reader.GetPointArrayStatus(name): return True return False
[docs] def enable_all_point_arrays(self): """Enable all point arrays.""" for name in self.point_array_names: self.enable_point_array(name)
[docs] def disable_all_point_arrays(self): """Disable all point arrays.""" for name in self.point_array_names: self.disable_point_array(name)
@property def all_point_arrays_status(self): """Return the status of all point arrays. Returns ------- dict[str, bool] """ return {name: self.point_array_status(name) for name in self.point_array_names} @property def number_cell_arrays(self): """Return the number of cell arrays. Returns ------- int """ return self.reader.GetNumberOfCellArrays() @property def cell_array_names(self): """Return the list of all cell array names. Returns ------- list[str] """ return [self.reader.GetCellArrayName(i) for i in range(self.number_cell_arrays)]
[docs] def enable_cell_array(self, name): """Enable cell array with name. Parameters ---------- name : str Cell array name. """ self.reader.SetCellArrayStatus(name, 1)
[docs] def disable_cell_array(self, name): """Disable cell array with name. Parameters ---------- name : str Cell array name. """ self.reader.SetCellArrayStatus(name, 0)
[docs] def cell_array_status(self, name): """Get status of cell array with name. Parameters ---------- name : str Cell array name. Returns ------- bool Whether reading the cell array is enabled. """ return bool(self.reader.GetCellArrayStatus(name))
[docs] def enable_all_cell_arrays(self): """Enable all cell arrays.""" for name in self.cell_array_names: self.enable_cell_array(name)
[docs] def disable_all_cell_arrays(self): """Disable all cell arrays.""" for name in self.cell_array_names: self.disable_cell_array(name)
@property def all_cell_arrays_status(self): """Return the status of all cell arrays. Returns ------- dict[str, bool] """ return {name: self.cell_array_status(name) for name in self.cell_array_names}
[docs]class TimeReader(ABC): """Abstract class for readers supporting time.""" @property @abstractmethod def number_time_points(self): """Return number of time points or iterations available to read. Returns ------- int """
[docs] @abstractmethod def time_point_value(self, time_point): """Value of time point or iteration by index. Parameters ---------- time_point: int Time point index. Returns ------- float """
@property def time_values(self): """All time or iteration values. Returns ------- list[float] """ return [self.time_point_value(idx) for idx in range(self.number_time_points)] @property @abstractmethod def active_time_value(self): """Active time or iteration value. Returns ------- float """
[docs] @abstractmethod def set_active_time_value(self, time_value): """Set active time or iteration value. Parameters ---------- time_value: float Time or iteration value to set as active. """
[docs] @abstractmethod def set_active_time_point(self, time_point): """Set active time or iteration by index. Parameters ---------- time_point: int Time or iteration point index for setting active time. """
[docs]class XMLImageDataReader(BaseReader, PointCellDataSelection): """XML Image Data Reader for .vti files.""" _class_reader = _vtk.vtkXMLImageDataReader
[docs]class XMLPImageDataReader(BaseReader, PointCellDataSelection): """Parallel XML Image Data Reader for .pvti files.""" _class_reader = _vtk.vtkXMLPImageDataReader
[docs]class XMLRectilinearGridReader(BaseReader, PointCellDataSelection): """XML RectilinearGrid Reader for .vtr files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_rectilinear_grid(load=False) >>> filename.split("/")[-1] # omit the path 'RectilinearGrid.vtr' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> sliced_mesh = mesh.slice('y') >>> sliced_mesh.plot(scalars='Void Volume Fraction', cpos='xz', ... show_scalar_bar=False) """ _class_reader = _vtk.vtkXMLRectilinearGridReader
[docs]class XMLPRectilinearGridReader(BaseReader, PointCellDataSelection): """Parallel XML RectilinearGrid Reader for .pvtr files.""" _class_reader = _vtk.vtkXMLPRectilinearGridReader
[docs]class XMLUnstructuredGridReader(BaseReader, PointCellDataSelection): """XML UnstructuredGrid Reader for .vtu files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_notch_displacement(load=False) >>> filename.split("/")[-1] # omit the path 'notch_disp.vtu' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot(scalars="Nodal Displacement", component=0, ... cpos='xy', show_scalar_bar=False) """ _class_reader = _vtk.vtkXMLUnstructuredGridReader
[docs]class XMLPUnstructuredGridReader(BaseReader, PointCellDataSelection): """Parallel XML UnstructuredGrid Reader for .pvtu files.""" _class_reader = _vtk.vtkXMLPUnstructuredGridReader
[docs]class XMLPolyDataReader(BaseReader, PointCellDataSelection): """XML PolyData Reader for .vtp files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cow_head(load=False) >>> filename.split("/")[-1] # omit the path 'cowHead.vtp' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot( ... cpos=((12, 3.5, -4.5), (4.5, 1.6, 0), (0, 1, 0.3)), ... clim=[0, 100], show_scalar_bar=False ... ) """ _class_reader = _vtk.vtkXMLPolyDataReader
[docs]class XMLStructuredGridReader(BaseReader, PointCellDataSelection): """XML StructuredGrid Reader for .vts files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_structured_grid(load=False) >>> filename.split("/")[-1] # omit the path 'StructuredGrid.vts' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot(style='wireframe', line_width=4, show_scalar_bar=False) """ _class_reader = _vtk.vtkXMLStructuredGridReader
[docs]class XMLMultiBlockDataReader(BaseReader, PointCellDataSelection): """XML MultiBlock Data Reader for .vtm or .vtmb files.""" _class_reader = _vtk.vtkXMLMultiBlockDataReader
# skip pydocstyle D102 check since docstring is taken from TimeReader
[docs]class EnSightReader(BaseReader, PointCellDataSelection, TimeReader): """EnSight Reader for .case files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cylinder_crossflow(load=False) >>> filename.split("/")[-1] # omit the path 'cylinder_Re35.case' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot(scalars="velocity", component=1, clim=[-20, 20], ... cpos='xy', cmap='RdBu', show_scalar_bar=False) """ _class_reader = _vtk.vtkGenericEnSightReader def _set_filename(self, filename): """Set filename and update reader.""" # Private method since changing file type requires a # different subclass. self._filename = filename self.reader.SetCaseFileName(filename) self._update_information() @property def number_time_points(self): # noqa: D102 return self.reader.GetTimeSets().GetItem(0).GetSize()
[docs] def time_point_value(self, time_point): # noqa: D102 return self.reader.GetTimeSets().GetItem(0).GetValue(time_point)
@property def active_time_value(self): # noqa: D102 return self.reader.GetTimeValue()
[docs] def set_active_time_value(self, time_value): # noqa: D102 if time_value not in self.time_values: raise ValueError( f"Not a valid time {time_value} from available time values: {self.reader_time_values}" ) self.reader.SetTimeValue(time_value)
[docs] def set_active_time_point(self, time_point): # noqa: D102 self.reader.SetTimeValue(self.time_point_value(time_point))
# skip pydocstyle D102 check since docstring is taken from TimeReader
[docs]class OpenFOAMReader(BaseReader, PointCellDataSelection, TimeReader): """OpenFOAM Reader for .foam files. By default, pyvista enables all patch arrays. This is a deviation from the vtk default. """ _class_reader = _vtk.vtkOpenFOAMReader def _set_defaults_post(self): self.enable_all_patch_arrays() @property def number_time_points(self): # noqa: D102 return self.reader.GetTimeValues().GetNumberOfValues()
[docs] def time_point_value(self, time_point): # noqa: D102 return self.reader.GetTimeValues().GetValue(time_point)
@property def active_time_value(self): # noqa: D102 try: value = self.reader.GetTimeValue() except AttributeError as err: # pragma: no cover raise AttributeError( "Inspecting active time value only supported for vtk versions >9.1.0" ) from err return value
[docs] def set_active_time_value(self, time_value): # noqa: D102 if time_value not in self.time_values: raise ValueError( f"Not a valid time {time_value} from available time values: {self.time_values}" ) self.reader.UpdateTimeStep(time_value)
[docs] def set_active_time_point(self, time_point): # noqa: D102 self.reader.UpdateTimeStep(self.time_point_value(time_point))
@property def decompose_polyhedra(self): """Whether polyhedra are to be decomposed when read. Returns ------- bool If ``True``, decompose polyhedra into tetrahedra and pyramids. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cavity(load=False) >>> reader = pyvista.OpenFOAMReader(filename) >>> reader.decompose_polyhedra = False >>> reader.decompose_polyhedra False """ return bool(self.reader.GetDecomposePolyhedra()) @decompose_polyhedra.setter def decompose_polyhedra(self, value): self.reader.SetDecomposePolyhedra(value) @property def skip_zero_time(self): """Indicate whether or not to ignore the '/0' time directory. Returns ------- bool If ``True``, ignore the '/0' time directory. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cavity(load=False) >>> reader = pyvista.OpenFOAMReader(filename) >>> reader.skip_zero_time = False >>> reader.skip_zero_time False """ return bool(self.reader.GetSkipZeroTime()) @skip_zero_time.setter def skip_zero_time(self, value): self.reader.SetSkipZeroTime(value) self._update_information() self.reader.SetRefresh() @property def cell_to_point_creation(self): """Whether cell data is translated to point data when read. Returns ------- bool If ``True``, translate cell data to point data. Warnings -------- When ``True``, cell and point data arrays will have duplicate names. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cavity(load=False) >>> reader = pyvista.OpenFOAMReader(filename) >>> reader.cell_to_point_creation = False >>> reader.cell_to_point_creation False """ return bool(self.reader.GetCreateCellToPoint()) @cell_to_point_creation.setter def cell_to_point_creation(self, value): self.reader.SetCreateCellToPoint(value) @property def number_patch_arrays(self): """Return number of patch arrays in dataset. Returns ------- int Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cavity(load=False) >>> reader = pyvista.OpenFOAMReader(filename) >>> reader.number_patch_arrays 4 """ return self.reader.GetNumberOfPatchArrays() @property def patch_array_names(self): """Names of patch arrays in a list. Returns ------- list[str] Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cavity(load=False) >>> reader = pyvista.OpenFOAMReader(filename) >>> reader.patch_array_names ['internalMesh', 'patch/movingWall', 'patch/fixedWalls', 'patch/frontAndBack'] """ return [self.reader.GetPatchArrayName(i) for i in range(self.number_patch_arrays)]
[docs] def enable_patch_array(self, name): """Enable reading of patch array. Parameters ---------- name : str Which patch array to enable. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cavity(load=False) >>> reader = pyvista.OpenFOAMReader(filename) >>> reader.enable_patch_array("patch/movingWall") >>> reader.patch_array_status("patch/movingWall") True """ self.reader.SetPatchArrayStatus(name, 1)
[docs] def disable_patch_array(self, name): """Disable reading of patch array. Parameters ---------- name : str Which patch array to disable. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cavity(load=False) >>> reader = pyvista.OpenFOAMReader(filename) >>> reader.disable_patch_array("internalMesh") >>> reader.patch_array_status("internalMesh") False """ self.reader.SetPatchArrayStatus(name, 0)
[docs] def patch_array_status(self, name): """Return status of reading patch array. Parameters ---------- name : str Which patch array to report status. Returns ------- bool Whether the patch with the given name is to be read. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cavity(load=False) >>> reader = pyvista.OpenFOAMReader(filename) >>> reader.enable_patch_array("patch/movingWall") >>> reader.patch_array_status("patch/movingWall") True """ return bool(self.reader.GetPatchArrayStatus(name))
[docs] def enable_all_patch_arrays(self): """Enable reading of all patch arrays. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cavity(load=False) >>> reader = pyvista.OpenFOAMReader(filename) >>> reader.enable_all_patch_arrays() >>> assert reader.patch_array_status("patch/movingWall") >>> assert reader.patch_array_status("patch/fixedWalls") """ self.reader.EnableAllPatchArrays()
[docs] def disable_all_patch_arrays(self): """Disable reading of all patch arrays. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cavity(load=False) >>> reader = pyvista.OpenFOAMReader(filename) >>> reader.disable_all_patch_arrays() >>> assert not reader.patch_array_status("patch.movingWall") >>> assert not reader.patch_array_status("internalMesh") """ self.reader.DisableAllPatchArrays()
@property def all_patch_arrays_status(self): """Status of reading all patch arrays. Returns ------- dict[str, bool] dict key is the patch name and the value is whether it will be read. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cavity(load=False) >>> reader = pyvista.OpenFOAMReader(filename) >>> reader.all_patch_arrays_status #doctest: +NORMALIZE_WHITESPACE {'internalMesh': True, 'patch/movingWall': True, 'patch/fixedWalls': True, 'patch/frontAndBack': True} """ return {name: self.patch_array_status(name) for name in self.patch_array_names}
[docs]class POpenFOAMReader(OpenFOAMReader): """Parallel OpenFOAM Reader for .foam files. Can read parallel-decomposed mesh information and time dependent data. This reader can be used for serial generated data, parallel reconstructed data, and decomposed data. """ _class_reader = staticmethod(_vtk.lazy_vtkPOpenFOAMReader) @property def case_type(self): """Indicate whether decomposed mesh or reconstructed mesh should be read. Returns ------- str If ``'reconstructed'``, reconstructed mesh should be read. If ``'decomposed'``, decomposed mesh should be read. Raises ------ ValueError If the value is not in ['reconstructed', 'decomposed'] Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cavity(load=False) >>> reader = pyvista.POpenFOAMReader(filename) >>> reader.case_type = 'reconstructed' >>> reader.case_type 'reconstructed' """ return 'reconstructed' if self.reader.GetCaseType() else 'decomposed' @case_type.setter def case_type(self, value): if value == 'reconstructed': self.reader.SetCaseType(1) elif value == 'decomposed': self.reader.SetCaseType(0) else: raise ValueError(f"Unknown case type '{value}'.") self._update_information()
[docs]class PLYReader(BaseReader): """PLY Reader for reading .ply files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_lobster(load=False) >>> filename.split("/")[-1] # omit the path 'lobster.ply' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot() """ _class_reader = _vtk.vtkPLYReader
[docs]class OBJReader(BaseReader): """OBJ Reader for reading .obj files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_trumpet(load=False) >>> filename.split("/")[-1] # omit the path 'trumpet.obj' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot(cpos='yz', show_scalar_bar=False) """ _class_reader = _vtk.vtkOBJReader
[docs]class STLReader(BaseReader): """STL Reader for .stl files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cad_model(load=False) >>> filename.split("/")[-1] # omit the path '42400-IDGH.stl' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot() """ _class_reader = _vtk.vtkSTLReader
[docs]class TecplotReader(BaseReader): """Tecplot Reader for ascii .dat files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_tecplot_ascii(load=False) >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh[0].plot() """ _class_reader = _vtk.vtkTecplotReader
[docs]class VTKDataSetReader(BaseReader): """VTK Data Set Reader for .vtk files. Notes ----- This reader calls ``ReadAllScalarsOn``, ``ReadAllColorScalarsOn``, ``ReadAllNormalsOn``, ``ReadAllTCoordsOn``, ``ReadAllVectorsOn``, and ``ReadAllFieldsOn`` on the underlying ``vtkDataSetReader``. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_brain(load=False) >>> filename.split("/")[-1] # omit the path 'brain.vtk' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> sliced_mesh = mesh.slice('x') >>> sliced_mesh.plot(cpos='yz', show_scalar_bar=False) """ _class_reader = _vtk.vtkDataSetReader def _set_defaults_post(self): self.reader.ReadAllScalarsOn() self.reader.ReadAllColorScalarsOn() self.reader.ReadAllNormalsOn() self.reader.ReadAllTCoordsOn() self.reader.ReadAllVectorsOn() self.reader.ReadAllFieldsOn() self.reader.ReadAllTensorsOn()
[docs]class VTKPDataSetReader(BaseReader): """Parallel VTK Data Set Reader for .pvtk files.""" _class_reader = staticmethod(_vtk.lazy_vtkPDataSetReader)
[docs]class BYUReader(BaseReader): """BYU Reader for .g files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_teapot(load=False) >>> filename.split("/")[-1] # omit the path 'teapot.g' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot(cpos='xy', show_scalar_bar=False) """ _class_reader = _vtk.vtkBYUReader
[docs]class FacetReader(BaseReader): """Facet Reader for .facet files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_clown(load=False) >>> filename.split("/")[-1] # omit the path 'clown.facet' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot(color="red") """ _class_reader = staticmethod(_vtk.lazy_vtkFacetReader)
[docs]class Plot3DMetaReader(BaseReader): """Plot3DMeta Reader for .p3d files.""" _class_reader = staticmethod(_vtk.lazy_vtkPlot3DMetaReader)
[docs]class MultiBlockPlot3DReader(BaseReader): """MultiBlock Plot3D Reader.""" _class_reader = staticmethod(_vtk.lazy_vtkMultiBlockPLOT3DReader) def _set_defaults(self): self.auto_detect_format = True
[docs] def add_q_files(self, files): """Add q file(s). Parameters ---------- files : str or Iterable(str) Solution file or files to add. """ # files may be a list or a single filename if files: if isinstance(files, (str, pathlib.Path)): files = [files] files = [_process_filename(f) for f in files] if hasattr(self.reader, 'AddFileName'): # AddFileName was added to vtkMultiBlockPLOT3DReader sometime around # VTK 8.2. This method supports reading multiple q files. for q_filename in files: self.reader.AddFileName(q_filename) else: # SetQFileName is used to add a single q file to be read, and is still # supported in VTK9. if len(files) > 0: if len(files) > 1: raise RuntimeError( 'Reading of multiple q files is not supported with this version of VTK.' ) self.reader.SetQFileName(files[0])
@property def auto_detect_format(self): """Whether to try to automatically detect format such as byte order, etc.""" return bool(self.reader.GetAutoDetectFormat()) @auto_detect_format.setter def auto_detect_format(self, value): self.reader.SetAutoDetectFormat(value)
[docs]class CGNSReader(BaseReader, PointCellDataSelection): """CGNS Reader for .cgns files. Creates a multi-block dataset and reads unstructured grids and structured meshes from binary files stored in CGNS file format, with data stored at the nodes, cells or faces. By default, all point and cell arrays are loaded as well as the boundary patch. This varies from VTK's defaults. For more details, see `vtkCGNSReader <https://vtk.org/doc/nightly/html/classvtkCGNSReader.html>`_ Examples -------- Load a CGNS file. All arrays are loaded by default. >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cgns_multi(load=False) >>> reader = pyvista.CGNSReader(filename) >>> reader.load_boundary_patch = False >>> ds = reader.read() >>> ds[0][0].cell_data pyvista DataSetAttributes Association : CELL Active Scalars : None Active Vectors : Momentum Active Texture : None Active Normals : None Contains arrays : Density float64 (2928,) Momentum float64 (2928, 3) VECTORS EnergyStagnationDensity float64 (2928,) ViscosityEddy float64 (2928,) TurbulentDistance float64 (2928,) TurbulentSANuTilde float64 (2928,) """ _class_reader = staticmethod(_vtk.lazy_vtkCGNSReader) def _set_defaults_post(self): self.enable_all_point_arrays() self.enable_all_cell_arrays() self.load_boundary_patch = True @property def distribute_blocks(self) -> bool: """Distribute each block in each zone across ranks. To make the reader disregard the piece request and read all blocks in the zone, set this to ``False``. The default is ``True``. Returns ------- bool If ``True``, distribute each block in each zone across ranks. Examples -------- Disable distributing blocks. >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cgns_multi(load=False) >>> reader = pyvista.CGNSReader(filename) >>> reader.distribute_blocks = False >>> reader.distribute_blocks False """ return bool(self._reader.GetDistributeBlocks()) @distribute_blocks.setter def distribute_blocks(self, value: str): self._reader.SetDistributeBlocks(value)
[docs] def base_array_status(self, name: str) -> bool: """Get status of base array with name. Parameters ---------- name : str Base array name. Returns ------- bool Whether reading the base array is enabled. """ return bool(self.reader.GetBaseArrayStatus(name))
@property def base_array_names(self): """Return the list of all base array names. Returns ------- list[int] """ return [self.reader.GetBaseArrayName(i) for i in range(self.number_base_arrays)] @property def number_base_arrays(self) -> int: """Return the number of base arrays. Returns ------- int """ return self.reader.GetNumberOfBaseArrays()
[docs] def enable_all_bases(self): """Enable reading all bases. By default only the 0th base is read. Examples -------- Read all bases. >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cgns_multi(load=False) >>> reader = pyvista.CGNSReader(filename) >>> reader.enable_all_bases() """ self._reader.EnableAllBases()
[docs] def disable_all_bases(self): """Disable reading all bases. By default only the 0th base is read. Examples -------- Disable reading all bases. >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cgns_multi(load=False) >>> reader = pyvista.CGNSReader(filename) >>> reader.disable_all_bases() """ self._reader.DisableAllBases()
[docs] def family_array_status(self, name) -> bool: """Get status of family array with name. Parameters ---------- name : str Family array name. Returns ------- bool Whether reading the family array is enabled. """ return bool(self.reader.GetFamilyArrayStatus(name))
@property def family_array_names(self) -> List[str]: """Return the list of all family array names. Returns ------- list[str] """ return [self.reader.GetFamilyArrayName(i) for i in range(self.number_family_arrays)] @property def number_family_arrays(self) -> int: """Return the number of face arrays. Returns ------- int """ return self.reader.GetNumberOfFamilyArrays()
[docs] def enable_all_families(self): """Enable reading all families. By default only the 0th family is read. Examples -------- Read all bases. >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cgns_multi(load=False) >>> reader = pyvista.CGNSReader(filename) >>> reader.enable_all_families() """ self._reader.EnableAllFamilies()
[docs] def disable_all_families(self): """Disable reading all families. Examples -------- Disable reading all bases. >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cgns_multi(load=False) >>> reader = pyvista.CGNSReader(filename) >>> reader.disable_all_families() """ self._reader.DisableAllFamilies()
@property def unsteady_pattern(self) -> bool: """Return or set using an unsteady pattern. When set to ``True`` (default is ``False``), the reader will try to determine FlowSolution_t nodes to read with a pattern matching This can be useful for unsteady solutions when FlowSolutionPointers are not reliable. Examples -------- Set reading the unsteady pattern to ``True``. >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cgns_multi(load=False) >>> reader = pyvista.CGNSReader(filename) >>> reader.unsteady_pattern = True >>> reader.unsteady_pattern True """ return self._reader.GetUseUnsteadyPattern() @unsteady_pattern.setter def unsteady_pattern(self, enabled: bool): self._reader.SetUseUnsteadyPattern(bool(enabled)) @property def vector_3d(self) -> bool: """Return or set adding an empty dimension to vectors in case of 2D solutions. Examples -------- Set adding an empty physical dimension to vectors to ``True``. >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cgns_multi(load=False) >>> reader = pyvista.CGNSReader(filename) >>> reader.vector_3d = True >>> reader.vector_3d True """ return self._reader.GetUse3DVector() @vector_3d.setter def vector_3d(self, enabled: bool): self._reader.SetUse3DVector(bool(enabled)) @property def load_boundary_patch(self) -> bool: """Return or set loading boundary patches. Notes ----- VTK default is ``False``, but PyVista uses ``True``. Examples -------- Enable loading boundary patches . >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cgns_multi(load=False) >>> reader = pyvista.CGNSReader(filename) >>> reader.load_boundary_patch = True >>> reader.load_boundary_patch True """ return self._reader.GetLoadBndPatch() @load_boundary_patch.setter def load_boundary_patch(self, enabled: bool): self._reader.SetLoadBndPatch(bool(enabled))
[docs]class BinaryMarchingCubesReader(BaseReader): """BinaryMarchingCubes Reader for .tri files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_pine_roots(load=False) >>> filename.split("/")[-1] # omit the path 'pine_root.tri' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot(color="brown") """ _class_reader = _vtk.vtkMCubesReader
@dataclass(order=True) class PVDDataSet: """Class for storing dataset info from PVD file.""" time: float part: int path: str group: str # skip pydocstyle D102 check since docstring is taken from TimeReader
[docs]class PVDReader(BaseReader, TimeReader): """PVD Reader for .pvd files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_wavy(load=False) >>> filename.split("/")[-1] # omit the path 'wavy.pvd' >>> reader = pyvista.get_reader(filename) >>> reader.time_values # doctest: +ELLIPSIS [0.0, 1.0, 2.0, 3.0, ... 12.0, 13.0, 14.0] >>> reader.set_active_time_point(5) >>> reader.active_time_value 5.0 >>> mesh = reader.read()[0] # MultiBlock mesh with only 1 block >>> mesh.plot(scalars='z') """ def __init__(self, filename): """Initialize PVD file reader.""" self._reader = None self.__directory = None self._datasets = [] self._active_datasets = [] self._active_readers = [] self._time_values = [] self._set_filename(filename) @property def reader(self): """Return the PVDReader. .. note:: This Reader does not have an underlying vtk Reader. """ return self @property def active_readers(self): """Return the active readers. Returns ------- list[pyvista.BaseReader] """ return self._active_readers @property def datasets(self): """Return all datasets. Returns ------- list[pyvista.PVDDataSet] """ return self._datasets @property def active_datasets(self): """Return all active datasets. Returns ------- list[pyvista.PVDDataSet] """ return self._active_datasets def _set_filename(self, filename): """Set filename and update reader.""" self._filename = filename self.__directory = os.path.join(os.path.dirname(filename)) self._datasets = None self._active_datasets = None self._update_information()
[docs] def read(self): """Read data from PVD timepoint. Overrides :func:`pyvista.BaseReader.read`. Returns ------- pyvista.MultiBlock """ return pyvista.MultiBlock([reader.read() for reader in self.active_readers])
def _update_information(self): """If dataset information is unavailable, parse file.""" if self.datasets is None: self._parse_file() def _parse_file(self): """Parse PVD file.""" if self.path is None: raise ValueError("Filename must be set") tree = ElementTree.parse(self.path) root = tree.getroot() dataset_elements = root[0].findall("DataSet") datasets = [] for element in dataset_elements: element_attrib = element.attrib datasets.append( PVDDataSet( float(element_attrib.get('timestep', 0)), int(element_attrib['part']), element_attrib['file'], element_attrib.get('group'), ) ) self._datasets = sorted(datasets) self._time_values = sorted(list(set([dataset.time for dataset in self.datasets]))) self.set_active_time_value(self.time_values[0]) @property def time_values(self): # noqa: D102 return self._time_values @property def number_time_points(self): # noqa: D102 return len(self.time_values)
[docs] def time_point_value(self, time_point): # noqa: D102 return self.time_values[time_point]
@property def active_time_value(self): # noqa: D102 # all active datasets have the same time return self.active_datasets[0].time
[docs] def set_active_time_value(self, time_value): # noqa: D102 self._active_datasets = [dataset for dataset in self.datasets if dataset.time == time_value] self._active_readers = [ get_reader(os.path.join(self.__directory, dataset.path)) for dataset in self.active_datasets ]
[docs] def set_active_time_point(self, time_point): # noqa: D102 self.set_active_time_value(self.time_values[time_point])
[docs]class DICOMReader(BaseReader): """DICOM Reader for reading ``.dcm`` files. This reader reads a single file or a path containing a several ``.dcm`` files (DICOM stack). Parameters ---------- path : str Path to the single DICOM (``.dcm``) file to be opened or the directory containing a stack of DICOM files. Examples -------- Read a DICOM stack. >>> import pyvista >>> from pyvista import examples >>> path = examples.download_dicom_stack(load=False) >>> reader = pyvista.DICOMReader(path) >>> dataset = reader.read() >>> dataset.plot(volume=True, zoom=3, show_scalar_bar=False) """ _class_reader = _vtk.vtkDICOMImageReader
[docs]class BMPReader(BaseReader): """BMP Reader for .bmp files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_masonry_texture(load=False) >>> filename.split("/")[-1] # omit the path 'masonry.bmp' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot() """ _class_reader = _vtk.vtkBMPReader
[docs]class DEMReader(BaseReader): """DEM Reader for .dem files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_st_helens(load=False) >>> filename.split("/")[-1] # omit the path 'SainteHelens.dem' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot() """ _class_reader = _vtk.vtkDEMReader
[docs]class JPEGReader(BaseReader): """JPEG Reader for .jpeg and .jpg files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_mars_jpg() >>> filename.split("/")[-1] # omit the path 'mars.jpg' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot() """ _class_reader = _vtk.vtkJPEGReader
[docs]class MetaImageReader(BaseReader): """Meta Image Reader for .mha and .mhd files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_chest(load=False) >>> filename.split("/")[-1] # omit the path 'ChestCT-SHORT.mha' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot() """ _class_reader = _vtk.vtkMetaImageReader
[docs]class NRRDReader(BaseReader): """NRRDReader for .nrrd and .nhdr files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_beach(load=False) >>> filename.split("/")[-1] # omit the path 'beach.nrrd' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot() """ _class_reader = _vtk.vtkNrrdReader
[docs]class PNGReader(BaseReader): """PNGReader for .png files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_vtk_logo(load=False) >>> filename.split("/")[-1] # omit the path 'vtk.png' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot() """ _class_reader = _vtk.vtkPNGReader
[docs]class PNMReader(BaseReader): """PNMReader for .pnm files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_gourds_pnm(load=False) >>> filename.split("/")[-1] # omit the path 'Gourds.pnm' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot() """ _class_reader = _vtk.vtkPNMReader
[docs]class SLCReader(BaseReader): """SLCReader for .slc files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_knee_full(load=False) >>> filename.split("/")[-1] # omit the path 'vw_knee.slc' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot() """ _class_reader = _vtk.vtkSLCReader
[docs]class TIFFReader(BaseReader): """TIFFReader for .tif and .tiff files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_crater_imagery(load=False) >>> filename.split("/")[-1] # omit the path 'BJ34_GeoTifv1-04_crater_clip.tif' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot() """ _class_reader = _vtk.vtkTIFFReader
[docs]class HDRReader(BaseReader): """HDRReader for .hdr files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_parched_canal_4k(load=False) >>> filename.split("/")[-1] # omit the path 'parched_canal_4k.hdr' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot() """ _class_reader = _vtk.vtkHDRReader
[docs]class PTSReader(BaseReader): """PTSReader for .pts files.""" _class_reader = _vtk.vtkPTSReader
[docs]class AVSucdReader(BaseReader): """AVSucdReader for .inp files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_cells_nd(load=False) >>> filename.split("/")[-1] # omit the path 'cellsnd.ascii.inp' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot(cpos="xy") """ _class_reader = _vtk.vtkAVSucdReader
[docs]class HDFReader(BaseReader): """HDFReader for .hdf files. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_can_crushed_hdf(load=False) >>> filename.split("/")[-1] # omit the path 'can-vtu.hdf' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot() """ _class_reader = staticmethod(_vtk.lazy_vtkHDFReader)
[docs] @wraps(BaseReader.read) def read(self): """Wrap the base reader to handle the vtk 9.1 --> 9.2 change.""" try: with pyvista.VtkErrorCatcher(raise_errors=True): return super().read() except RuntimeError as err: # pragma: no cover if "Can't find the `Type` attribute." in str(err): raise RuntimeError( f'{self.path} is missing the Type attribute. ' 'The VTKHDF format has changed as of 9.2.0, ' f'see {HDF_HELP} for more details.' ) else: raise err
[docs]class GLTFReader(BaseReader): """GLTFeader for .gltf and .glb files.""" _class_reader = _vtk.vtkGLTFReader
[docs]class FluentReader(BaseReader): """FluentReader for .cas files.""" _class_reader = _vtk.vtkFLUENTReader
[docs]class MFIXReader(BaseReader): """MFIXReader for .res files.""" _class_reader = _vtk.vtkMFIXReader
[docs]class SegYReader(BaseReader): """SegYReader for .sgy and .segy files.""" _class_reader = staticmethod(_vtk.lazy_vtkSegYReader)
class _GIFReader: """Simulate a VTK reader for GIF files.""" _data_object = None _observers: List[Union[int, Callable]] = [] _n_frames = 0 _current_frame = 0 def SetFileName(self, filename): """Needed for VTK-like compatibility with BaseReader.""" self._filename = filename def UpdateInformation(self): """Needed for VTK-like compatibility with BaseReader.""" pass def AddObserver(self, event_type, callback): """Needed for VTK-like compatibility with BaseReader.""" self._observers.append([event_type, callback]) def RemoveObservers(self, *args): """Needed for VTK-like compatibility with BaseReader.""" self._observers = [] def GetProgress(self): return self._current_frame / self._n_frames def UpdateObservers(self, event_type): for event_type_allowed, observer in self._observers: if event_type_allowed == event_type: observer(self, event_type) def Update(self): """Read the GIF and store internally to `_data_object`.""" from PIL import Image, ImageSequence img = Image.open(self._filename) self._data_object = pyvista.UniformGrid(dims=(img.size[0], img.size[1], 1)) # load each frame to the grid (RGB since gifs do not support transparency self._n_frames = img.n_frames for i, frame in enumerate(ImageSequence.Iterator(img)): self._current_frame = i data = np.array(frame.convert('RGB').getdata(), dtype=np.uint8) self._data_object.point_data.set_array(data, f'frame{i}') self.UpdateObservers(6) if 'frame0' in self._data_object.point_data: self._data_object.point_data.active_scalars_name = 'frame0' def GetOutputDataObject(self, *args): """Needed for VTK-like compatibility with BaseReader.""" return self._data_object
[docs]class GIFReader(BaseReader): """GIFReader for .gif files. Parameters ---------- path : str Path of the GIF to read. Examples -------- >>> import pyvista >>> from pyvista import examples >>> filename = examples.download_gif_simple(load=False) >>> filename.split("/")[-1] # omit the path 'sample.gif' >>> reader = pyvista.get_reader(filename) >>> mesh = reader.read() >>> mesh.plot(rgba=True, zoom='tight', border=True, border_width=2) """ _class_reader = _GIFReader
CLASS_READERS = { # Standard dataset readers: '.bmp': BMPReader, '.cas': FluentReader, '.case': EnSightReader, '.cgns': CGNSReader, '.dat': TecplotReader, '.dcm': DICOMReader, '.dem': DEMReader, '.facet': FacetReader, '.foam': POpenFOAMReader, '.g': BYUReader, '.gif': GIFReader, '.glb': GLTFReader, '.gltf': GLTFReader, '.img': DICOMReader, '.inp': AVSucdReader, '.jpg': JPEGReader, '.jpeg': JPEGReader, '.hdf': HDFReader, '.hdr': HDRReader, '.mha': MetaImageReader, '.mhd': MetaImageReader, '.nhdr': NRRDReader, '.nrrd': NRRDReader, '.obj': OBJReader, '.p3d': Plot3DMetaReader, '.ply': PLYReader, '.png': PNGReader, '.pnm': PNMReader, '.pts': PTSReader, '.pvd': PVDReader, '.pvti': XMLPImageDataReader, '.pvtk': VTKPDataSetReader, '.pvtr': XMLPRectilinearGridReader, '.pvtu': XMLPUnstructuredGridReader, '.res': MFIXReader, '.segy': SegYReader, '.sgy': SegYReader, '.slc': SLCReader, '.stl': STLReader, '.tif': TIFFReader, '.tiff': TIFFReader, '.tri': BinaryMarchingCubesReader, '.vti': XMLImageDataReader, '.vtk': VTKDataSetReader, '.vtm': XMLMultiBlockDataReader, '.vtmb': XMLMultiBlockDataReader, '.vtp': XMLPolyDataReader, '.vtr': XMLRectilinearGridReader, '.vts': XMLStructuredGridReader, '.vtu': XMLUnstructuredGridReader, }