Defining Time-Varying Sources with ParaView’s Programmable Source
One question about ParaView that comes up from time to time is how to define time-varying data sources with the Programmable Source. I’ll show the basics of doing this here.
Let’s start by looking at a simple example that produces a single static sphere. First, fire up ParaView and create a Programmable Source. The Script property for the Programmable Source in this example should be:
import vtk sphere = vtk.vtkSphereSource() sphere.SetRadius(1.0) sphere.Update() pd = self.GetPolyDataOutput() pd.ShallowCopy(sphere.GetOutput())
This creates a simple sphere source at the origin. Pretty boring, right?
Let’s make the sphere radius vary with time. To do this, we need to tell ParaView that our Programmable Source produces time-varying data. First, we tell the pipeline that the source has time information and define the time values in the Script (RequestInformation) property:
timeSteps = range(100) outInfo = self.GetOutputInformation(0) timeRange = [timeSteps[0], timeSteps[-1]] outInfo.Set(vtk.vtkStreamingDemandDrivenPipeline.TIME_RANGE(), timeRange, 2) outInfo.Set(vtk.vtkStreamingDemandDrivenPipeline.TIME_STEPS(), timeSteps, len(timeSteps))
Here, we define 100 timesteps [0, 1, 2, … 99]. We need to inform the pipeline about the time range as well as the actual time values themselves. To do this, we set the vtkStreamingDemandDrivenPipeline.TIME_RANGE() and vtkStreamingDemandDrivenPipeline.TIME_STEPS() information keys in the output information.
Next, we adjust our original Script property to modify the radius according to the time value. We retrieve the time value with the vtkStreamingDemandDrivenPipeline.UPDATE_TIME_STEP() key in the output information from the Programmable Filter and derive a radius value from it.
import vtk outInfo = self.GetOutputInformation(0) if outInfo.Has(vtk.vtkStreamingDemandDrivenPipeline.UPDATE_TIME_STEP()): time = outInfo.Get(vtk.vtkStreamingDemandDrivenPipeline.UPDATE_TIME_STEP()) else: time = 0 radius = math.sin(time * 2 * math.pi / 100) + 1.0 sphere = vtk.vtkSphereSource() sphere.SetRadius(radius) sphere.Update() pd = self.GetPolyDataOutput() pd.ShallowCopy(sphere.GetOutput())
When you click the Apply button on the Programmable Filter, you will notice that the number of time steps in the animation controls jumps to 100. If you click the play button, you will see a pulsing sphere.
Obviously, you can do a lot more with the timestep values. See, for example, section 13.2.2 in the ParaView User’s Guide for how to read series of CSV files where each one defines a different timestep.
Update 2016/1/5: To create an XML filter with a time-varying Programmable Source as outlined in this blog post, you will need to add one special property to the XML describing your source. Simply add this XML to your proxy XML description to let ParaView know your source provides time-varying data:
<DoubleVectorProperty information_only="1" name="TimestepValues" repeatable="1"> <Documentation> Available timestep values. </Documentation> </DoubleVectorProperty>
Hi,
thanks for the article! We need to write a source plugin with time-steps and I did notice that this does not work in previous versions (pre 4.4). The time-line did not update there. Now we have this problem again if RequestInformation() comes from an XML plugin. Everything works but the PV timeline does not notice the change.
Thanks for your help,
Christian
Hi Christian H,
Could you share with me your XML plugin by sending it to cory.quammen@kitware.com?
Thank you,
Cory
Christian,
I updated the post at the bottom with the necessary XML you need to add to tell ParaView your programmable source provides time-varying data.
– Cory
This works! Thanks a lot, that was the missing piece. I don’t know if this would help if I put the Programmable Source into a custom filter… That maybe a slightly different problem.
All the best,
Christian
Hello,
Thanks for this example.
I tried to run this example in ParaView 4.3.1 as well as 5.4.1, but didn’t manage to get it running.
The time steps aren’t getting updated according to the defined values (range(100)) and the pre-set range is 0 to 1 and time-steps are 0, 0.111, 0.222, … 1.
I added proxy XML description in the xml of the state file (.pvsm) to let ParaView know my source provides time-varying data Unfortunately, it doesn’t fix the issue (Actually not sure if it is the right place.).
I’d appreciate if you give me a hint on what I am doing wrong.
Cheers,
Farid
Farid, Sorry, there was a recent problem with the code formatting in the blog post that I have now fixed. Also, there was a typo in the RequestInformation Script that I have now fixed. Give it a try again and see if you still have a problem.
Thanks a lot. It worked.
The second code box seems to have a typo. The line
timeRange = [timesteps[0], timeSteps[-1]]
should read
timeRange = [timeSteps[0], timeSteps[-1]] # lowercase ‘S’ was capitalized on first element
I couldn’t get the code the run using any single code box I found a minimal working example to be the following:
import vtk
sphere = vtk.vtkSphereSource()
sphere.SetRadius(1.0)
sphere.Update()
timeSteps = range(100)
outInfo = self.GetOutputInformation(0)
timeRange = [timeSteps[0], timeSteps[-1]]
outInfo.Set(vtk.vtkStreamingDemandDrivenPipeline.TIME_RANGE(), timeRange, 2)
outInfo.Set(vtk.vtkStreamingDemandDrivenPipeline.TIME_STEPS(), timeSteps, len(timeSteps))
outInfo = self.GetOutputInformation(0)
if outInfo.Has(vtk.vtkStreamingDemandDrivenPipeline.UPDATE_TIME_STEP()):
time = outInfo.Get(vtk.vtkStreamingDemandDrivenPipeline.UPDATE_TIME_STEP())
else:
time = 0
radius = math.sin(time * 2 * math.pi / 100) + 1.0
sphere = vtk.vtkSphereSource()
sphere.SetRadius(radius)
sphere.Update()
pd = self.GetPolyDataOutput()
pd.ShallowCopy(sphere.GetOutput())
Thanks for the typo correction. I have fixed the blog post. And thanks for putting it all together in one example.