Real-Time Insight with ParaView Catalyst: A Hands-On Guide Part 3: Creating Animations

High-performance simulations generate massive datasets—but extracting insight from that data shouldn’t be a bottleneck. ParaView Catalyst integrates analysis and visualization directly into the simulation workflow, delivering in situ processing that eliminates the need for slow, storage-heavy post-processing. The result? You get immediate feedback, streamlined workflows, and new opportunities to steer simulations on the fly.

Built on top of the robust and scalable ParaView architecture, Catalyst minimizes the I/O burden traditionally associated with simulation runs. Whether you’re working at your desk or deploying on a large HPC system, Catalyst adapts to your needs with a flexible, extensible design compatible with a wide variety of simulation codes and computing environments.

This is the last in a series of blogs on writing ParaView Catalyst scripts. You can find the previous article where we demonstrate how to create a ParaView Catalyst script that produces visualization geometry using  a Catalyst instrumented version of LULESH, a well-known mini-app that simulates shock hydrodynamics in high-energy physics here.

In this article, we will be writing scripts that produce image files that can be turned into an animation.

Creating Animations

A crucial application of in situ post-processing involves generating animations without the need to store simulation results, thereby conserving both time and resources. In the following ParaView Catalyst Python script, we will be saving images, which can then be compiled into a video, rather than saving 3D geometry.

#### import the simple module from the paraview
from paraview.simple import *

# ----------------------------------------------------------------
# Part 1: Set Catalyst options
# ----------------------------------------------------------------
from paraview import catalyst
options = catalyst.Options()
options.ExtractsOutputDirectory = 'images'
options.GlobalTrigger.Frequency = 1

# ----------------------------------------------------------------
# Part 2: Setup the view to be used in the visualization
# ----------------------------------------------------------------

#### disable automatic camera reset on 'Show'
paraview.simple._DisableFirstRenderCameraReset()

# Create a new 'Render View'
renderView1 = CreateView('RenderView')
renderView1.Set(
    ViewSize=[1477, 870],
    CenterOfRotation=[0.5625, 0.5625, 0.5625],
    CameraPosition=[-1.5701753191519916, -1.431548219143569, -1.8135467362403885],
    CameraFocalPoint=[0.5625000000000009, 0.5625000000000018, 0.5625000000000002],
    CameraViewUp=[0.8239692610112054, -0.3733041867192652, -0.42628469487716336],
    CameraFocalDisk=1.0,
    CameraParallelScale=0.9742785792574935,
)

# ----------------------------------------------------------------
# Part 3: Create the producer for the grid channel
# ----------------------------------------------------------------
grid = TrivialProducer(registrationName="grid")

# ----------------------------------------------------------------
# Part 4: Setup the visualization in view 'renderView1'
# ----------------------------------------------------------------

# show data from grid
gridDisplay = Show(grid, renderView1, 'StructuredGridRepresentation')

# get color transfer function/color map for 'acceleration'
accelerationLUT = GetColorTransferFunction('acceleration')
accelerationLUT.Set(
    RGBPoints=GenerateRGBPoints(
        range_min=0.0,
        range_max=212825.18145290436,
    ),
    ScalarRangeInitialized=1.0,
)

# Set the transfer function to be used in displaying the data
gridDisplay.Set(
    Representation='Surface',
    ColorArrayName=['POINTS', 'acceleration'],
    LookupTable=accelerationLUT,
    Assembly='Hierarchy',
)

# ----------------------------------------------------------------
# Part 5: Setup the color legend parameters for this view
# ----------------------------------------------------------------

# get color legend/bar for accelerationLUT in view renderView1
accelerationLUTColorBar = GetScalarBar(accelerationLUT, renderView1)
accelerationLUTColorBar.Set(
    Title='acceleration',
    ComponentTitle='Magnitude',
)

# set color bar visibility
accelerationLUTColorBar.Visibility = 1

# show color legend
gridDisplay.SetScalarBarVisibility(renderView1, True)

# ----------------------------------------------------------------
# Part 6: Create an image extractor
# ----------------------------------------------------------------

# create extractor
pNG1 = CreateExtractor('PNG', renderView1, registrationName='PNG1')
# trace defaults for the extractor.
# init the 'PNG' selected for 'Writer'
pNG1.Writer.Set(
    FileName='RenderView1_{timestep:06d}.png',
    ImageResolution=[1477, 870],
    Format='PNG',
)

This case is a bit more complex than those used in the previous blogs since we need to specify how the information should be rendered.  Let’s examine each part of the script.

Part 1: Set Catalyst options

Similar to the examples in the previous blogs, this section defines the image write frequency and storage location.

Part 2: Setup the view to be used in the visualization

To generate images, we must first create a render view, defining its size and camera parameters. ParaView automatically resets the camera when displaying data; therefore, we need to disable this feature to establish a specific view.

Several settings are straightforward, such as view size, camera position, focal point, and view-up direction. ParaView can assist in saving these details. For more information on VTK’s camera model, refer to here.

Part 3: Create the producer for the grid channel

Identical to the examples in the previous blogs, we need to create a producer for the Catalyst channel named grid.

Part 4: Setup the visualization in the created view

In this section, we begin by instructing the newly created view to display the simulation data received from Catalyst, which we call the visual representation of the data. Next, we generate the transfer function responsible for coloring the data. This function will determine color based on the acceleration magnitude values at each grid node. Finally, we apply this transfer function to the visual representation.

Part 5: Setup the color legend parameters for this view

This section will add a color legend to the images we generate.

Part 6: Create an image extractor

Here, an extractor is configured to produce PNG images instead of VTPD geometry files that we generated in the previous blog. We also define the image resolution, matching the view size, and establish a naming pattern for the generated files. In this case, all files will begin with “RenderView1_” followed by a six-digit number representing the simulation timestep.

Below is a video that was generated using the above script and assembling the resulting images.

Animation showing the acceleration magnitude of a LULESH simulation using ParaView Catalyst.

Want to Go Deeper?

This guide focused on writing Catalyst scripts by hand, but there’s much more you can do:

  • Want to instrument your own simulation to work with Catalyst? Start here.
  • Prefer a visual approach? You can use ParaView’s GUI to design pipelines and export them as Catalyst scripts—no manual coding required. Learn how to here.

ParaView Catalyst isn’t just about saving time—it’s about making better decisions, faster. Whether you’re monitoring early results or guiding your simulation interactively, Catalyst helps you stay in control, ultimately leading to improved decision-making and accelerated progress.

Need help integrating ParaView Catalyst into your code? Kitware brings decades of expertise in scientific visualization and simulation. Contact our team to discover how we can help you fully leverage ParaView Catalyst.

Leave a Reply