Python script overlay

This viewport overlay type allows you to write a custom Python script function that can paint arbitrary text and graphics on top of images rendered by OVITO. This makes it possible to enrich a figure or a movie with additional information (e.g. a scale bar, see example below).

The Apply changes button saves the entered Python script and runs it once. Any errors that occur during the script execution are displayed in the output area below. Any text output resulting from script calls to the built-in print() function also appears here. This can be useful for debugging purposes during the development of a script. Note that during the first initialization run, the render() function defined by the script is not executed yet. However, if needed, variables and helper functions can be defined at this stage in the global scope and accessed from the render() function.

The render() script function is called by OVITO each time the viewport is repainted or when an image or movie frame is rendered. The function's first parameter is a QPainter object, which allows the render() function to paint over the three-dimensional picture rendered by OVITO by issuing arbitrary drawing commands. The second parameter, args, is a dictionary object that contains additional arguments such as the viewport being rendered, the general render settings, and the viewport's projection parameters.

The user-defined script has full access to OVITO's data model and can access viewport properties, camera and animation settings, modifiers, and data pipeline results. For more information on OVITO's Python interface and the object model, see the Scripting Reference.

Example

The following script renders a scale bar into the viewport (with a fixed length of 4 nm, as shown in the example picture). You can copy/paste the source code into the script input field and adjust the parameters in the code as needed.

from PyQt5.QtCore import *
from PyQt5.QtGui import *

# Parameters:
bar_length = 40   # Simulation units (e.g. Angstroms)
bar_color = QColor(0,0,0)
label_text = "{} nm".format(bar_length/10)
label_color = QColor(255,255,255)

# This function is called by OVITO on every viewport update.
def render(painter, **args):
	if args['is_perspective']: 
		raise Exception("This only works with non-perspective viewports.")
		
	# Compute length of bar in screen space
	screen_length = 0.5 * bar_length * painter.window().height() / args['fov']

	# Define geometry of bar in screen space
	height = 0.07 * painter.window().height()
	margin = 0.02 * painter.window().height()
	rect = QRectF(margin, margin, screen_length, height)

	# Render bar
	painter.fillRect(rect, bar_color)

	# Render text label
	font = painter.font()
	font.setPixelSize(height)
	painter.setFont(font)
	painter.setPen(QPen(label_color))
	painter.drawText(rect, Qt.AlignCenter, label_text)