CFD Online Discussion Forums

CFD Online Discussion Forums (http://www.cfd-online.com/Forums/)
-   ParaView (http://www.cfd-online.com/Forums/paraview/)
-   -   pvbatch script for saving animations modifing each frame (http://www.cfd-online.com/Forums/paraview/125704-pvbatch-script-saving-animations-modifing-each-frame.html)

Gaetano October 29, 2013 13:18

pvbatch script for saving animations modifing each frame
 
Hi all.

I'd like to have your inputs on a problem that is puzzling me from days.

I want to save an animation starting from a series of vtk. Apart from the rendering of a point field, I need a line source to be superimposed. The coordinates of the two points defining the line have to be read from a text file (two points for each vtk).

I managed to create an image sequence, that is to export each single frame of my animation. Now I'd like to have only an .ogv as output of my python script.

I tried something like the script here, but I wasn't successful:

-----------------------------------------------------------
ERROR: In /root/ParaView-v4.0.1-source/ParaViewCore/ClientServerCore/Rendering/vtkPVCameraCueManipulator.cxx, line 94
vtkPVCameraCueManipulator (0x1ed8d550): No camera to animate.

./video3.sh: line 5: 25353 Segmentation fault /share/paraview-4.0.1-MESA/bin/pvbatch --use-offscreen-rendering screen3.py
-----------------------------------------------------------

Of course the error comes from the fact that I'm not animating the camera.

Another hint is here, where the suggestion is to put the rendering instructions into a "Python script to be called on every timestep" using the "Python Animation Cue". Nonetheless I couldn't find any reference/example on internet.

Any suggestion?

PS: the rendering instructions are those I could register using the GUI tracing tool
PPS: I'm using Paraview 4.0.1 with MESA support on a Linux machine

Gaetano October 30, 2013 06:31

Minimal script
 
Just to give some more background, here's a minimal version of my script:

Code:

import math
try: paraview.simple
except: from paraview.simple import *
paraview.simple._DisableFirstRenderCameraReset()

# number of frames
frames = 121
# time difference between steps (needed for reconstruct filenames)
step = 0.05

# List containing the x and y coordinates of the two points
pos = [[] for i in range(frames)]
i=0

# Filename containing the coordinates in the following format:
# time x_top y_top x_bottom y_bottom
# 0.12 0.123456 0.123456 0.123456 0.123456
# ...
in_file = open("/home/project/simulation/points.out","r")

# Loop through lines in file
for line in in_file:
  [time,xt,yt,xb,yb] = line.rsplit(' ',5)
  # Store the coordinate in a 2D list
  pos[i] = [float(xt), float(yt), float(xb), float(yb)]
  i = i+1
in_file.close()

for i in range(frames):
  # Read file
  file = "/home/project/simulation/VTK/sim_" + str(int(i*step*1000)) + ".vtk"
  reader = LegacyVTKReader( FileNames=file )

  RenderView1 = GetRenderView()

  Slice1 = Slice( SliceType="Plane" )
  Slice1.SliceOffsetValues = [0.0]
  Slice1.SliceType = "Plane"
  Slice1.SliceType.Origin = [0.0, 0.0, 0.0]
  Slice1.SliceType.Normal = [0.0, 0.0, 1.0]

  DataRepresentation1 = Show()
  DataRepresentation1.ScaleFactor = 0.05
  DataRepresentation1.SelectionPointFieldDataArrayName = 'U'
  DataRepresentation1.EdgeColor = [0.0, 0.0, 0.5]
  a1_U_PVLookupTable = GetLookupTableForArray( "U", 3, RGBPoints=[0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0], VectorMode='Magnitude', NanColor=[0.5, 0.5, 0.5], ColorSpace='HSV', ScalarRangeInitialized=1.0, LockScalarRange=1 )
  a1_U_PiecewiseFunction = CreatePiecewiseFunction( Points=[0.0, 0.0, 0.5, 0.0, 1.0, 1.0, 0.5, 0.0] )
  DataRepresentation1.ColorArrayName = 'U'
  DataRepresentation1.LookupTable = a1_U_PVLookupTable

  Line1 = Line()
  Line1.Point1 = [ pos[i][0], pos[i][1], 0.0]
  Line1.Point2 = [ pos[i][2], pos[i][3], 0.0]

  DataRepresentation2 = Show()
  DataRepresentation2.ScaleFactor = 0.02
  DataRepresentation2.SelectionPointFieldDataArrayName = 'Texture Coordinates'
  DataRepresentation2.EdgeColor = [0.0, 0.0, 0.5]
  DataRepresentation2.LineWidth = 3.0

  RenderView1.ResetCamera()
  RenderView1.CenterAxesVisibility = 0
  RenderView1.OrientationAxesVisibility = 1
  RenderView1.ViewSize = [ 2400, 2400 ]

  ScalarBarWidgetRepresentation1 = CreateScalarBar( ComponentTitle='', Title='U', Enabled=1, LabelFontSize=12, LookupTable=a1_U_PVLookupTable, TitleFontSize=12, Position=[0.9, 0.25] )
  GetRenderView().Representations.append(ScalarBarWidgetRepresentation1)

  WriteImage('/home/project/frames/video' + str(int(i*step*1000)) + '.png')

  # Memory saving?
  Delete(reader)
  Delete(Slice1)
  Delete(Threshold1)
  Delete(Contour1)
  Delete(Line1)

It basically built each frame from scratch and save it as png. I know that it looks horrible, but I'm a beginner in both python programming and paraview scripting.

Is there a way to save an .ogv starting from those frames?

Any comments on the script are extremely welcome! :D

wyldckat November 2, 2013 17:09

Greetings Gaetano,

:eek: Wow, that's some heavy duty coding you want to perform! And for pvbatch, to top it off!

Personally, I prefer to use GUI first for testing. And ParaView has got a marvellous feature in the "Tools" menu, namely "Start/Stop Trace". This allows us to register most of the commands we executed graphically and when we stop tracing, we get a script which most of the times gives a good code to start with. Problem is when it doesn't give us all of the code we need :(

But in this case, I did a quick test, and the following pearls of wisdom it gave me were (with ParaView 3.12.0):
  1. We can load a timeline of VTK files with something like this:
    Code:

    cavity_ = LegacyVTKReader( FileNames=['/home/user/mycase/cavity_0.vtk', '/home/user/mycase/cavity_20.vtk', '/home/user/mycase/cavity_40.vtk', '/home/user/mycase/cavity_60.vtk', '/home/user/mycase/cavity_80.vtk', '/home/user/mycase/cavity_100.vtk'] )
  2. We can switch to another time frame by using this code:
    Code:

    AnimationScene1 = GetAnimationScene()
    AnimationScene1.EndTime = 5.0
    AnimationScene1.PlayMode = 'Snap To TimeSteps'
    AnimationScene1.AnimationTime = 2.0

    RenderView1 = GetRenderView()
    RenderView1.ViewTime = 2.0

    where 2.0 is the frame (time) I wanted. It will load up the respective data from the VTK file automatically.
  3. The embedded code to be executed on each time frame is done like this:
    Code:

    PythonAnimationCue1 = PythonAnimationCue( Script='def start_cue(self): pass\n\ndef tick(self): pass\n\nprint(self)\n\ndef end_cue(self): pass' )
As for coding the cue code, the best I can provide is the example I wrote some time ago here: http://www.cfd-online.com/Forums/ope...tml#post446333 post #6.


As for saving to OGV... on ParaView 4.0.1 I got this from the Python trace feature:
Quote:

WriteAnimation('/home/user/mycase/test.ogv', Magnification=1, Quality=2, FrameRate=15.000000)
Best regards,
Bruno

Gaetano November 4, 2013 13:08

Quote:

Originally Posted by wyldckat (Post 460276)
Personally, I prefer to use GUI first for testing. And ParaView has got a marvellous feature in the "Tools" menu, namely "Start/Stop Trace".

I know: all the code above was a modification of the output of the trace tool (first Post Scriptum in my first message). :p

Quote:

We can switch to another time frame by using this code:
Code:

AnimationScene1 = GetAnimationScene()
AnimationScene1.EndTime = 5.0
AnimationScene1.PlayMode = 'Snap To TimeSteps'
AnimationScene1.AnimationTime = 2.0

RenderView1 = GetRenderView()
RenderView1.ViewTime = 2.0

where 2.0 is the frame (time) I wanted. It will load up the respective data from the VTK file automatically.
Here's how to move between frames, at least! But actually the definitive hint is:

Quote:

The embedded code to be executed on each time frame is done like this:
Code:

PythonAnimationCue1 = PythonAnimationCue( Script='def start_cue(self): pass\n\ndef tick(self): pass\n\nprint(self)\n\ndef end_cue(self): pass' )

Eventually, I managed to create the video I wanted. I used also the minimal script I found here: it told me how to use that "PythonAnimationCue".

For future reference (and my 2 cents for the community), here's how I did it:

Code:

try: paraview.simple
except: from paraview.simple import *
paraview.simple._DisableFirstRenderCameraReset()

# number of frames
frames = 121
# time difference between steps (needed for reconstruct filenames)
step = 0.05

AnimationScene1 = GetAnimationScene()
AnimationScene1.EndTime = frames-1
AnimationScene1.PlayMode = 'Snap To TimeSteps'

RenderView1 = GetRenderView()


# List containing the x and y coordinates of the two points
pos = [[] for i in range(frames)]

# Filename containing the coordinates in the following format:
# time x_top y_top x_bottom y_bottom
# 0.12 0.123456 0.123456 0.123456 0.123456
# ...
in_file = open("/home/project/simulation/points.out","r")

# Loop through lines in file
i=0
for line in in_file:
  [time,xt,yt,xb,yb] = line.rsplit(' ',5)
  # Store the coordinate in a 2D list
  pos[i] = [float(xt), float(yt), float(xb), float(yb)]
  i = i+1
in_file.close()

for i in range(frames):
  # Read file
  file = "/home/project/simulation/VTK/sim_" + str(int(i*step*1000)) + ".vtk"
  files.append(file)

reader = LegacyVTKReader( FileNames=files )

Slice1 = Slice( SliceType="Plane" )
Slice1.SliceOffsetValues = [0.0]
Slice1.SliceType = "Plane"
Slice1.SliceType.Origin = [0.0, 0.0, 0.0]
Slice1.SliceType.Normal = [0.0, 0.0, 1.0]

DataRepresentation1 = Show()
DataRepresentation1.ScaleFactor = 0.05
DataRepresentation1.SelectionPointFieldDataArrayName = 'U'
DataRepresentation1.EdgeColor = [0.0, 0.0, 0.5]
a1_U_PVLookupTable = GetLookupTableForArray( "U", 3, RGBPoints=[0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0], VectorMode='Magnitude', NanColor=[0.5, 0.5, 0.5], ColorSpace='HSV', ScalarRangeInitialized=1.0, LockScalarRange=1 )
a1_U_PiecewiseFunction = CreatePiecewiseFunction( Points=[0.0, 0.0, 0.5, 0.0, 1.0, 1.0, 0.5, 0.0] )
DataRepresentation1.ColorArrayName = 'U'
DataRepresentation1.LookupTable = a1_U_PVLookupTable

Line1 = Line()

RenderView1.ResetCamera()

ScalarBarWidgetRepresentation1 = CreateScalarBar( ComponentTitle='', Title='U', Enabled=1, LabelFontSize=12, LookupTable=a1_U_PVLookupTable, TitleFontSize=12, Position=[0.9, 0.25] )
GetRenderView().Representations.append(ScalarBarWidgetRepresentation1)

PythonAnimationCue1 = PythonAnimationCue()
PythonAnimationCue1.Script= """
def start_cue(self): pass

def tick(self):

  i = int(GetAnimationScene().TimeKeeper.Time)

  RenderView1.ViewTime = i
  AnimationScene1.AnimationTime = i

  Line1 = FindSource("Line1")

  Line1.UpdatePipeline(GetAnimationScene().TimeKeeper.Time)

  Line1.Point1 = [ pos[i][0], pos[i][1], 0.0]
  Line1.Point2 = [ pos[i][2], pos[i][3], 0.0]

  DataRepresentation2 = Show()
  DataRepresentation2.ScaleFactor = 0.02
  DataRepresentation2.SelectionPointFieldDataArrayName = 'Texture Coordinates'
  DataRepresentation2.EdgeColor = [0.0, 0.0, 0.5]
  DataRepresentation2.LineWidth = 3.0

def end_cue(self): pass
"""

AnimationScene1.Cues.append(PythonAnimationCue1)

RenderView1.CenterAxesVisibility = 0
RenderView1.OrientationAxesVisibility = 1
RenderView1.ViewSize = [ 2400, 2400 ]

WriteAnimation('/home/project/frames/video.ogv', Magnification=1, Quality=2, FrameRate=8.0)

Thanks Bruno: you really made my day!

Regards,
Gaetano

Gaetano January 30, 2014 06:42

Errata corrige: my script seems to put the line at the previous instant into the current instant photogram. There is still something wrong, so be careful if you're going to use it.

Regards,
Gaetano


All times are GMT -4. The time now is 10:27.