[Paraview] Learning PV internals helped by the PV-GUI and python
Jordi Campos i Miralles
jcampos at maia.ub.es
Mon Jul 2 11:59:17 EDT 2007
Hi,
I'm trying to learn about PV internals. As usual, I read and look the
source code, but thanks to Python console I'm able to play with the
learned concepts. In this message I post the way I'm doing it (including
a "tool" script), in case somebody else is interested or have some
comments.
The main steps are the following:
1. Start PV
2. Use the GUI to build the desired pipeline
3. Dump it into a Python script (using the "dump tool")
4. Analyze the script to see what is being done
5. Modify the script as desired
6. Test the script as stand-alone
7. Load the script in a running PV
The "dump tool" is an script (listed below) I've done in order to dump
the "PV session" into a python script. This way, it is possible to do
your work "using the PV GUI" or "scripting in python" mixed as you want.
For example, I applied a mask to a given dataset using the PV-GUI (with
the Calculator filter), and after I updated the script to save the
filled volume (it depended on different pipeline steps data) and to
perform the same operation on the N datasets I had (with a simple code
loop).
I don't know if it will be useful to somebody else, but for me it is
being a nice way to start to learn how PV works internally.
Regards,
jor;)i
# PV-Dump.py
# Script to be run inside Paraview:
# Menu Tools -> Python Shell, Run Script
# Afterwards, try using "help(Dump)", "Dump.proxyList()" ...
import re
class Dump:
"""Collection of 'static methods' useful to inspect a running Paraview
pipeline (dumping information to screen or Python code)."""
@staticmethod
def proxyList():
"""Prints current proxies groups and names"""
proxies = Dump.__getProxies()
for group in proxies:
print "* ", group
for name in proxies[group]:
print " - ", name, " ( ", proxies[group][name].SMProxy.GetXMLGroup(), " )"
print
@staticmethod
def allToPython( fileName=None ):
"""Prints the python code necessary to recreate the current PV session.
If a file name is provided, it is save into the file."""
import sys
if fileName:
stdoutOrig = sys.stdout
file = open( fileName, 'w')
sys.stdout = file
Dump.__scriptStart()
Dump.proxiesToPython()
Dump.__scriptEnd()
if fileName:
sys.stdout = stdoutOrig
file.close()
@staticmethod
def proxiesToPython( includeAll=False ):
"""Prints python code to create the current proxies.
By default some PV infrastructure proxies are not printed,
but if includeAll is True all of them are printed."""
proxies = Dump.__getProxies()
order = Dump.__orderProxies( proxies ) # Get proxies
# ordered by dependencies among them
for level in order:
for item in level:
(group, name) = item.split(':') # Iterate on them
wrapName = proxies[group][name].SMProxy.GetXMLName()
if includeAll or wrapName not in Dump.__HIDDENPROXIES: # Avoid defaults
Dump.proxyToPython( group, name, Dump.__niceLabel(name)) # Dump code
print
@staticmethod
def proxyToPython(group, name, varName='proxy'):
"""Prints the python code necessary to create and setup the given proxy,
using varName as the variable identifier"""
proxies = Dump.__getProxies()
proxy = proxies[group][name]
wrapGroup = proxy.SMProxy.GetXMLGroup()
wrapName = proxy.SMProxy.GetXMLName()
print ' '*54, "# ", varName # Code: create
if wrapName == "LODDisplay": # - display proxy
dispInput = Dump.__niceLabel( Dump.__proxyIdLabel( proxy.GetInput()[0] ) )
print varName +' = paraview.CreateDisplay(' \
+ dispInput +', renderM)'
else: # - other proxies
print varName +' = paraview.CreateProxy("' \
+ wrapGroup +'", "'+ wrapName +'", "' \
+ group +'", "'+ name +'")'
patternName = re.compile(' *XMLName: *(.*)')
patternValues = re.compile(' *Values: *(.*)')
patternNum = re.compile('^[-+]?[0-9.]+$')
patternHex = re.compile('^0x[0-9a-f]+$')
patternBadProp= re.compile('LightK\:')
for prop in proxy: # For each property
match = patternName.search( str(prop) )
propName = match.groups()[0]
match = patternValues.search( str(prop) ) # Get property.Values
if match:
values = match.groups()[0]
valuesArray = values.strip().split(' ')
if patternNum.match( valuesArray[0] ): # If numeric: no quote
valuesList = ', '.join( valuesArray )
elif patternHex.match( valuesArray[0] ): # If hex: fetch object
valuesArray = proxy.__getattr__("Get"+propName)()
valuesList = ', '.join( Dump.__niceLabel( Dump.__proxyIdLabel(p) )
for p in valuesArray)
else: # If alpha: quote
valuesList = ', '.join('"' + p + '"' for p in valuesArray)
# Code: set value
if not patternBadProp.search( propName ) and \
valuesList != "none" and \
valuesList != '""':
print varName +'.Set'+ propName +'( '+ valuesList +' )'
else: # Code: comment
print '# '+ varName +'.Set'+ propName +'( '+ valuesList +' )'
#else:
# print '# '+ varName +'.'+ propName +': no match for Values'
print varName +'.UpdateVTKObjects()'
print
# Private -----------------------------------------------
__HIDDENPROXIES = [ "Manipulators", "InteractorStyle", "TrackballZoom",
"PVAnimationScene", "TimeKeeper", "ElementInspectorView",
"LODRenderModule", "MultiViewRenderModule" ]
@staticmethod
def __getProxies():
"""Returns the list of proxies in the current connection"""
proxies = paraview.pyProxyManager().GetProxiesOnConnection( \
paraview.ActiveConnection )
return proxies
@staticmethod
def __orderProxies( proxies ):
"""Returns an array, where each entry contains the names of the proxies that
depend on the previous array entry."""
patternName = re.compile(' *XMLName: *(.*)')
patternValues = re.compile(' *Values: *(.*)')
patternHex = re.compile('^0x[0-9a-f]+$')
pmanager = paraview.pyProxyManager()
dependencies = {} # COLLECT DEPS
for group in proxies: # For each proxy
for name in proxies[group]:
dependencies[group+':'+name] = {} # Init its depend.
proxy = proxies[group][name]
for prop in proxy:
match = patternName.search( str(prop) )
propName = match.groups()[0]
match = patternValues.search( str(prop) ) # Check prop. values
if match:
values = match.groups()[0]
valuesArray = values.strip().split(' ')
if patternHex.match( valuesArray[0] ): # If memory address
valuesArray = proxy.__getattr__("Get"+propName)()
for mother in valuesArray:
motherProxyVTK = mother.SMProxy
for motherGroup in proxies: # Find proxy by addr
motherName= pmanager.IsProxyInGroup( motherProxyVTK, motherGroup )
if motherName:
dependencies[group+':'+name][motherGroup+':'+motherName]=1
order = [] ; currentLevel = [] ; previousLevel = [] # ORDER DEPS
for proxy in pmanager.GetProxiesInGroup('view_modules', # Start by Views
paraview.ActiveConnection):
previousLevel.append( 'view_modules:'+ proxy )
renders = pmanager.GetProxiesInGroup("multirendermodule", # add Renderers
paraview.ActiveConnection)
for renderM in renders.keys():
previousLevel.append( 'multirendermodule:'+renderM )
order.append( previousLevel )
while len( previousLevel ) > 0: # Follow depend.
for item in previousLevel:
currentLevel.extend( dependencies[ item ].keys() )
if len(currentLevel) > 0 :order.append( currentLevel )
previousLevel = [] ; previousLevel.extend( currentLevel )
currentLevel = []
order.reverse() # First pxs w/o deps
uniqueOrder = [] ; alreadyDeclared = {} # Remove duplicates
for level in order:
newLevel = []
for item in level:
if not alreadyDeclared.get( item ):
alreadyDeclared[ item ] = True
newLevel.append( item )
uniqueOrder.append( newLevel )
return uniqueOrder
@staticmethod
def __niceLabel( label ):
"""Returns a string that can be used as var name
(starting by a letter, without .-_, ...)"""
if not label: return "none"
label = label.replace('.', '') # drop .-_
label = label.replace('-', '')
label = label.replace('_', '')
if re.compile('[A-z]1').match( label[-2:] ):
label = label[0:-1] # drop suffix '1'
if re.compile('^[0-9]').match( label ):
label = 'v' + label # add preffix when starts by number
label = label[0].lower() + label[1:] # lower 1st char
return label
@staticmethod
def __proxyIdLabel( proxy ):
"""Returns the given proxy's PV displayed name"""
proxyVTK = proxy.SMProxy
pmanager = paraview.pyProxyManager()
proxies = Dump.__getProxies()
for group in proxies:
idLabel = pmanager.IsProxyInGroup( proxyVTK, group )
if idLabel:
return idLabel
return None
@staticmethod
def __scriptStart():
print '#!/usr/local/bin/pvpython'
print '# <script>.py'
print 'import paraview'
print 'if paraview.ActiveConnection == None : CONSOLE = True'
print 'else : CONSOLE = False'
print 'if CONSOLE: # init Conn and RenderM'
print ' paraview.ActiveConnection = paraview.Connect()'
print ' renderM = paraview.CreateRenderWindow()'
print 'else:'
print ' renders = paraview.pyProxyManager().GetProxiesInGroup("multirendermodule",'
print ' paraview.ActiveConnection)'
print ' renderM = renders.values()[0].GetRenderModules()[0]'
print
@staticmethod
def __scriptEnd():
print
print 'if CONSOLE:'
print ' renderM.ResetCamera()'
print ' renderM.StillRender()'
print ' raw_input("Enter to finish")'
print ' #import time ; time.sleep(2)'
--
Jordi Campos i Miralles
Departament de Matemàtica Aplicada i Anàlisi, MAiA
Facultat de Matemàtiques, Universitat de Barcelona
Gran Via de les Corts Catalanes, 585
08007 Barcelona
Telf : +34 93 403 93 72
More information about the ParaView
mailing list