Author Topic: Scripting Every Nth frame  (Read 639 times)

tabedzki

  • Newbie
  • *
  • Posts: 8
Scripting Every Nth frame
« on: September 06, 2018, 05:19:11 PM »
Sorry if this was mentioned somewhere in the documentation but I had trouble finding it. Is there a way to, via scripting, only render every Nth frame (say 5) when exporting to a gif? I have tried different methods but they either render one frame or all frames. What would be the line to add to the script to get it done.

Thanks in advance

Alexander Stukowski

  • Administrator
  • Hero Member
  • *****
  • Posts: 500
Re: Scripting Every Nth frame
« Reply #1 on: September 06, 2018, 06:34:20 PM »
Hi,

The answer depends on which version of OVITO you are using. In the old 2.9.0 release, there has been an undocumented parameter in the RenderSettings class, which you can set, e.g.

Code: [Select]
render_settings.everyNthFrame = 5

If you already switched to OVITO 3.0.0-dev, the new Viewport.render_anim() method provides the every_nth keyword parameter.

-Alex

tabedzki

  • Newbie
  • *
  • Posts: 8
Re: Scripting Every Nth frame
« Reply #2 on: September 07, 2018, 04:52:48 AM »
That got it working; thank you, Alex!

Two other questions (for OVITOS 2.9.0):
1) When I rendered it using the below script, the first image came out very small and then the other frame I was interested in came out normally. Do you know what might be causing that?
2) How do I include the [SourceFrame] as a text overlay in the bottom right hand corner?

Thanks again!
-Tabedzki

Code: [Select]
#!/usr/bin/env python
from ovito import dataset
from ovito.io import import_file
from ovito.modifiers import SelectExpressionModifier
from ovito.modifiers import SliceModifier
from ovito.vis import Viewport
from ovito.vis import RenderSettings
from ovito.vis import TachyonRenderer
from ovito.vis import OpenGLRenderer
from ovito.modifiers import PythonScriptModifier
from ovito.data import ParticleProperty
import os
from ovito.vis import *
from math import *

# def frame_write(frame,input, output):


def main(lammpstrj_path, gif_path):
    vs = Viewport()
    print("Input file: ", lammpstrj_path)
    print("Output file:", gif_path)
    node = import_file(lammpstrj_path, multiple_frames = True)
    node.add_to_scene()
    vp = dataset.viewports.viewports[0]
    os.makedirs(os.path.dirname(gif_path), exist_ok=True)
    settings = RenderSettings(
        filename = gif_path,
        size = (800, 600),
        range = RenderSettings.Range.ANIMATION,
        # range = RenderSettings.Range.CUSTOM_INTERVAL,
        # custom_range = (50, 100, 5),
        # frames_per_second = 1,
        everyNthFrame = 25,
        renderer = OpenGLRenderer(),
        # renderer = TachyonRenderer(),
    )
    vp.render(settings)

if __name__ == '__main__':
    import sys
    usage = "Usage: {} lammpstrj_path".format(sys.argv[0])
    n_args = len(sys.argv[1:])
    if n_args < 1:
        print(usage)
    else:
        lammpstrj_path = os.path.abspath(sys.argv[1])
        gif_path = (
            lammpstrj_path
            .replace('.lammpstrj', '.gif')
        )
        main(lammpstrj_path, gif_path)

Alexander Stukowski

  • Administrator
  • Hero Member
  • *****
  • Posts: 500
Re: Scripting Every Nth frame
« Reply #3 on: September 07, 2018, 09:11:06 AM »
1)

Probably this is due to a bug in the old OVITO version, see this discussion thread:

http://forum.ovito.org/index.php?topic=306.0

Maybe it helps to insert a call to Viewport.zoom_all() right before rendering the animation.

2)

See this part of the documentation:

https://ovito.org/manual/python/modules/ovito_vis.html#ovito.vis.TextLabelOverlay

In your particular case:

Code: [Select]
from ovito.vis import TextLabelOverlay
from PyQt5 import QtCor
...

overlay = TextLabelOverlay(
    text = '[SourceFrame]',
    alignment = QtCore.Qt.AlignRight ^ QtCore.Qt.AlignBottom,
    offset_y = 0.1,
    font_size = 0.03,
    text_color = (0,0,0))
vs.overlays.append(overlay)

tabedzki

  • Newbie
  • *
  • Posts: 8
Re: Scripting Every Nth frame
« Reply #4 on: September 07, 2018, 02:30:16 PM »
Awesome! Thank you so much for your support!

tabedzki

  • Newbie
  • *
  • Posts: 8
Re: Scripting Every Nth frame
« Reply #5 on: September 07, 2018, 08:53:46 PM »
Sorry. I have one last question. I want to modify the gif to have a certain fps rate, but when I run the following script, I get the corresponding error. Do you know which arguments are incompatible? and how would I modify the fps as well as modify the everyNthFrame argument in the same script?

So basically, I would want as the first frame of the gif to be Frame 0 of my visualization and have that be there for a second, then my next gif frame to be Frame 5 of the visualization with that being there for 1 second, and so on. Do you have suggestions as how to modify it?

Thanks again
Tabedzki

Code: [Select]
def main(lammpstrj_path, gif_path):
    vs = Viewport()
    print("Input file: ", lammpstrj_path)
    print("Output file:", gif_path)
    node = import_file(lammpstrj_path, multiple_frames = True)
    node.add_to_scene()
    vp = dataset.viewports.viewports[0]
    print(range(node.source.num_frames))
    os.makedirs(os.path.dirname(gif_path), exist_ok=True)
    dataset.anim.frames_per_second = 2,
    settings = RenderSettings(
        filename = gif_path,
        size = (800, 600),
        range = RenderSettings.Range.ANIMATION,
        # range = RenderSettings.Range.CUSTOM_INTERVAL,
        # custom_range = (50, 100, 5),
        # frames_per_second = 1,
        everyNthFrame = 25,
        renderer = OpenGLRenderer(),
        # renderer = TachyonRenderer(),
    )
    vp.render(settings)

Code: [Select]
Traceback (most recent call last):
  File "../../lammpstrj_to_gif.py", line 65, in <module>
    main(lammpstrj_path, gif_path)
  File "../../lammpstrj_to_gif.py", line 39, in main
    dataset.anim.frames_per_second = 2,
TypeError: (): incompatible function arguments. The following argument types are supported:
    1. (arg0: Ovito::AnimationSettings, arg1: int) -> None

Invoked with: AnimationSettings(), (2,)
ERROR: The Python script '../../lammpstrj_to_gif.py' has exited with an error.

Alexander Stukowski

  • Administrator
  • Hero Member
  • *****
  • Posts: 500
Re: Scripting Every Nth frame
« Reply #6 on: September 07, 2018, 11:21:37 PM »
This time it's not a bug in Ovito :) It's a typo in your script:

Code: [Select]
dataset.anim.frames_per_second = 2,

Remove the trailing comma at the end of the line. Python interprets this expression as a one-element tuple, not an integer value. See

https://wiki.python.org/moin/TupleSyntax

Alexander Stukowski

  • Administrator
  • Hero Member
  • *****
  • Posts: 500
Re: Scripting Every Nth frame
« Reply #7 on: September 07, 2018, 11:30:50 PM »
I think if you set everyNthFrame to render only every 5th frame, and set dataset.anim.frames_per_second=1, you should get what you want. The frames per second setting determines the playback rate of the rendered video file, irrespective of the everyNthFrame setting. So if you render fewer frames of the animation, it will appear to play faster than if you render all frames.

tabedzki

  • Newbie
  • *
  • Posts: 8
Re: Scripting Every Nth frame
« Reply #8 on: September 10, 2018, 03:27:51 PM »
Hi Dr. Stukowski,

I believe I was able to manipulate the amount of frames per second as well as the frequency of which frames are shown. However, I was unable to include the text on the gif regardless of the font size and the string (I went to large sizes and made it rely on a static string instead of '[SourceFrame]'). Do you know what might be causing this problem?

Code: [Select]
#!/usr/bin/env python

from ovito import dataset
from ovito.vis import TextLabelOverlay
from PyQt5 import QtCore
from ovito.io import import_file
from ovito.modifiers import SelectExpressionModifier
from ovito.modifiers import SliceModifier
from ovito.vis import Viewport
from ovito.vis import RenderSettings
from ovito.vis import TachyonRenderer
from ovito.vis import OpenGLRenderer
from ovito.modifiers import PythonScriptModifier
from ovito.data import ParticleProperty
import os
from ovito.vis import *
from math import *

def main(lammpstrj_path, gif_path):
    # vs = Viewport()
    print("Input file: ", lammpstrj_path)
    print("Output file:", gif_path)
    node = import_file(lammpstrj_path, multiple_frames = True)
    node.add_to_scene()
    vp = dataset.viewports.viewports[0]
    print(range(node.source.num_frames))
    os.makedirs(os.path.dirname(gif_path), exist_ok=True)
    overlay = TextLabelOverlay(
    text = 'SAMPLE TEXT',
    alignment = QtCore.Qt.AlignRight ^ QtCore.Qt.AlignBottom,
    offset_y = 0.1,
    font_size = 444.03,
    text_color = (150,150,0))
    dataset.anim.frames_per_second = 1
    settings = RenderSettings(
        filename = gif_path,
        size = (800, 600),
        range = RenderSettings.Range.ANIMATION,
        # range = RenderSettings.Range.CUSTOM_INTERVAL,
        everyNthFrame = 5,
        renderer = OpenGLRenderer(),
        # renderer = TachyonRenderer(),
    )
    vp.overlays.append(overlay)
    vp.zoom_all()
    vp.render(settings)

if __name__ == '__main__':
    import sys
    usage = "Usage: {} lammpstrj_path".format(sys.argv[0])
    n_args = len(sys.argv[1:])
    if n_args < 1:
        print(usage)
    else:
        lammpstrj_path = os.path.abspath(sys.argv[1])
        gif_path = (
            lammpstrj_path
            .replace('.lammpstrj', '.gif')
        )
        main(lammpstrj_path, gif_path)

Alexander Stukowski

  • Administrator
  • Hero Member
  • *****
  • Posts: 500
Re: Scripting Every Nth frame
« Reply #9 on: September 10, 2018, 03:39:52 PM »
I think the font size of the text label is too large in your case:

Code: [Select]
    font_size = 444.03,

Note that the font_size parameter must be specified as a fraction of the rendered image height. In your case, the resulting characters are so huge that they no longer overlap with the visible viewport region. Rather use a font_size in the range of 0.05 or so.

tabedzki

  • Newbie
  • *
  • Posts: 8
Re: Scripting Every Nth frame
« Reply #10 on: September 10, 2018, 04:30:09 PM »
That solved it! I thought it was the font height. Thank you