Animations from scientific data using Paraview 4.3 and python

2015-04-05
#paraview #python #ubuntu #howto

§ Create frames

This note describes usage of Paraview 4.3 (contrary to previous note with Paraview before 4.1). Some changes were made:

  • command line arguments were added to make code more reusable
  • it works with Paraview extracted from the archive (4.3.1)
  • white background must be specified manually (SetViewProperties(view, Background = [1, 1, 1]) in the code)

Script is tested under Ubuntu 14.04 with Paraview 4.3.1. Paraview was downloaded from official site and extracted to /home/bikulov/bin/ParaView-4.3.1-Linux-64bit/lib/paraview-4.3 (you have to change this line in script to your destination). State file must be prepared in the same Paraview 4.3.1 to avoid compatibility issues (or you may have errors about ColorArrayName).

Script (also available as a gist):

#!/usr/bin/env python

import os, sys
import glob, natsort, argparse

ParaviewPath="/home/bikulov/bin/ParaView-4.3.1-Linux-64bit/lib/paraview-4.3"
print("export LD_LIBRARY_PATH={ParaviewPath}:$LD_LIBRARY_PATH".format(ParaviewPath=ParaviewPath))

sys.path.append(os.path.join(ParaviewPath, "site-packages"))
sys.path.append(os.path.join(ParaviewPath, "site-packages/vtk"))
from paraview.simple import *

def main(pipeline, state, files, output):
    filenames = natsort.natsorted(files)
    servermanager.LoadState(state)
    view = servermanager.GetRenderView()
    camera = view.GetActiveCamera()
    phase = FindSource(pipeline)

    # Set white background
    SetViewProperties(view, Background = [1, 1, 1])

    try:
         os.makedirs(output)
    except:
        pass

    imgNum = 0

    for f in filenames:
        phase.FilePrefix = f
        phase.FileNameChanged()
        view.WriteImage(os.path.join(output, str(imgNum).zfill(6) + ".png"), "vtkPNGWriter", 1)
        imgNum += 1

if __name__ == "__main__":
    parser = argparse.ArgumentParser(prog="PROG", description="Draw With Paraview")
    parser.add_argument("--state", type=str, help="State file to load", default="state.pvsm")
    parser.add_argument("--pipeline", type=str, help="Pipiline name for changing file", default="data")
    parser.add_argument("--output", type=str, help="Output path for images", default="img")
    parser.add_argument("files", nargs="*", help="Files to be used in the pipeline")

    args = parser.parse_args()

    main(pipeline=args.pipeline, state=args.state, files=args.files, output=args.output)

Command line arguments explanation:

  • --state is filename with state to be loaded (File->Save State in Paraview)
  • --pipeline is the name of pipeline inside state (item in Pipeline browser, for which you want to change File Prefix)
  • --output is path to dir where images will be saved
  • files are bunch of raw binary images you whant to visualize as video

Example run (will process all *-phase.raw files in directory and save resulting images into imgtest directory):

./draw_with_paraview.py --state state.pvsm --pipeline data --output imgtest *-phase.raw

Note: you must add path to paraview libraries in LD_LIBRARY_PATH before run (script prints out this line for convenience):

export LD_LIBRARY_PATH=/home/bikulov/bin/ParaView-4.3.1-Linux-64bit/lib/paraview-4.3:$LD_LIBRARY_PATH

§ Postprocess frames

You may want to crop images in the output folder. For mp4 width and height must be divisible by two, so you may need to crop for identify them accordingly (in parallel for speed):

img=$(ls *.png|head -n 1)
width=$(($(identify -format "(%[fx:w]/2)*2" ${img})))
height=$(($(identify -format "(%[fx:h]/2)*2" ${img})))
find -name '*.png' -exec mogrify -crop "${width}x${height}+0+0" {} +

Or the same commands in one line:

img=$(ls *.png|head -n 1); width=$(($(identify -format "(%[fx:w]/2)*2" ${img}))); height=$(($(identify -format "(%[fx:h]/2)*2" ${img}))); find -name '*.png' -exec mogrify -crop "${width}x${height}+0+0" {} +

You may also need to crop images to some specific size, just use the final line:

find -name '*.png' -exec mogrify -crop <width>x<height>+<x_shift>+<y_shift> {} +

§ Create animation from the frames

Create video from images (ffmpeg no longer supported, so use avconv):

avconf -qscale 1 -r 20 -b 9600 -i %06d.png output_file.mp4