# Standardizing string substitutions

**URL:** https://discourse.paraview.org/t/standardizing-string-substitutions/4719
**Category:** Development
**Tags:** proposal
**Created:** [June 30, 2020, 4:48pm UTC](https://discourse.paraview.org/t/standardizing-string-substitutions/4719 "2020-06-30T16:48:41Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![utkarsh.ayachit](https://discourse.paraview.org/user_avatar/discourse.paraview.org/utkarsh.ayachit/32/39_2.png) [@utkarsh.ayachit](https://discourse.paraview.org/u/utkarsh.ayachit)
#### Post date: [June 30, 2020, 4:48pm UTC](https://discourse.paraview.org/t/standardizing-string-substitutions/4719/1 "2020-06-30T16:48:41Z")

</div>

We have several cases in ParaView where strings (or filenames) are substituted by runtime values. e.g.

- In Chart views, we can use `${TIME}` to have it replaced with current view time.
- In AnnotationTime source, we use `%f` or other printf style format string to be substituted with time
- The newly added extract-generators support using `%t` or `%ts` to be replaced with time or timestep

Similarly (but not exactly the same), there are few other places were substitutions happen:

- the Python calculator defines `time` and `time_index` as variables to use to access current time and timestep index.
- ParaView [pvsc](https://www.paraview.org/Wiki/ParaView:Server_Configuration) server configuration files use `$varname$`.

It’s probably time to standardize these. Here’s a proposal:

We add [`fmt`](https://fmt.dev/dev/syntax.html) as a thirdparty library we depend on. `fmt` supports named arguments with format specifiers. The context defines what named variables are available. We start by defining some variables in global scope, such as username, systemname, date etc. – things that are currently available only through **EnviromentAnnotation** filter. Views/filters/sources/ will have additional variables like current-time available. We build a document that documents various scopes and variables available within each scope.

Now, for any string in the application, we transform it using `fmt` together with the variables defined the context. For example, for Chart Title that uses today’s date and current time, one can use `"Created on {TODAYS_DATE} for time {VIEW_TIME}"` The [fmt syntax](https://fmt.dev/dev/syntax.html) defines a rich set of ways to control how the values are formatted including leading 0s, text-alignment etc.

I am not too thrilled about the variable names I used in this example, but I am sure we can come up with a nice way for namespacing which is readable and succinct.

The same could apply to filenames. Writers could use formatted string substitutions to generate filenames before writing. Maybe same for readers? – this one’s tricky though. We’ll need to clearly define context for reader not include time since that doesn’t make much sense since the time is coming from the reader itself.

Thoughts? Suggestions?

---

<div class="post-metadata">

### Author: ![dcthomp](https://discourse.paraview.org/user_avatar/discourse.paraview.org/dcthomp/32/20_2.png) [@dcthomp](https://discourse.paraview.org/u/dcthomp)
#### Post date: [June 30, 2020, 5:17pm UTC](https://discourse.paraview.org/t/standardizing-string-substitutions/4719/2 "2020-06-30T17:17:14Z")

</div>

I like the idea of consistent string formatting. The cmb superbuild already has a dependency on [PEGTL](https://github.com/taocpp/PEGTL), which doesn’t do what fmt does, but would be pretty easy to use if you wanted to implement parsing string-format specifiers yourself. I mention it because it’s header-only and we have found it useful. You could imagine extending the parser to allow people to refer to field data or other data that fmt might have a hard time dealing with.

---

<div class="post-metadata">

### Author: ![wascott](https://discourse.paraview.org/letter_avatar_proxy/v4/letter/w/8e8cbc/32.png) [@wascott](https://discourse.paraview.org/u/wascott)
#### Post date: [June 30, 2020, 5:51pm UTC](https://discourse.paraview.org/t/standardizing-string-substitutions/4719/3 "2020-06-30T17:51:49Z")

</div>

From a black box user of ParaView, +1.

---

<div class="post-metadata">

### Author: ![Kenneth\_Moreland](https://discourse.paraview.org/user_avatar/discourse.paraview.org/kenneth_moreland/32/15033_2.png) [@Kenneth\_Moreland](https://discourse.paraview.org/u/Kenneth_Moreland)
#### Post date: [June 30, 2020, 7:02pm UTC](https://discourse.paraview.org/t/standardizing-string-substitutions/4719/4 "2020-06-30T19:02:47Z")

</div>

Sounds cool.

Are there thoughts to use this in the `Calculator` filter? That would help a lot for field names with spaces or hyphens.

How would this interact with parts of ParaView that use, for example, the Python interpreter, such as `Python Calculator` and the find dialog?

---

<div class="post-metadata">

### Author: ![dcthomp](https://discourse.paraview.org/user_avatar/discourse.paraview.org/dcthomp/32/20_2.png) [@dcthomp](https://discourse.paraview.org/u/dcthomp)
#### Post date: [June 30, 2020, 8:54pm UTC](https://discourse.paraview.org/t/standardizing-string-substitutions/4719/5 "2020-06-30T20:54:10Z")

</div>

> [@Kenneth\_Moreland](#):
>
> Are there thoughts to use this in the `Calculator` filter? That would help a lot for field names with spaces or hyphens.
> 
> How would this interact with parts of ParaView that use, for example, the Python interpreter, such as `Python Calculator` and the find dialog?

I think these are both orthogonal to strings for annotation/chart legends, but interesting in their own right. PEGTL sure would make a rewrite of vtkArrayCalculator a lot easier and more robust. I’d love to be able to reference global field-data in array-calculations on point/cell data.

As far as the Python Calculator, I think its string expression should continue to be as close as possible to valid python code that is fed to the interpreter. Or we should take Python out of the name. 🙂

---

<div class="post-metadata">

### Author: ![utkarsh.ayachit](https://discourse.paraview.org/user_avatar/discourse.paraview.org/utkarsh.ayachit/32/39_2.png) [@utkarsh.ayachit](https://discourse.paraview.org/u/utkarsh.ayachit)
#### Post date: [June 30, 2020, 11:04pm UTC](https://discourse.paraview.org/t/standardizing-string-substitutions/4719/6 "2020-06-30T23:04:48Z")

</div>

maybe even more tangential, it’s probably worthwhile to revisit vtkArrayCalculator. Several libraries [now exist](https://github.com/ArashPartow/math-parser-benchmark-project) that we may be able to leverage easily.

---

<div class="post-metadata">

### Author: ![dcthomp](https://discourse.paraview.org/user_avatar/discourse.paraview.org/dcthomp/32/20_2.png) [@dcthomp](https://discourse.paraview.org/u/dcthomp)
#### Post date: [July 1, 2020, 12:04pm UTC](https://discourse.paraview.org/t/standardizing-string-substitutions/4719/7 "2020-07-01T12:04:16Z")

</div>

> [@utkarsh.ayachit](#):
>
> … it’s probably worthwhile to revisit vtkArrayCalculator. …

Another math-parsing library we’ve been pointed at recently is [METL](https://github.com/TillHeinzel/METL) which is based on PEGTL and looks pretty interesting.

---

<div class="post-metadata">

### Author: ![utkarsh.ayachit](https://discourse.paraview.org/user_avatar/discourse.paraview.org/utkarsh.ayachit/32/39_2.png) [@utkarsh.ayachit](https://discourse.paraview.org/u/utkarsh.ayachit)
#### Post date: [July 3, 2020, 5:36pm UTC](https://discourse.paraview.org/t/standardizing-string-substitutions/4719/8 "2020-07-03T17:36:10Z")

</div>

Going back to the string formatting topic and without explicitly discussing which library to use, here’s a proposal:

- We add a new type of domain (or hint) which can be added to string-vector-properties that indicates to the application that the value is a formattable string. This avoids weird scenarios where we end up formatting array names and such.
- Such property values can contain “replacement fields” surrounded by curly braces `{}` . Anything that is not contained in braces is considered literal text, which is copied unchanged to the output. If you need to include a brace character in the literal text, it can be escaped by doubling: `{{` and `}}` .
- Supported field names are defined is named context maps/dictionaries and can be referenced as `{context_name[key]}`, for example `{GLOBALS[username]}` gets replaced by username during execution.
- Predefined named contexts available are `GLOBALS` and `ENV`. Individual processing objects, such as the TimeToTextFilter or ChartView, can define additional context maps. `GLOBALS` gets populated when the process is launched and will include things like username, system name, current date, etc. `ENV` provides access to environment variables. Note, these don’t change over the lifetime of the process. This is crucial since that helps us implement a solution that works with any vtkObject-subclass that simply takes in character strings. The format substitution is handled by ParaView before calling the `Set..(const char*..)` method on the vtkObject-subclass when updating the property value.
- Specific sources/filters/views may provide additional named contexts. For example, Chart View may define a named context called `VIEW` with items like ‘time’. The format substitution happens every time the view renders. Thus for a title with time, one can use something like `Plot for time {VIEW[time]}`. Extract Generators, similarly, define a context that allows users to use time or timestep-index in format strings when specifying output filenames.
- To make things simpler, one can skip the name of the context object i.e. instead of using `{VIEW[time]}` one can just write `{time}`. In that case, the named contexts are evaluated in a predetermined order: starting with the local, vtkObject-specific, context map such as `VIEW`, then `GLOBALS` and finally `ENV`.

By design there is no data-dependent variables except if defined specifically by a vtkObject-subclass. For example, if one wants something that converts data array values to strings with formatting, one has to write that as a filter, providing a local context-map for accessing input data variables. This helps us explicitly define when the substitutions happen – in this case, since it’s a filter, that will happen anytime the filter re-executes.

---

<div class="post-metadata">

### Author: ![Kenneth\_Moreland](https://discourse.paraview.org/user_avatar/discourse.paraview.org/kenneth_moreland/32/15033_2.png) [@Kenneth\_Moreland](https://discourse.paraview.org/u/Kenneth_Moreland)
#### Post date: [July 4, 2020, 2:06pm UTC](https://discourse.paraview.org/t/standardizing-string-substitutions/4719/9 "2020-07-04T14:06:02Z")

</div>

I like these ideas very much.

One question about. For contexts provided by objects (i.e. sources/filters/views), how to you determine which instance is being referred to? For example, it is common to have multiple views. In that case, how do you resolve something like `{VIEW[foo]}` assuming both views provide a `foo` variable?

---

<div class="post-metadata">

### Author: ![utkarsh.ayachit](https://discourse.paraview.org/user_avatar/discourse.paraview.org/utkarsh.ayachit/32/39_2.png) [@utkarsh.ayachit](https://discourse.paraview.org/u/utkarsh.ayachit)
#### Post date: [July 4, 2020, 9:36pm UTC](https://discourse.paraview.org/t/standardizing-string-substitutions/4719/10 "2020-07-04T21:36:32Z")

</div>

> [@Kenneth\_Moreland](#):
>
> For contexts provided by objects (i.e. sources/filters/views), how to you determine which instance is being referred to?

Such named-contexts are only available for text within the corresponding object. For example, in current ParaView, we have **Annotate Time Filter**. The **Text** property for that filter will not have access to `VIEW` at all. Only properties on a view proxy itself will have access to it. Currently, we only have potentially formattable string properties on Chart Views e.g. Chart Title, Left Axis Title etc. For these properties, _VIEW_ is clearly defined even in multi-view setups – it’s the view on which the property is being specified.

The advantage of doing so is that we have better control of when values may change and need to be re-generated. If we allowed **Annotate Time Filter** to access `VIEW`, we’ll now need to make the filter re-executed anytime the VIEW’s parameters could change which can get complicated very quickly.

---

<div class="post-metadata">

### Author: ![utkarsh.ayachit](https://discourse.paraview.org/user_avatar/discourse.paraview.org/utkarsh.ayachit/32/39_2.png) [@utkarsh.ayachit](https://discourse.paraview.org/u/utkarsh.ayachit)
#### Post date: [July 8, 2020, 5:30pm UTC](https://discourse.paraview.org/t/standardizing-string-substitutions/4719/11 "2020-07-08T17:30:53Z")

</div>

I’ve created [an issue](https://gitlab.kitware.com/paraview/paraview/-/issues/20068) to track and prioritize this proposal implementation.
