# Linking animation frames to time series data (hdf5, numpy) in Python reader plugin

**URL:** https://discourse.paraview.org/t/linking-animation-frames-to-time-series-data-hdf5-numpy-in-python-reader-plugin/16337
**Category:** ParaView Support
**Tags:** python
**Created:** [March 14, 2025, 7:14pm UTC](https://discourse.paraview.org/t/linking-animation-frames-to-time-series-data-hdf5-numpy-in-python-reader-plugin/16337 "2025-03-14T19:14:25Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![rbrooksher](https://discourse.paraview.org/letter_avatar_proxy/v4/letter/r/a183cd/32.png) [@rbrooksher](https://discourse.paraview.org/u/rbrooksher)
#### Post date: [March 14, 2025, 7:14pm UTC](https://discourse.paraview.org/t/linking-animation-frames-to-time-series-data-hdf5-numpy-in-python-reader-plugin/16337/1 "2025-03-14T19:14:25Z")

</div>

Hello,

I have been attempting to create a reader plugin for my hdf5 dataset. The problem I am facing is that animation frames are consistently showing as the default, 10 steps between 1 and 10 inclusive. Is this expected? I have had trouble finding insight in the documentation, but I had expected setting executive.TIME\_STEPS() and executive.TIME\_RANGE() to link my data to the animation. Is there a way to set these from the reader, or am I going about this the wrong way? I have included an example reader similar to my own using a randomly generated numpy array.

```auto
"""
ParaView Python Reader for a 4D NumPy array of shape (T, X, Y, Z).
"""
from __future__ import division, print_function

import os
import numpy as np
import vtk
from paraview.util.vtkAlgorithm import *
from vtkmodules.util import numpy_support as vtknp

def generate_seeded_4d_array(T, X, Y, Z, seed=0):
    """
    Generate a 4D NumPy array of shape (T, X, Y, Z) with random values.
    The 'seed' parameter ensures reproducible random numbers.
    """
    np.random.seed(seed)
    # Creates a 4D array with values in [0, 1)
    data = np.random.rand(T, X, Y, Z)
    return data

@smproxy.reader(name="Random4DNumPyReader",
                label="Random 4D NumPy Reader",
                extensions=["npy"],
                file_description="4D NumPy array (T, X, Y, Z)")
class Random4DNumPyReader(VTKPythonAlgorithmBase):
    def __init__ (self):
        # We have one output port (the 3D image) and no inputs.
        VTKPythonAlgorithmBase. __init__ (self,
                                        nInputPorts=0,
                                        nOutputPorts=1,
                                        outputType="vtkImageData")

        self.__FileName = None
        self.__Data = None
        self.__TimeSteps = None

    #### FileName property ####
    @smproperty.stringvector(name="FileName")
    @smdomain.filelist()
    def SetFileName(self, fname):
        """Called by ParaView when the user selects a file."""
        if self.__FileName != fname:
            self.__FileName = fname
            self.Modified() # Mark the reader "modified" so it reloads

    def RequestInformation(self, request, inInfo, outInfo):
        """
        ParaView calls RequestInformation first to query the data extents,
        time steps, etc.
        """
        if not self.__FileName or not os.path.exists(self.__FileName):
            return 1

        executive = self.GetExecutive()

        # Load the 4D array. Shape expected: (T, X, Y, Z)
        data_array = np.load(self.__FileName)
        self.__Data = data_array # Keep a reference for RequestData

        # Suppose data_array.shape = (T, X, Y, Z)
        shape = data_array.shape
        if len(shape) != 4:
            raise RuntimeError(
                f"Expected a 4D array (T, X, Y, Z), got shape={shape}"
            )

        T, X, Y, Z = shape

        # Define discrete time steps as integers 0..T-1 (or floats)
        self.__TimeSteps = list(range(T))
        
        # Tell ParaView about the available time steps
        outInfo_0 = outInfo.GetInformationObject(0)

        outInfo_0.Remove(executive.TIME_STEPS())
        outInfo_0.Remove(executive.TIME_RANGE())
        for t in self.__TimeSteps:
            outInfo_0.Append(executive.TIME_STEPS(), t)
        
        outInfo_0.Append(executive.TIME_RANGE(), self.__TimeSteps[0])
        outInfo_0.Append(executive.TIME_RANGE(), self.__TimeSteps[-1])

        extent = [0, X - 1, 0, Y - 1, 0, Z - 1]
        outInfo_0.Set(
            executive.WHOLE_EXTENT(),
            extent,
            6
        )

        return 1

    def RequestData(self, request, inInfo, outInfo):
        if self.__Data is None:
            return 1
        
        executive = self.GetExecutive()

        time = request.Get(executive.UPDATE_TIME_STEP())
        if self.__TimeSteps:
            if time not in self.__TimeSteps:
                idx = int(round(time))
            else:
                idx = int(time)
        else:
            idx = 0

        vol_3d = self.__Data[idx, :, :, :]

        output = vtk.vtkImageData.GetData(outInfo, 0)

        X, Y, Z = vol_3d.shape

        output.SetDimensions(X, Y, Z)

        output.AllocateScalars(vtk.VTK_FLOAT, 1)

        flat_data = vol_3d.astype(np.float32).ravel(order="C")
        vtk_array = vtknp.numpy_to_vtk(flat_data, deep=True, array_type=vtk.VTK_FLOAT)
        vtk_array.SetName("RandomData")
        output.GetPointData().SetScalars(vtk_array)

        output.GetInformation().Set(
            vtk.vtkDataObject.DATA_TIME_STEP(), time
        )
        return 1

```

---

<div class="post-metadata">

### Author: ![jfavre](https://discourse.paraview.org/letter_avatar_proxy/v4/letter/j/b5ac83/32.png) [@jfavre](https://discourse.paraview.org/u/jfavre)
#### Post date: [March 15, 2025, 1:48pm UTC](https://discourse.paraview.org/t/linking-animation-frames-to-time-series-data-hdf5-numpy-in-python-reader-plugin/16337/2 "2025-03-15T13:48:12Z")

</div>

I have seen that many many times. The following code will probably help

```auto
animationScene1 = GetAnimationScene()
animationScene1.UpdateAnimationUsingDataTimeSteps()

```
