10. Annotations

Explicit labeling and annotation of particular data values is often an important element in data visualization and analysis. ParaView provides a variety of mechanisms to enable annotation in renderings ranging from free floating text rendered alongside other visual elements in the render view to data values associated with particular points or cells.

10.1. Annotation sources

Several types of text annotations can be added through the Sources > Alphabetical menu. Text from these sources is drawn on top of 3D elements in the render view. All annotation sources share some common properties under the Display section of the Properties panel. These include Font Properties such as the font to use, the size of the text, its color, opacity, and justification, as well as text effects to apply such as making it bold, italic, or shadowed.

../_images/FontProperties.png

Fig. 10.1 Font property controls in annotation sources and filters.

There are three fonts available in ParaView: Arial, Courier, and Times. You can also supply an arbitrary TrueType font file (*.ttf) to use by selecting the File entry in the popup menu under Font Properties and clicking on the ... button to the right of the font file text field. A file selection dialog will appear letting you choose a font file from the file system on which paraview (or pvpython) is running.

The remaining display properties control where the text is placed in the render view. There are two modes for placement, one that uses predefined positions relative to the render view, and one that enables arbitrary interactive placement in the render view. The first mode is active when the Use Window Location checkbox is selected. It enables the annotation to be placed in one of the four corners of the render view or centered horizontally at the top or bottom of the render view. Buttons with icons representing the location are shown in the Pipeline browser. These buttons correspond to locations in the render view as depicted in Fig. 10.2.

../_images/AnnotationLocations.png

Fig. 10.2 Annotation placement buttons and where they place the annotation.

The second mode, activated by clicking the Lower Left Corner checkbox, lets you arbitrarily place the annotation. If the Interactivity property is enabled, you can click and drag the annotation in the render view to place it, or you can manually enter a location where the lower left corner of the annotation’s bounding box should be placed. The coordinates are defined in terms of fractional coordinates that range from [0, 1] in the x and y dimensions. The coordinate system of the render view has a lower left origin, so a Lower Left Corner value of [0, 0] will place the annotation in the lower left corner of the render view.

10.1.1. Text source

The Text source enables you to add a text annotation in the render view. It has one property defining what text is displayed. Text can be multiline, and it can contain numbers and unicode characters. Text may also contain Mathtex expressions between starting and ending dollar signs. Mathtext expressions are a subset of TeX math expressions [dt] . When Mathtext is used, the text can only be on a single line.

../_images/TextSource.png

Fig. 10.3 An example of the Text source annotation in the upper left corner with a math expression rendered from a Mathtext [dt] expression.

10.1.2. Annotate Time source

The Annotate Time source is nearly identical to the Text source, but it also offers access to the current time value set in ParaView. Control over the format of the time display is available through the Format property. This property takes a string with optional formatting sections understood by the fmt library. By default, the value is “Time: {time:f}” where the “time” term inside the curly braces is replaced with ParaView’s current time value, and the “:f” specifies that it should be formatted as a float with six decimal digits. For other formatting possibilities, please see the fmt syntax description at https://fmt.dev/latest/syntax.html. Examples are near the bottom of that page.

10.2. Annotation filters

The annotation sources described in the previous section are available for adding text annotations that do not depend on any loaded datasets. To create annotations that show values from an available data source in the Pipeline Browser , several annotation filters are available. The properties available to change the text font and annotation location are exactly the same as those available for the annotation sources described in the previous section.

10.2.1. Annotate Attribute Data filter

The Annotate Attribute Data makes it possible to create an annotation with a data value from an array (or attribute) in a dataset. To use the filter, first select the data array with the data of interest in the Select Input Array . These arrays may be point, cell, or field data arrays. The Element Id property specifies the index of the point or cell whose value should be shown in the annotation. If the selected input array is a field array (not associated with points or cells), the Element Id specifies the tuple of the array to show. When running in parallel, the Process Id denotes the process that holds the array from which the value should be obtained.

../_images/AnnotateAttributeData.png

Fig. 10.4 Properties of the Annotate Attribute Data filter.

The Prefix text property precedes the attribute value in the rendered annotation. There is no formatting string - the number is appended after the prefix. If the array value selected is a scalar value, the annotation will contain just the number. On the other hand, if the array value is from a multicomponent array, the individual components will be added to the annotation label in a space-separated list that is surrounded by parentheses.

10.2.2. Annotate Global Data filter

Some file formats include the concept of global data, a single data value stored in the data array for each time step. ParaView stores the set of such data values as a field data array associated with the dataset with the same number of values as timesteps. To display these global values in the render view, use the Annotate Global Data filter. The Select Arrays popup menu shows the available field data arrays. The Prefix and Suffix properties come before and after the data value in the annotation, respectively. The Format property is a C language number format specifier as you would use in a printf function call. The filter will provide a warning if the format is invalid for the global data type.

10.2.3. Annotate Time Filter

A nice feature of ParaView is that it supports data sources that produce different data at different times. Examples include file readers that read in data for a requested time step and certain temporal filters. Each data source advertises to ParaView the time values for which it can produce data. The data produced and displayed in ParaView depends on the time you set in the ParaView VCR Controls or Time Inspector panel.

What is even nicer is that you can have several data sources that each advertise and respond to a possibly unique set of times. That is, available sources do not need to advertise that they support the same set of time points - in fact, they may define data at entirely different time points. Given a requested time, each data source will produce the data corresponding to the time it supports closest to the requested time. This features makes it possible to create animations from multiple datasets varying at different time resolutions, for instance.

While the Annotate Time source described earlier can be used to display ParaView’s currently requested time, it does not show the time value to which a particular data source is responding. For example ParaView may be requesting data for time 5.0, but if a source produces data for time values 10.0 and above, it will produce the data for time 10.0, even though time 5.0 was requested. To show the time for which a data source is producing data, you can instead use the Annotate Time Filter . Simply attach it to the source of interest. If several data sources are present, a separate instance of this filter may be attached to each one.

Control over the format of the time display is available through the Format property. The format string is a string supported by the fmt library and defaults to “Time: {time:f}” where the “time” string inside the curly braces is replaced by the currently loaded time value of the data source to which this filter is attached. This filter also includes Shift and Scale properties used to linearly transform the displayed time. The time value is first multiplied by the scale and then the shift is then added to it.

10.2.4. Environment Annotation filter

If you want to display information about the environment in which a visualization was generated, use the Environment Annotation filter. By attaching this filter to a data source, you can have it automatically display your user name on the system running ParaView, show which operating system was used to generate it, present the date and time when the visualization was generated, and show the file name of the source data if applicable. Each of these items can be enabled or disabled by checkboxes in the Properties panel for this filter.

If the input source for this filter is a file reader, the File Name property is initialized to the name of the file. A checkbox labeled Display Full Path is available to show the full path of the file, but if unchecked, only the file name will be displayed. This default file path can be overridden by changing the text in the File Name property. If this filter is attached to a filter instead of a reader, the file path will be initialized to an empty string. It can be changed to the original file name manually, or an arbitrary string if so desired.

10.2.5. Python Annotation filter

The most versatile annotation filter, the Python Annotation filter, offers the most general way of generating annotations that include information about the dataset. Values from point, cell, field, and row data arrays may be accessed and combined with mathematical operations in a short Python expression defined in the Expression property. The type of data arrays available for use in the Expression is set with the Array Association property.

Before going further, let’s look at an example of how to use the Python Annotation filter. Assume you want to show a data value at from a point array named Pressure at point index 22. First, set the Array Association to Point Data to ensure point data arrays can be referenced in the Python annotation expression. To show the pressure value at point 22, set the Expression property to

Pressure[22]
../_images/PythonAnnotationSimple.png

Fig. 10.5 An example of a basic Python Annotation filter showing the value of the Pressure array at point 22.

You can augment the Python expression to give the annotation more meaning. To add a prefix, set the Expression to

'Pressure: %f' % (Pressure[22])

noindent All data arrays in the chosen association are provided as variables that can be referenced in the expression as long as their names are valid Python variables. Array names that are invalid Python variable names are available through a modified version of the array name. This sanitized version of the array name consists of the subset of characters in the array name that are letters, numbers, or underscore (_) joined together without spaces in the order in which they appear in the original array name. For example, an array named Velocity X will be made available in the variable VelocityX .

Point and cell data in composite datasets such as multiblock datasets is accessed somewhat differently than point or cell data in non-composite datasets. The expression

Pressure[22]

retrieves a single scalar value from a point array in a non-composite dataset, the same expression retrieves the 22nd element of the Pressure array in each block. These values are held in a VTKCompositeDataArray, which is a data structure that holds arrays associated with each block in the dataset. Hence, when the expression

Pressure[22]

is evaluated on a composite dataset, the value returned and displayed is actually an assemblage of array values from each block. To access the value from a single block, the array from that block must be selected from the Arrays member of the result VTKCompositeDataArray. To show the Pressure value associated with 22nd point of block 2, for example, set the expression to

Pressure[22].Arrays[2]

This expression yields a single data value in the rendered annotation, assuming that the Pressure array has a single component. To show a range of array values, use a Python range expression in the index into the Pressure field, e.g.,

Pressure[22:24].Arrays[2]

This will show the Pressure values for points 22 and 23 from block 2. You can also retrieve more than one array using an index range on the Arrays member, e.g.,

Pressure[22:24].Arrays[2:5]

This expression evaluates to Pressure for points 22 and 23 for blocks 2, 3, and 4.

The Array Association is really a convenience to make the set of data arrays of the given association available as variables that can be used in the Expression . The downside of using these array names is that arrays from only one array association are available at a time. That means annotations that require the combination of a cell data array and point data array, for example, cannot be expressed with these convenience Python variables alone.

Fortunately, you can access any array in the input to this filter with a slightly more verbose expression. For example, the following expression multiplies a cell data value by a point data value:

inputs[0].CellData['Volume'][0] * inputs[0].PointData['Pressure'][0]

Note that the arrays in the input are accessed in the above example using their original array names.

In the example above, the expression inputs[0] refers to the first input to the filter. While this filter can take only one input, it is based on the same code used by the Python Calculator (described in Section 5.9.2), which puts its several inputs into a Python list, hence the input to the Python Annotation filter is referenced as inputs[0] .

In addition to making variables for the current array association available in the expression, this filter provides some other variables that can be useful when computing an annotation value.

  • points : Point locations (available for datasets with explicit points).

  • time_value , t_value : The current time value set in ParaView.

  • time_steps , t_steps : The number of timesteps available in the input.

  • time_range , t_range : The range of timesteps in the input.

  • time_index , t_index : The index of the current timestep in ParaView.

There are some situations where the variables above are not defined. If the input has no explicitly defined points, e.g., image data, the points variable is not defined. If the input does not define timesteps, the time_* and t_* variables are not defined.

Finally, all the capabilities of the Python Calculator, documented in Section 5.9.2,

are available, including the NumPy integration and access to the NumPy and SciPy methods.

Common Errors

The time-related variables are not needed to index into point or cell data arrays. Only the point and cell arrays loaded for the current timestep are available in the filter. You cannot access point or cell data from arbitrary timesteps from within this filter.

With the capabilities in this filter, it is possible to reproduce the other annotation sources and filters, as shown below.

  • Text source: To produce the text “My annotation”, write "My annotation"

  • Annotate Time source: To produce the equivalent of Time: {time:f}, write "Time: %f" % time_value

  • Annotate Attribute Data filter: To produce the equivalent of setting Select Input Array to EQPS, Element Id to 0 and Process Id to 0, and Prefix to Value is:, write 'Value is: %.12f' % (inputs[0].CellData['EQPS'][0]) .

  • Annotate Global Data filter: To produce the same annotation as setting Select Arrays to KE, Prefix to Value is: , Format to %7.5g, and empty suffix, write "Value is: %7.5g" % (inputs[0].FieldData['KE'].Arrays[0][time_index])

  • Annotate Time Filter : To produce the equivalent of setting Format to Time: %f, Shift to 3, and Scale to 2, write "Time: %f" % (2*time_value + 3) .

The examples above are meant to illustrate the versatility of the Python Annotation filter. Using the specialized annotation sources and filters are likely to be more convenient than entering the expressions in the examples.