Feature request: Clone renderView

I am setting up a state which holds multipe renderViews, so that I can have a batch job render all these views for a particular dataset. I often want these views to show the same scene but viewed from different angles and/or just slightly modified.
However, when creating a new renderView I have to reconfigure all display properties all over again which is tedious.
Here it would be helpful to have a “clone a renderView” option.

2 Likes

I have a similar situation and I also think “clone renderView” can be a very helpful feature, however, maybe it is possible to manipulate the saved state file and duplicating some lines, but it would be very messy.

I agree this would be a nice built-in feature, but I’ve made some macros to do this (sorry @bastian, I didn’t see your original post!).

They are not super-thoroughly tested but generally seem to do what I want.

MirrorH.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''Macro to split and mirror current view
Splits horizontally
'''

from paraview.simple import *

# Get initial view
renderView1 = GetActiveView()

# Get initial layout
layout1 = GetLayout()

# Split cell
layout1.SplitViewHorizontal(renderView1)

# Create a new 'Render View'
renderView2 = CreateView('RenderView')

# Assign to layout (needed in ParaView 5.7.0+)
pv_ver = GetParaViewVersion()
if pv_ver >= 5.7:
    AssignViewToLayout(renderView2, layout1, hint=2)

# Get sources
sources = GetSources()

# Copy view properties
for prop in renderView1.ListProperties():
    if prop == 'Representations': # representation cannot exist in two views
        continue

    propval = renderView1.GetPropertyValue(prop)
    try:
        renderView2.SetPropertyWithName(prop, propval)
    except Exception as ex:
        try:
            renderView2.SetPropertyWithName(prop, propval.GetData())
        except (AttributeError, RuntimeError):
            #print(prop, propval, type(propval))
            #print('  {}'.format(type(ex)))
            pass

# Copy representation properties
for source in sources.values():
    rep1 = GetRepresentation(proxy=source, view=renderView1)
    rep2 = GetRepresentation(proxy=source, view=renderView2)

    props = rep1.ListProperties()
    for prop in props:
        propval = rep1.GetPropertyValue(prop)

        try:
            rep2.SetPropertyWithName(prop, propval)
        except Exception as ex:
            try:
                rep2.SetPropertyWithName(prop, propval.GetData())
            except RuntimeError:
                pass

UpdateScalarBars(renderView2)

# Explicitly copy camera properties
camera_props = ['Position', 'FocalPoint', 'ViewAngle', 'ViewUp', 'ParallelProjection', 'ParallelScale']
for prop in camera_props:
    eval_str = 'renderView2.Camera{0} = renderView1.Camera{0}'.format(prop)
    exec(eval_str)

Render(renderView2)

MirrorV.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''Macro to split and mirror current view
Splits vertically
'''

from paraview.simple import *

# Get initial view
renderView1 = GetActiveView()

# Get initial layout
layout1 = GetLayout()

# Split cell
layout1.SplitViewVertical(renderView1)

# Create a new 'Render View'
renderView2 = CreateView('RenderView')

# Assign to layout (needed in ParaView 5.7.0+)
pv_ver = GetParaViewVersion()
if pv_ver >= 5.7:
    AssignViewToLayout(renderView2, layout1, hint=2)

# Get sources
sources = GetSources()

# Copy view properties
for prop in renderView1.ListProperties():
    if prop == 'Representations': # representation cannot exist in two views
        continue

    propval = renderView1.GetPropertyValue(prop)
    try:
        renderView2.SetPropertyWithName(prop, propval)
    except Exception as ex:
        try:
            renderView2.SetPropertyWithName(prop, propval.GetData())
        except (AttributeError, RuntimeError):
            #print(prop, propval, type(propval))
            #print('  {}'.format(type(ex)))
            pass

# Copy representation properties
for source in sources.values():
    rep1 = GetRepresentation(proxy=source, view=renderView1)
    rep2 = GetRepresentation(proxy=source, view=renderView2)

    props = rep1.ListProperties()
    for prop in props:
        propval = rep1.GetPropertyValue(prop)

        try:
            rep2.SetPropertyWithName(prop, propval)
        except Exception as ex:
            try:
                rep2.SetPropertyWithName(prop, propval.GetData())
            except RuntimeError:
                pass

UpdateScalarBars(renderView2)

# Explicitly copy camera properties
camera_props = ['Position', 'FocalPoint', 'ViewAngle', 'ViewUp', 'ParallelProjection', 'ParallelScale']
for prop in camera_props:
    eval_str = 'renderView2.Camera{0} = renderView1.Camera{0}'.format(prop)
    exec(eval_str)

Render(renderView2)
3 Likes

Awesome, this is what I was looking for.

The scripts seem to work well. I only found two tweaks necessary:

  • I removed UpdateScalarBars(renderView2) for this had colorbars show that were disabled in renderView1.
  • I added paraview.simple._DisableFirstRenderCameraReset() which I found is needed to make the view-cloning work without first manually changing the view via the GUI.

For convenience I merged the two scripts into one:

RenderViewCloning.py (4.1 KB)

When run in ParaView the new script defines the functions split_right() and split_down(). By calling one of these two functions one achieves the splitting of the current layout with a new renderView being created, just like your scripts did.

I added a new function clone_to_new_layout() which obviously creates a new Layout and then clones the current RenderView into this new Layout.

This script should be maintained in some GIT repository though. Is there a dedicated repository for ParaView-scripts?

This is really useful and I’m using that all the time!

I have fixed a few bugs

  • use vtkSMProxyClipboard for copying the properties (that’s what is used by the copy/paste buttons in ParaView); this should correctly handle all types of properties (among others, I get a segfault when assigning None to OSPRayMaterial)
  • support for sources with multiple output ports (using the result of GetSources() only affects the first output ports)
  • representations are only created for ports that are visible
  • the AutomaticRescaleRangeMode of color transfer functions is temporarily set to Never, preventing them from getting rescaled upon calling GetRepresentation
  • I’ve also replaced the eval call by getattr/setattr (not a bug fix, just makes me sleep better at night)
1 Like

This iteration of the script is a great improvement and I am using it all the time, too.

There is one glitch one may want to know about:

Once the RenderView is cloned, changing the Color Palette only ever affects the first RenderView and it seems to be impossible to change the Color Palette active in the clones.
So bear in mind that if you plan on changing the Color Palette, do so before cloning the RenderView.

Hi, for me this does not copy the color palette and also not the font sizes of my (text annotations).

Should we move this to “Feature request” category @cory.quammen ?

Sure. Moved.

For me it does copy the color palette (Paraview version 5.9.1)

I have added the following features:

  • clone additional lights
  • clone scalarbar properties

I no longer observe this issue in Paraview 5.9.1:

1 Like

Thank you very much. It was very useful.