ParaView-5.0.1: Added the source-tree to ThirdParty-dev and patched as described in the README file

Resolves bug-report http://bugs.openfoam.org/view.php?id=2098
This commit is contained in:
Henry Weller
2016-05-30 21:20:56 +01:00
parent 1cce60aa78
commit eba760a6d6
24640 changed files with 6366069 additions and 0 deletions

View File

@ -0,0 +1,13 @@
include(vtkModuleMacrosPython)
# The RELATIVE make vtk_module_python_package() preserve the vtk/module package
# structure when building/installing. Otherwise, we'd just get the "web"
# package.
vtk_module_python_package(${vtk-module} "paraview/web"
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}")
# copy some default sources and proxies for ParaViewWeb
set(ParaViewPython_BINARY_DIR "${VTK_BUILD_PYTHON_MODULE_DIR}/paraview/web")
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/defaultProxies.json"
DESTINATION "${ParaViewPython_BINARY_DIR}"
USE_SOURCE_PERMISSIONS)

View File

@ -0,0 +1,49 @@
# RpcName: addRuler pv.widgets.ruler.add
# RpcName: addSource pv.pipeline.manager.proxy.add
# RpcName: clearAll pv.test.reset
# RpcName: colorBy pv.color.manager.color.by
# RpcName: connect pv.remote.connect
# RpcName: createWidgetRepresentation pv.widgets.representation.create
# RpcName: deleteSource pv.pipeline.manager.proxy.delete
# RpcName: endSelection pv.selection.end
# RpcName: exportData pv.export.data
# RpcName: getColoringInfo pv.test.color.info.get
# RpcName: getDatabase pv.data.prober.database.json
# RpcName: getDatabaseAsHTML pv.data.prober.database.html
# RpcName: getLutDataRange pv.pipeline.manager.lut.range.get
# RpcName: getPipeline pv.pipeline.manager.pipeline.get
# RpcName: getProbeData pv.data.prober.probe.data
# RpcName: getScalarBarVisibilities pv.color.manager.scalarbar.visibility.get
# RpcName: getSceneMetaData viewport.webgl.metadata
# RpcName: getWebGLData viewport.webgl.data
# RpcName: goToNext pv.data.prober.time.next
# RpcName: goToPrev pv.data.prober.time.previous
# RpcName: listColorMapNames pv.color.manager.list.preset
# RpcName: listFiles pv.files.list
# RpcName: listFilters pv.filters.list
# RpcName: listServerDirectory file.server.directory.list
# RpcName: loadData pv.data.prober.load.data
# RpcName: loadDatasets pv.data.prober.load.dataset
# RpcName: loadState pv.loader.state
# RpcName: mouseInteraction viewport.mouse.interaction
# RpcName: openFile pv.pipeline.manager.file.open
# RpcName: openFileFromPath pv.file.loader.open.file
# RpcName: openRelativeFile pv.pipeline.manager.file.ropen
# RpcName: pushState pv.pipeline.manager.proxy.update
# RpcName: pvDisconnect pv.remote.disconnect
# RpcName: reloadPipeline pv.pipeline.manager.reload
# RpcName: rescaleTransferFunction pv.color.manager.rescale.transfer.function
# RpcName: resetCamera viewport.camera.reset
# RpcName: reverseConnect pv.remote.reverse.connect
# RpcName: selectColorMap pv.color.manager.select.preset
# RpcName: setLutDataRange pv.pipeline.manager.lut.range.update
# RpcName: setScalarBarVisibilities pv.color.manager.scalarbar.visibility.set
# RpcName: startSelection pv.selection.start
# RpcName: stillRender viewport.image.render
# RpcName: updateCamera viewport.camera.update
# RpcName: updateCenterAxesVisibility viewport.axes.center.visibility.update
# RpcName: updateDisplayProperty pv.pipeline.manager.proxy.representation.update
# RpcName: updateOrientationAxesVisibility viewport.axes.orientation.visibility.update
# RpcName: updateScalarbarVisibility pv.pipeline.manager.scalarbar.visibility.update
# RpcName: updateScalarRange pv.pipeline.manager.scalar.range.rescale
# RpcName: updateTime pv.vcr.action

View File

@ -0,0 +1,34 @@
{
"sources": [
{ "name": "AnnotateTime", "label": "Annotate Time" },
{ "name": "Cone" },
{ "name": "Sphere" },
{ "name": "Text" },
{ "name": "Wavelet" }
],
"filters": [
{ "name": "Calculator" },
{ "name": "CellDatatoPointData", "label": "Cell Data To Point Data" },
{ "name": "Clip" },
{ "name": "Contour" },
{ "name": "D3" },
{ "name": "ExtractCTHParts", "label": "Extract CTH Parts" },
{ "name": "ProcessIdScalars", "label": "Process ID Scalars" },
{ "name": "Reflect" },
{ "name": "Slice" },
{ "name": "StreamTracer", "label": "Stream Tracer" },
{ "name": "Threshold" },
{ "name": "Transform" },
{ "name": "Tube" },
{ "name": "Ribbon" },
{ "name": "WarpByScalar", "label": "Warp By Scalar" },
{ "name": "WarpByVector", "label": "Warp By Vector" },
{ "name": "ExtractBlock", "label": "Extract Blocks" }
],
"readers": [
{ "name": "LegacyVTKReader", "extensions": [ "vtk" ], "method": "FileNames" },
{ "name": "Xdmf3ReaderS", "extensions": [ "xmf", "xdmf" ] }
]
}

View File

@ -0,0 +1,4 @@
vtk_module(vtkParaViewWebPython
DEPENDS
AutobahnPython
EXCLUDE_FROM_WRAPPING)

View File

@ -0,0 +1,227 @@
#--------------------------------------------------------------------------
# Handle BooleanDomain
#--------------------------------------------------------------------------
def booleanDomainDecorator(props, xmlProps, uiProps, domain):
uiProps['widget'] = 'checkbox'
uiProps['type'] = 'int'
return True
#--------------------------------------------------------------------------
# Handle EnumerationDomain
#--------------------------------------------------------------------------
def enumerationDomainDecorator(props, xmlProps, uiProps, domain):
uiProps['widget'] = 'list-1'
uiProps['type'] = 'int'
valMap = {}
for entryNum in range(domain.GetNumberOfEntries()):
valMap[domain.GetEntryText(entryNum)] = domain.GetEntryValue(entryNum)
uiProps['values'] = valMap
return True
#--------------------------------------------------------------------------
# Handle StringListDomain
#--------------------------------------------------------------------------
def stringListDomainDecorator(props, xmlProps, uiProps, domain):
uiProps['widget'] = 'list-1'
uiProps['type'] = 'str'
valuesList = []
for idx in range(domain.GetNumberOfStrings()):
valuesList.append(domain.GetString(idx))
uiProps['values'] = valuesList
return True
#--------------------------------------------------------------------------
# Handle TreeDomain
#--------------------------------------------------------------------------
def treeDomainDecorator(props, xmlProps, uiProps, domain):
uiProps['type'] = 'int'
uiProps['widget'] = 'list-n'
valMap = {}
index = 0
stack = []
stack.append([ domain.GetInformation(), [] ])
while len(stack) > 0:
me = stack.pop()
dataInformation = me[0]
accumulatedName = me[1]
if len(accumulatedName) > 1 and accumulatedName[0] == 'Element Blocks':
print index,' -> ',' + '.join(accumulatedName)
valMap[accumulatedName[-1]] = index
index += 1
infoName = None
if dataInformation:
infoName = dataInformation.GetCompositeDataClassName()
if infoName:
# May have children
info = dataInformation.GetCompositeDataInformation()
numChildren = info.GetNumberOfChildren()
if numChildren > 0:
for i in range(numChildren - 1, -1, -1):
child = info.GetDataInformation(i)
childName = info.GetName(i)
stack.append([ child, accumulatedName + [childName] ])
#valMap = { 'Block 1': 2, 'Block 2': 3 }
uiProps['values'] = valMap
return True
#--------------------------------------------------------------------------
# Handle ArrayListDomain
#--------------------------------------------------------------------------
def arrayListDomainDecorator(props, xmlProps, uiProps, domain):
uiProps['type'] = 'str'
uiProps['widget'] = 'list-1'
fieldMap = { "0": "POINTS", "1": "CELLS" }
valuesMap = {}
valuesList = []
for arnum in range(domain.GetNumberOfStrings()):
stringName = domain.GetString(arnum)
try:
assocVar = domain.GetFieldAssociation(arnum)
valuesMap[stringName] = [ fieldMap[str(assocVar)], stringName ]
except:
valuesList.append(stringName)
if len(valuesList) > 0:
uiProps['values'] = valuesList
else:
uiProps['values'] = valuesMap
return True
#--------------------------------------------------------------------------
# Handle ArraySelectionDomain
#--------------------------------------------------------------------------
def arraySelectionDomainDecorator(props, xmlProps, uiProps, domain):
uiProps['type'] = 'str'
uiProps['widget'] = 'list-n'
valuesList = []
for arnum in range(domain.GetNumberOfStrings()):
valuesList.append(domain.GetString(arnum))
uiProps['values'] = valuesList
return True
#--------------------------------------------------------------------------
# Handle IntRangeDomain, DoubleRangeDomain, and ArrayRangeDomain
#--------------------------------------------------------------------------
def numberRangeDomainDecorator(props, xmlProps, uiProps, domain):
uiProps['widget'] = 'textfield'
domainClass = domain.GetClassName()
if domainClass.rfind('Int') >= 0:
uiProps['type'] = 'int'
else:
uiProps['type'] = 'float'
ranges = []
idx = 0
while domain.GetMinimumExists(idx) == 1 and domain.GetMaximumExists(idx) == 1:
ranges.append({ 'min': domain.GetMinimum(idx), 'max': domain.GetMaximum(idx) })
idx += 1
uiProps['range'] = ranges
if idx == 0:
return False
return True
#--------------------------------------------------------------------------
# Handle ProxyListDomain
#--------------------------------------------------------------------------
def proxyListDomainDecorator(props, xmlProps, uiProps, domain):
uiProps['widget'] = 'list-1'
uiProps['size'] = 1
uiProps['type'] = 'proxy'
values = {}
for i in xrange(domain.GetNumberOfProxies()):
nextProxy = domain.GetProxy(i)
values[nextProxy.GetXMLLabel()] = nextProxy.GetGlobalIDAsString()
uiProps['values'] = values
return True
#--------------------------------------------------------------------------
# Decorate for PropertyWidgetDecorator hint with type="ClipScalarDecorator"
#--------------------------------------------------------------------------
# FIXME: Remove this when GenericDecorator goes into master
def clipScalarDecorator(prop, uiElt, hint):
proxy = None
try:
proxy = prop.SMProperty.GetParent()
except:
try:
proxy = prop.GetParent()
except:
print 'ERROR: unable to get proxy for property ' + prop.Name
return
excludeAttr = hint.GetAttribute('exclude')
if not excludeAttr or excludeAttr != '1':
depends = proxy.GetGlobalIDAsString() + ':ClipFunction:Scalar:1'
else:
depends = proxy.GetGlobalIDAsString() + ':ClipFunction:Scalar:0'
uiElt['depends'] = depends
#--------------------------------------------------------------------------
# Decorate for PropertyWidgetDecorator hint with type="GenericDecorator"
#--------------------------------------------------------------------------
def genericDecorator(prop, uiElt, hint):
proxy = None
try:
proxy = prop.SMProperty.GetParent()
except:
try:
proxy = prop.GetParent()
except:
print 'ERROR: unable to get proxy for property ' + prop.Name
return
mode = hint.GetAttribute("mode")
# For now we just handle visbility mode
if mode == 'visibility':
propName = hint.GetAttribute("property")
value = hint.GetAttribute("value")
inverse = hint.GetAttribute("inverse")
visibility = '1'
if not inverse or inverse != '1':
visibility = '1'
else:
visibility = '0'
uiElt['depends'] = "%s:%s:%s:%s" % (proxy.GetGlobalIDAsString(), propName, value, visibility)
#--------------------------------------------------------------------------
# Decorate for Widget hint with type="multi_line"
#--------------------------------------------------------------------------
def multiLineDecorator(prop, uiElt, hint):
uiElt['widget'] = 'textarea'

View File

@ -0,0 +1,516 @@
r"""web_helper is a module that provides access to functions that helps to build
new protocols and process ParaView data structure into web friendly ones.
"""
import types
import sys
import os
import traceback
# import paraview modules.
import paraview
from paraview import simple, servermanager
from paraview.servermanager import ProxyProperty, InputProperty
from vtkPVServerManagerCorePython import *
# Needed for:
# vtkSMPVRepresentationProxy
from vtkPVServerManagerRenderingPython import *
# =============================================================================
# Pipeline management
# =============================================================================
class Pipeline:
"""
Define a data structure that represent a pipeline as a tree.
This provide also methods to get the data structure for the web environment
"""
# --------------------------------------------------------------------------
def __init__(self, name):
self.root_node = { 'name': name, 'icon': 'server', 'children': [] }
self.parent_ids = { '0':'0' }
self.children_ids = { '0':[] }
# --------------------------------------------------------------------------
def clear(self):
"""
Clear the pipeline tree.
"""
self.root_node['children'] = []
self.parent_ids = { '0':'0' }
self.children_ids = { '0':[] }
# --------------------------------------------------------------------------
def addNode(self, parent_id, node_id):
"""
Add node into the pipeline tree.
"""
pid = str(parent_id)
nid = str(node_id)
# Add child
if self.children_ids.has_key(pid):
self.children_ids[pid].append(nid)
else:
self.children_ids[pid] = [nid]
# Add parent
self.parent_ids[nid] = pid
# --------------------------------------------------------------------------
def removeNode(self, id):
"""
Remove a node from the pipeline tree.
"""
nid = str(id)
pid = self.parent_ids[nid]
if pid:
del self.parent_ids[nid]
self.children_ids[pid].remove(nid)
# --------------------------------------------------------------------------
def isEmpty(self):
return len(self.parent_ids) == 1
# --------------------------------------------------------------------------
def getRootNode(self, view = None):
"""
Create a tree structure of the pipeline with the current proxy state.
"""
self.root_node['children'] = []
self.__fill_children(self.root_node, self.children_ids['0'], view)
return self.root_node
# --------------------------------------------------------------------------
def __fill_children(self, nodeToFill, childrenIds, view = None):
for id in childrenIds:
node = getProxyAsPipelineNode(id, view)
nid = str(node['proxy_id'])
if nodeToFill.has_key('children'):
nodeToFill['children'].append(node)
else:
nodeToFill['children'] = [ node ]
if self.children_ids.has_key(nid):
self.__fill_children(node, self.children_ids[nid]);
# =============================================================================
# Proxy management
# =============================================================================
def idToProxy(id):
"""
Return the proxy that match the given proxy ID.
"""
remoteObject = simple.servermanager.ActiveConnection.Session.GetRemoteObject(int(id))
if remoteObject:
return simple.servermanager._getPyProxy(remoteObject)
return None
# --------------------------------------------------------------------------
def getParentProxyId(proxy):
"""
Return '0' if the given proxy has no Input otherwise will return
the parent proxy id as a String.
"""
if proxy and proxy.GetProperty("Input"):
parentProxy = proxy.GetProperty("Input").GetProxy(0)
if parentProxy:
return parentProxy.GetGlobalIDAsString()
return '0'
# --------------------------------------------------------------------------
def getProxyAsPipelineNode(id, view=None):
"""
Create a representation for that proxy so it can be used within a pipeline
browser.
"""
pxm = servermanager.ProxyManager()
proxy = idToProxy(id)
rep = simple.GetDisplayProperties(proxy)
nbActiveComp = 1
pointData = []
searchArray = ('POINTS' == rep.ColorArrayName[0]) and (len(rep.ColorArrayName[1]) > 0)
if servermanager.ActiveConnection.GetNumberOfDataPartitions() > 1:
info = { \
'lutId': 'vtkProcessId_1', \
'name': 'vtkProcessId', \
'size': 1, \
'range': [0, servermanager.ActiveConnection.GetNumberOfDataPartitions()-1] }
pointData.append(info)
# FIXME seb
# dataInfo = rep.GetRepresentedDataInformation()
# pointData = dataInfo.GetPointDataInformation()
# cellData = dataInfo.GetCellDataInformation()
# for idx in pointData.GetNumberOfArrays():
# info = pointData.GetArrayInformation(idx)
# nbComponents = info.GetNumberOfComponents()
# if searchArray and array.Name == rep.ColorArrayName:
# nbActiveComp = nbComponents
# rangeOn = (nbComponents == 3 if -1 else 0)
# info = { \
# 'lutId': info.GetName() + '_' + str(nbComponents), \
# 'name': info.GetName, \
# 'size': nbComponents, \
# 'range': info.GetRange(rangeOn) }
# pointData.append(info)
for array in proxy.GetPointDataInformation():
nbComponents = array.GetNumberOfComponents()
if searchArray and array.Name == rep.ColorArrayName[1]:
nbActiveComp = nbComponents
rangeOn = (nbComponents == 1 if 0 else -1)
info = { \
'lutId': array.Name + '_' + str(nbComponents), \
'name': array.Name, \
'size': nbComponents, \
'range': array.GetRange(rangeOn) }
pointData.append(info)
cellData = []
searchArray = ('CELLS' == rep.ColorArrayName[0]) and (len(rep.ColorArrayName[1]) > 0)
for array in proxy.GetCellDataInformation():
nbComponents = array.GetNumberOfComponents()
if searchArray and array.Name == rep.ColorArrayName[1]:
nbActiveComp = nbComponents
rangeOn = (nbComponents == 1 if 0 else -1)
info = { \
'lutId': array.Name + '_' + str(nbComponents), \
'name': array.Name, \
'size': nbComponents, \
'range': array.GetRange(rangeOn) }
cellData.append(info)
state = getProxyAsState(proxy.GetGlobalID())
showScalarbar = 1 if view and vtkSMPVRepresentationProxy.IsScalarBarVisible(rep.SMProxy, view.SMProxy) else 0
repName = 'Hide'
if rep.Visibility == 1:
repName = rep.Representation
return { 'proxy_id' : proxy.GetGlobalID(), \
'name' : pxm.GetProxyName("sources", proxy), \
'bounds' : proxy.GetDataInformation().GetBounds(), \
'pointData' : pointData, \
'cellData' : cellData, \
'activeData': str(rep.ColorArrayName[0]) + ':' + str(rep.ColorArrayName[1]), \
'diffuseColor' : str(rep.DiffuseColor), \
'showScalarBar' : showScalarbar, \
'representation': repName, \
'state' : state, \
'children' : [] }
# --------------------------------------------------------------------------
def getProxyAsState(id):
"""
Return a json representation of the given proxy state.
Example of the state of the Clip filter
{
proxy_id: 234,
ClipType: {
proxy_id: 235,
Normal: [0,0,1],
Origin: [0,0,0],
InsideOut: 0
}
}
"""
proxy_id = int(id)
proxy = idToProxy(proxy_id)
state = { 'proxy_id': proxy_id , 'type': 'proxy', 'domains': getProxyDomains(proxy_id)}
properties = {}
allowedTypes = [int, float, list, str]
if proxy:
for property in proxy.ListProperties():
propertyName = proxy.GetProperty(property).Name
if propertyName in ["Refresh", "Input"] or propertyName.__contains__("Info"):
continue
data = proxy.GetProperty(property).GetData()
if type(data) in allowedTypes:
properties[propertyName] = data
continue
# Not a simple property
# Need more investigation
prop = proxy.GetProperty(property)
pythonProp = servermanager._wrap_property(proxy, prop)
proxyList = []
try:
proxyList = pythonProp.Available
except:
pass
if len(proxyList) and prop.GetNumberOfProxies() == 1:
listdomain = prop.GetDomain('proxy_list')
if listdomain:
proxyPropertyValue = prop.GetProxy(0)
for i in xrange(listdomain.GetNumberOfProxies()):
if listdomain.GetProxy(i) == proxyPropertyValue:
properties[propertyName] = proxyList[i]
# Add selected proxy in list of prop to edit
properties[propertyName + '_internal'] = getProxyAsState(listdomain.GetProxy(i).GetGlobalID())
elif type(prop) == ProxyProperty:
try:
subProxyId = proxy.GetProperty(property).GetData().GetGlobalID()
properties[propertyName] = getProxyAsState(subProxyId)
except:
print "Error on", property, propertyName
print "Skip property: ", str(type(data))
print data
state['properties'] = properties;
return state
# --------------------------------------------------------------------------
def updateProxyProperties(proxy, properties):
"""
Loop over the properties object and update the mapping properties
to the given proxy.
"""
try:
allowedProperties = proxy.ListProperties()
for key in properties:
validKey = servermanager._make_name_valid(key)
if validKey in allowedProperties:
value = removeUnicode(properties[key])
property = servermanager._wrap_property(proxy, proxy.GetProperty(validKey))
if property.GetDomain('proxy_list') and len(value) == 1 and type(value[0]) == str:
try:
idx = property.GetAvailable().index(value[0])
proxyToSet = servermanager._getPyProxy(property.GetDomain('proxy_list').GetProxy(idx))
property.SetData(proxyToSet)
except:
traceback.print_stack()
pass
elif value == 'vtkProcessId':
property.SetElement(0, value)
else:
property.SetData(value)
except:
traceback.print_stack()
# --------------------------------------------------------------------------
def removeUnicode(value):
if type(value) == unicode:
return str(value)
if type(value) == list:
result = []
for v in value:
result.append(removeUnicode(v))
return result
return value
# =============================================================================
# XML and Proxy Definition for GUI generation
# =============================================================================
def getProxyDomains(id):
"""
Return a json based structured based on the proxy XML.
"""
jsonDefinition = {}
proxy = idToProxy(id)
xmlElement = servermanager.ActiveConnection.Session.GetProxyDefinitionManager().GetCollapsedProxyDefinition(proxy.GetXMLGroup(), proxy.GetXMLName(), None)
nbChildren = xmlElement.GetNumberOfNestedElements()
for i in range(nbChildren):
xmlChild = xmlElement.GetNestedElement(i)
name = xmlChild.GetName()
if name.__contains__('Property'):
propName = xmlChild.GetAttribute('name')
jsonDefinition[propName] = extractProperty(proxy, xmlChild)
jsonDefinition[propName]['order'] = i
# Look for proxy properties and their domain
orderIndex = nbChildren
for property in proxy.ListProperties():
if property == 'Input':
continue
if type(proxy.GetProperty(property)) == ProxyProperty:
try:
subProxyId = proxy.GetProperty(property).GetData().GetGlobalID()
subDomain = getProxyDomains(subProxyId)
for key in subDomain:
jsonDefinition[key] = subDomain[key]
jsonDefinition[key]['order'] = orderIndex
orderIndex = orderIndex + 1
except:
print "(Def) Error on", property, ", skipping it..."
#print "(Def) Skip property: ", str(type(data))
return jsonDefinition
def extractProperty(proxy, xmlPropertyElement):
propInfo = {}
propInfo['name'] = xmlPropertyElement.GetAttribute('name')
propInfo['label'] = xmlPropertyElement.GetAttribute('label')
if xmlPropertyElement.GetAttribute('number_of_elements') != None:
propInfo['size'] = xmlPropertyElement.GetAttribute('number_of_elements')
propInfo['type'] = xmlPropertyElement.GetName()[:-14]
propInfo['panel_visibility'] = xmlPropertyElement.GetAttribute('panel_visibility')
propInfo['number_of_elements'] = xmlPropertyElement.GetAttribute('number_of_elements')
propInfo['domains'] = []
if xmlPropertyElement.GetAttribute('default_values') != None:
propInfo['default_values'] = xmlPropertyElement.GetAttribute('default_values')
nbChildren = xmlPropertyElement.GetNumberOfNestedElements()
for i in range(nbChildren):
xmlChild = xmlPropertyElement.GetNestedElement(i)
name = xmlChild.GetName()
if name.__contains__('Domain'):
propInfo['domains'].append(extractDomain(proxy, propInfo['name'], xmlChild))
return propInfo
def extractDomain(proxy, propertyName, xmlDomainElement):
domainObj = {}
name = xmlDomainElement.GetName()
domainObj['type'] = name[:-6]
# Handle Range
if name.__contains__('RangeDomain'):
if xmlDomainElement.GetAttribute('min') != None:
domainObj['min'] = xmlDomainElement.GetAttribute('min')
if xmlDomainElement.GetAttribute('max') != None:
domainObj['max'] = xmlDomainElement.GetAttribute('max')
# Handle Enum
if name.__contains__('EnumerationDomain'):
domainObj['enum'] = []
nbChildren = xmlDomainElement.GetNumberOfNestedElements()
for i in range(nbChildren):
xmlChild = xmlDomainElement.GetNestedElement(i)
if xmlChild.GetName() == "Entry":
domainObj['enum'].append({'text': xmlChild.GetAttribute('text'), 'value': xmlChild.GetAttribute('value')})
# Handle ArrayListDomain
if name.__contains__('ArrayListDomain'):
dataType = xmlDomainElement.GetAttribute('attribute_type')
if dataType == 'Scalars':
domainObj['nb_components'] = 1
elif dataType == 'Vectors':
domainObj['nb_components'] = 3
else:
domainObj['nb_components'] = -1
# Handle ProxyListDomain
if name.__contains__('ProxyListDomain'):
domainObj['list'] = proxy.GetProperty(propertyName).Available
# Handle Bounds
if name.__contains__('BoundsDomain'):
for attrName in ['default_mode', 'mode', 'scale_factor']:
try:
attrValue = xmlDomainElement.GetAttribute(attrName)
if attrValue:
domainObj[attrName] = attrValue
except:
pass
return domainObj
# =============================================================================
# File Management
# =============================================================================
def listFiles(pathToList):
"""
Create a tree structure of the given directory that will be understand by
the pipelineBrowser widget.
The provided path should not have a trailing '/'.
return {
children: [
{ name: 'fileName.vtk', path: '/full_path/to_file/fileName.vtk' },
{ name: 'directoryName', path: '/full_path/to_file/directoryName', children: [] }
]
}
"""
global fileList
if pathToList[-1] == '/':
pathToList = pathToList[:-1]
nodeTree = {}
nodeTree[pathToList] = {'children': []}
for path, directories, files in os.walk(pathToList):
parent = nodeTree[path]
for directory in directories:
child = {'name': directory , 'path': (path + '/' + directory), 'children': []}
nodeTree[path + '/' + directory] = child
parent['children'].append(child)
for filename in files:
child = {'name': filename, 'path': (path + '/' + filename) }
nodeTree[path + '/' + filename] = child
parent['children'].append(child)
fileList = nodeTree[pathToList]['children']
return fileList
# =============================================================================
# Apply domains
# =============================================================================
def apply_domains(parentProxy, proxy_id):
"""
Handle bounds domain
"""
proxy = idToProxy(proxy_id)
# Call recursively on each sub-proxy if any
for property_name in proxy.ListProperties():
prop = proxy.GetProperty(property_name)
if prop.IsA('vtkSMProxyProperty'):
try:
if len(prop.Available) and prop.GetNumberOfProxies() == 1:
listdomain = prop.GetDomain('proxy_list')
if listdomain:
for i in xrange(listdomain.GetNumberOfProxies()):
internal_proxy = listdomain.GetProxy(i)
apply_domains(parentProxy, internal_proxy.GetGlobalIDAsString())
except:
exc_type, exc_obj, exc_tb = sys.exc_info()
print "Unexpected error:", exc_type, " line: " , exc_tb.tb_lineno
# Reset all properties to leverage domain capabilities
for prop_name in proxy.ListProperties():
try:
prop = proxy.GetProperty(prop_name)
iter = prop.NewDomainIterator()
iter.Begin()
while not iter.IsAtEnd():
domain = iter.GetDomain()
iter.Next()
try:
if domain.IsA('vtkSMBoundsDomain'):
domain.SetDomainValues(parentProxy.GetDataInformation().GetBounds())
except AttributeError as attrErr:
print 'Caught exception setting domain values in apply_domains:'
print attrErr
prop.ResetToDefault()
# Need to UnRegister to handle the ref count from the NewDomainIterator
iter.UnRegister(None)
except:
exc_type, exc_obj, exc_tb = sys.exc_info()
print "Unexpected error:", exc_type, " line: " , exc_tb.tb_lineno
proxy.UpdateVTKObjects()

View File

@ -0,0 +1,307 @@
r"""
The ParaViewWeb iPython module is used as a helper to create custom
iPython notebook profile.
The following sample show how the helper class can be used inside
an iPython profile.
# Global python import
import exceptions, logging, random, sys, threading, time, os
# Update python path to have ParaView libs
pv_path = '/.../ParaView/build'
sys.path.append('%s/lib' % pv_path)
sys.path.append('%s/lib/site-packages' % pv_path)
# iPython import
from IPython.display import HTML
from IPython.parallel import Client
import paraview
from paraview.web import ipython as pv_ipython
from vtk import *
iPythonClient = None
paraviewHelper = pv_ipython.ParaViewIPython()
webArguments = pv_ipython.WebArguments('/.../path-to-web-directory')
def _start_paraview():
paraviewHelper.Initialize()
paraviewHelper.SetWebProtocol(pv_ipython.IPythonProtocol, webArguments)
return paraviewHelper.Start()
def _stop_paraview():
paraviewHelper.Finalize()
def _pv_activate_dataset():
pv_ipython.IPythonProtocol.ActivateDataSet('iPython-demo')
def _push_new_timestep():
# processing code generating new vtkDataSet
# newDataset = ...
pv_ipython.IPythonProtocol.RegisterDataSet('iPython-demo', newDataset)
def StartParaView(height=600, path='/apps/Visualizer/'):
global iPythonClient, paraviewHelper
if not iPythonClient:
iPythonClient = Client(profile='pvw')
urls = iPythonClient[:].apply_sync(lambda:_start_paraview())
url = ""
for i in urls:
if len(i) > 0:
url = i
return HTML("<iframe src='%s%s' width='100%%' height='%i'></iframe>"%(url, path, height))
def StopParaView():
global iPythonClient, paraviewHelper
iPythonClient[:].apply_sync(lambda:_stop_paraview())
def ActivateDataSet():
iPythonClient[:].apply_sync(lambda:_pv_activate_dataset())
def ComputeNextTimeStep():
global iPythonClient
if not iPythonClient:
iPythonClient = Client(profile='pvw')
iPythonClient[:].apply_sync(lambda:_push_new_timestep())
"""
import exceptions, traceback, logging, random, sys, threading, time, os, paraview
from mpi4py import MPI
from vtk.web import server
from paraview.vtk import *
from vtkCommonCorePython import *
from vtkCommonDataModelPython import *
from vtkCommonExecutionModelPython import *
from vtkFiltersSourcesPython import *
from vtkParallelCorePython import *
from vtkParaViewWebCorePython import *
from vtkPVClientServerCoreCorePython import *
from vtkPVServerManagerApplicationPython import *
from vtkPVServerManagerCorePython import *
from vtkPVVTKExtensionsCorePython import *
from vtkWebCorePython import *
from paraview.web import wamp as pv_wamp
#------------------------------------------------------------------------------
# Global variables
#------------------------------------------------------------------------------
logger = logging.getLogger()
logger.setLevel(logging.ERROR)
#------------------------------------------------------------------------------
# Global internal methods
#------------------------------------------------------------------------------
def _get_hostname():
import socket
if socket.gethostname().find('.')>=0:
return socket.gethostname()
else:
return socket.gethostbyaddr(socket.gethostname())[0]
#------------------------------------------------------------------------------
# ParaView iPython helper class
#------------------------------------------------------------------------------
class ParaViewIPython(object):
processModule = None
globalController = None
localController = None
webProtocol = None
webArguments = None
processId = -1
number_of_process = -1
def Initialize(self, log_file_path = None, logging_level = logging.DEBUG):
if not ParaViewIPython.processModule:
vtkInitializationHelper.Initialize("ipython-notebook", 4) # 4 is type of process
ParaViewIPython.processModule = vtkProcessModule.GetProcessModule()
ParaViewIPython.globalController = ParaViewIPython.processModule.GetGlobalController()
if MPI.COMM_WORLD.Get_size() > 1 and (ParaViewIPython.globalController is None or ParaViewIPython.globalController.IsA("vtkDummyController") == True):
import vtkParallelMPIPython
ParaViewIPython.globalController = vtkParallelMPIPython.vtkMPIController()
ParaViewIPython.globalController.Initialize()
ParaViewIPython.globalController.SetGlobalController(ParaViewIPython.globalController)
ParaViewIPython.processId = ParaViewIPython.globalController.GetLocalProcessId()
ParaViewIPython.number_of_process = ParaViewIPython.globalController.GetNumberOfProcesses()
ParaViewIPython.localController = ParaViewIPython.globalController.PartitionController(ParaViewIPython.number_of_process, ParaViewIPython.processId)
# must unregister if the reference count is greater than 1
if ParaViewIPython.localController.GetReferenceCount() > 1:
ParaViewIPython.localController.UnRegister(None)
ParaViewIPython.globalController.SetGlobalController(ParaViewIPython.localController)
if log_file_path:
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
fh = logging.FileHandler('%s-%s.txt' % (log_file_path, str(ParaViewIPython.processId)))
fh.setLevel(logging_level)
fh.setFormatter(formatter)
logger.addHandler(fh)
logger.info("Process %i initialized for ParaView" % os.getpid())
logger.info("Sub-Controller: " + str(ParaViewIPython.localController.GetLocalProcessId()) + "/" + str(ParaViewIPython.localController.GetNumberOfProcesses()))
logger.info("GlobalController: " + str(ParaViewIPython.processId) + "/" + str(ParaViewIPython.number_of_process))
else:
logger.info("ParaView has already been initialized. No operation was performed.")
def Finalize(self):
if ParaViewIPython.processModule:
vtkInitializationHelper.Finalize()
ParaViewIPython.processModule = None
def GetProcessId(self):
return ParaViewIPython.processId
def GetNumberOfProcesses(self):
return ParaViewIPython.number_of_process
def __repr__(self):
return self.__str__()
def __str__(self):
return "Host: %s - Controller: %s - Rank: %d/%d" % (_get_hostname(), ParaViewIPython.localController.GetClassName(), ParaViewIPython.processId, ParaViewIPython.number_of_process)
def SetWebProtocol(self, protocol, arguments):
ParaViewIPython.webProtocol = protocol
ParaViewIPython.webArguments = arguments
if not hasattr(ParaViewIPython.webArguments, 'port'):
ParaViewIPython.webArguments.port = 8080
ParaViewIPython.webProtocol.rootNode = (self.GetProcessId() == 0)
ParaViewIPython.webProtocol.updateArguments(ParaViewIPython.webArguments)
@staticmethod
def _start_satelite():
logger.info('ParaView Satelite %d - Started' % ParaViewIPython.processId)
sid = vtkSMSession.ConnectToSelf();
vtkWebUtilities.ProcessRMIs()
ParaViewIPython.processModule.UnRegisterSession(sid);
logger.info('ParaView Satelite %d - Ended' % ParaViewIPython.processId)
@staticmethod
def _start_web_server():
server.start_webserver(options=ParaViewIPython.webArguments, protocol=ParaViewIPython.webProtocol)
from paraview import simple
simple.Disconnect()
ParaViewIPython.localController.TriggerBreakRMIs()
@staticmethod
def debug():
for i in range(10):
logger.info('In debug loop ' + str(i))
def Start(self):
thread = None
if self.GetProcessId() == 0:
thread = threading.Thread(target=ParaViewIPython._start_web_server)
thread.start()
time.sleep(10)
logger.info("WebServer thread started")
return "http://%s:%d" % (_get_hostname(), ParaViewIPython.webArguments.port)
else:
thread = threading.Thread(target=ParaViewIPython._start_satelite)
thread.start()
logger.info("Satelite thread started")
return ""
#------------------------------------------------------------------------------
# ParaView iPython protocol
#------------------------------------------------------------------------------
class IPythonProtocol(pv_wamp.PVServerProtocol):
rootNode = False
dataDir = None
authKey = "vtkweb-secret"
fileToLoad = None
producer = None
groupRegex = "[0-9]+\\."
excludeRegex = "^\\.|~$|^\\$"
@staticmethod
def ActivateDataSet(key):
if IPythonProtocol.rootNode and IPythonProtocol.producer:
IPythonProtocol.producer.UpdateDataset = ''
IPythonProtocol.producer.UpdateDataset = key
@staticmethod
def RegisterDataSet(key, dataset):
vtkDistributedTrivialProducer.SetGlobalOutput(key, dataset)
@staticmethod
def updateArguments(options):
IPythonProtocol.dataDir = options.dataDir
IPythonProtocol.authKey = options.authKey
IPythonProtocol.fileToLoad = options.fileToLoad
IPythonProtocol.authKey = options.authKey
IPythonProtocol.groupRegex = options.groupRegex
IPythonProtocol.excludeRegex = options.excludeRegex
def initialize(self):
from paraview import simple
from paraview.web import protocols as pv_protocols
# Make sure ParaView is initialized
if not simple.servermanager.ActiveConnection:
simple.Connect()
if not IPythonProtocol.producer:
IPythonProtocol.producer = simple.DistributedTrivialProducer()
IPythonProtocol.ActivateDataSet('iPython-demo')
simple.Show(IPythonProtocol.producer)
simple.Render()
# Bring used components
self.registerVtkWebProtocol(pv_protocols.ParaViewWebFileListing(IPythonProtocol.dataDir, "Home", IPythonProtocol.excludeRegex, IPythonProtocol.groupRegex))
self.registerVtkWebProtocol(pv_protocols.ParaViewWebPipelineManager(IPythonProtocol.dataDir, IPythonProtocol.fileToLoad))
self.registerVtkWebProtocol(pv_protocols.ParaViewWebMouseHandler())
self.registerVtkWebProtocol(pv_protocols.ParaViewWebViewPort())
self.registerVtkWebProtocol(pv_protocols.ParaViewWebViewPortImageDelivery())
self.registerVtkWebProtocol(pv_protocols.ParaViewWebViewPortGeometryDelivery())
self.registerVtkWebProtocol(pv_protocols.ParaViewWebTimeHandler())
self.registerVtkWebProtocol(pv_protocols.ParaViewWebRemoteConnection())
self.registerVtkWebProtocol(pv_protocols.ParaViewWebFileManager(IPythonProtocol.dataDir))
# Update authentication key to use
self.updateSecret(IPythonProtocol.authKey)
def __str__(self):
return "Root node: " + str(IPythonProtocol.rootNode)
#------------------------------------------------------------------------------
# ParaView iPython default arguments
#------------------------------------------------------------------------------
class WebArguments(object):
def __init__(self, webDir = None):
self.content = webDir
self.port = 8080
self.host = 'localhost'
self.debug = 0
self.timeout = 120
self.nosignalhandlers = True
self.authKey = 'vtkweb-secret'
self.uploadDir = ""
self.testScriptPath = ""
self.baselineImgDir = ""
self.useBrowser = ""
self.tmpDirectory = ""
self.testImgFile = ""
self.forceFlush = False
self.dataDir = '.'
self.groupRegex = "[0-9]+\\."
self.excludeRegex = "^\\.|~$|^\\$"
self.fileToLoad = None
def __str__(self):
return "http://%s:%d/%s" % (self.host, self.port, self.content)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,258 @@
r"""
This module is a ParaViewWeb server application.
The following command line illustrate how to use it::
$ pvpython .../pv_web_catalyst.py --data-dir /.../path-to-your-data-directory
--data-dir is used to list that directory on the server and let the client choose a file to load.
Any ParaViewWeb executable script come with a set of standard arguments that
can be overriden if need be::
--port 8080
Port number on which the HTTP server will listen to.
--content /path-to-web-content/
Directory that you want to server as static web content.
By default, this variable is empty which mean that we rely on another server
to deliver the static content and the current process only focus on the
WebSocket connectivity of clients.
--authKey vtkweb-secret
Secret key that should be provided by the client to allow it to make any
WebSocket communication. The client will assume if none is given that the
server expect "vtkweb-secret" as secret key.
"""
# import to process args
import os
import math
# import paraview modules.
import paraview
# for 4.1 compatibility till we fix ColorArrayName and ColorAttributeType usage.
paraview.compatibility.major = 4
paraview.compatibility.minor = 1
from paraview import simple
from paraview.web import wamp as pv_wamp
from paraview.web import protocols as pv_protocols
from vtk.web import server
try:
import argparse
except ImportError:
# since Python 2.6 and earlier don't have argparse, we simply provide
# the source for the same as _argparse and we use it instead.
from vtk.util import _argparse as argparse
# import annotations
from autobahn.wamp import register as exportRpc
# =============================================================================
# Handle function helpers
# =============================================================================
def convert_to_float(v):
return float(v)
# -----------------------------------------------------------------------------
def convert_to_float_array(v):
return [ float(v) ]
# -----------------------------------------------------------------------------
def update_property(handle, value):
property = handle['proxy'].GetProperty(handle['property'])
if handle.has_key('convert'):
property.SetData( handle['convert'](value) )
else:
property.SetData( value )
# -----------------------------------------------------------------------------
def create_property_handle(proxy, property_name, convert = None):
handle = { 'proxy': proxy, 'property': property_name, 'update': update_property }
if convert:
handle['convert'] = convert
return handle
# -----------------------------------------------------------------------------
def update_representation(handle, value):
proxy = handle['proxy']
if handle['color_list'].has_key(value):
for propName in handle['color_list'][value]:
prop = proxy.GetProperty(propName)
if prop != None:
prop.SetData(handle['color_list'][value][propName])
if handle.has_key('override_location'):
proxy.ColorAttributeType = handle['override_location']
# -----------------------------------------------------------------------------
def create_representation_handle(representation_proxy, colorByList, array_location = None):
handle = { 'proxy': representation_proxy, 'color_list': colorByList, 'update': update_representation }
if array_location:
handle['override_location'] = array_location
return handle
# =============================================================================
# Define a pipeline object
# =============================================================================
class CatalystBasePipeline(object):
def __init__(self):
self.field_data = {}
self.handles = {}
self.metadata = {}
def apply_pipeline(self, input_data, time_steps):
'''
Method called when data to process is ready
'''
self.metadata['time'] = { "default": time_steps[0], "type": "range", "values": time_steps, "label": "time", "priority": 0 }
def add_key(self, key, default_value, data_type, values, label, priority, handles):
self.handles[key] = handles
self.metadata[key] = {
"default": default_value,
"type": data_type,
"values": values,
"label": label,
"priority": priority
}
def register_data(self, fieldName, location, scalarRange, lutType):
self.field_data[fieldName] = {
"ColorArrayName": (location, fieldName),
"Range": scalarRange,
"LookupTable": self._create_lookup_table(fieldName, scalarRange, lutType),
"ScalarOpacityFunction": self._create_piecewise_function(scalarRange)
}
def update_argument(self, key, value):
for handle in self.handles[key]:
handle['update'](handle, value)
def get_metadata(self):
return self.metadata
def _create_data_values(self, scalarRange, number_of_values):
inc = float(scalarRange[1]-scalarRange[0]) / float(number_of_values)
values = []
for i in range(number_of_values+1):
values.append(float(scalarRange[0] + (float(i)*inc) ))
return values
def _create_lookup_table(self, name, scalarRange, lutType):
if lutType == 'blueToRed':
return simple.GetLookupTableForArray( name, 1, RGBPoints=[scalarRange[0], 0.231373, 0.298039, 0.752941, (scalarRange[0]+scalarRange[1])/2, 0.865003, 0.865003, 0.865003, scalarRange[1], 0.705882, 0.0156863, 0.14902], VectorMode='Magnitude', NanColor=[0.0, 0.0, 0.0], ColorSpace='Diverging', ScalarRangeInitialized=1.0, LockScalarRange=1)
else:
return simple.GetLookupTableForArray( name, 1, RGBPoints=[scalarRange[0], 0.0, 0.0, 1.0, scalarRange[1], 1.0, 0.0, 0.0], VectorMode='Magnitude', NanColor=[0.0, 0.0, 0.0], ColorSpace='HSV', ScalarRangeInitialized=1.0, LockScalarRange=1)
def _create_piecewise_function(self, scalarRange):
return simple.CreatePiecewiseFunction( Points=[scalarRange[0], 0.0, 0.5, 0.0, scalarRange[1], 1.0, 0.5, 0.0] )
# =============================================================================
# Create custom Catalyst Pipeline Manager class to handle clients requests
# =============================================================================
class _PVCatalystManager(pv_wamp.PVServerProtocol):
dataDir = None
authKey = "vtkweb-secret"
plugins = None
pipeline_handler = None
@staticmethod
def add_arguments(parser):
parser.add_argument("--data-dir", default=os.getcwd(), help="path to data directory to list", dest="path")
parser.add_argument("--plugins", default="", help="List of fully qualified path names to plugin objects to load", dest="plugins")
@staticmethod
def configure(args):
_PVCatalystManager.authKey = args.authKey
_PVCatalystManager.dataDir = args.path
_PVCatalystManager.plugins = args.plugins
def initialize(self):
# Bring used components
self.registerVtkWebProtocol(pv_protocols.ParaViewWebStartupPluginLoader(_PVCatalystManager.plugins))
self.registerVtkWebProtocol(pv_protocols.ParaViewWebMouseHandler())
self.registerVtkWebProtocol(pv_protocols.ParaViewWebViewPort())
self.registerVtkWebProtocol(pv_protocols.ParaViewWebViewPortImageDelivery())
self.registerVtkWebProtocol(pv_protocols.ParaViewWebViewPortGeometryDelivery())
# Update authentication key to use
self.updateSecret(_PVCatalystManager.authKey)
view = simple.GetRenderView()
view.Background = [1,1,1]
@exportRpc("catalyst.file.open")
def openFileFromPath(self, files):
fileToLoad = []
number_of_time_steps = 1
if type(files) == list:
number_of_time_steps = len(files)
for file in files:
fileToLoad.append(os.path.join(_PVCatalystManager.dataDir, file))
else:
fileToLoad.append(os.path.join(_PVCatalystManager.dataDir, files))
self.time_steps = [ i for i in range(number_of_time_steps)]
reader = simple.OpenDataFile(fileToLoad)
if _PVCatalystManager.pipeline_handler:
_PVCatalystManager.pipeline_handler.apply_pipeline(reader, self.time_steps)
@exportRpc("catalyst.pipeline.initialize")
def initializePipeline(self, conf):
if _PVCatalystManager.pipeline_handler and "initialize_pipeline" in dir(_PVCatalystManager.pipeline_handler):
_PVCatalystManager.pipeline_handler.initialize_pipeline(conf)
@exportRpc("catalyst.active.argument.update")
def updateActiveArgument(self, key, value):
if key == "time":
simple.GetAnimationScene().TimeKeeper.Time = float(value)
elif _PVCatalystManager.pipeline_handler:
_PVCatalystManager.pipeline_handler.update_argument(key, value)
@exportRpc("catalyst.arguments.get")
def getArguments(self):
if _PVCatalystManager.pipeline_handler:
return _PVCatalystManager.pipeline_handler.get_metadata()
else:
return { "time": {
"default": "0",
"type": "range",
"values": self.time_steps,
"label": "time",
"priority": 0 } }
# =============================================================================
# Main: Parse args and start server
# =============================================================================
if __name__ == "__main__":
# Create argument parser
parser = argparse.ArgumentParser(description="ParaView/Web Pipeline Manager web-application")
# Add arguments
server.add_arguments(parser)
_PVCatalystManager.add_arguments(parser)
# Exctract arguments
args = parser.parse_args()
# Configure our current application
_PVCatalystManager.configure(args)
# Start server
server.start_webserver(options=args, protocol=_PVCatalystManager)

View File

@ -0,0 +1,18 @@
r"""paraviewweb_wamp is the paraview-specific subclass
of vtkweb_wamp that provides the PVWeb Application
"""
from vtk.web import wamp
from vtkParaViewWebCorePython import vtkPVWebApplication
from paraview.web import protocols as pv_protocols
class PVServerProtocol(wamp.ServerProtocol):
def __init__(self, config):
wamp.ServerProtocol.__init__(self, config)
wamp.imageCapture = pv_protocols.ParaViewWebViewPortImageDelivery()
wamp.imageCapture.setApplication(self.Application)
def initApplication(self):
return vtkPVWebApplication()

View File

@ -0,0 +1,156 @@
r"""
This module provides classes to handle Rest API for WebGL piece request.
This module is now deprecated.
"""
from twisted.web import server, resource
from twisted.web import server, resource
from twisted.web.error import Error
from paraview import simple
from paraview.web import helper
from vtkParaViewWebCorePython import vtkPVWebApplication
import exceptions
import base64
pv_web_app = vtkPVWebApplication()
class WebGLResource(resource.Resource):
"""
Resource using to serve WebGL data. If supports URLs of two forms:
- to get the meta-data as json-rpc message:
http://.../WebGL?q=meta&vid=456
- to get a binary webgl object:
http://.../WebGL?q=mesh&vid=456&id=1&part=0
vid : visualization view ID (GlobalID of the view Proxy)
id : id of the object in the scene
part: WebGL has a size limit, therefore an object can be splitted in
several part. This is the part index.
"""
def _missing_parameter(self, parameter):
raise Error(400, "Missing required parameter: %s" % parameter)
def _get_parameter(self, args, parameter, required=True):
"""
Extract a parameter value from the request args.
:param parameter: The parameter name
:type parameter: str
:param required: True if the function should raise an error is the
parameter is missing.
:type required: bool
"""
value = None
if not parameter in args:
if required:
self._missing_parameter(parameter)
else:
values = args[parameter]
if len(values) == 1:
value = values[0]
elif required:
self._missing_parameter(parameter)
return value
def _get_view(self, vid):
"""
Returns the view for a given view ID, if vid is None then return the
current active view.
:param vid: The view ID
:type vid: str
"""
def _get_active_view():
view = simple.GetActiveView()
if not view:
raise Error(404, "No view provided to WebGL resource")
return view
view = None
if vid:
try:
view = helper.mapIdToProxy(vid)
except exceptions.TypeError:
pass
if not view:
view = _get_active_view()
return view
def _render_GET_mesh(self, vid, request):
"""
Handle GET requests to get WebGL data for a particular object.
"""
object_id = self._get_parameter(request.args, 'id')
part_number = self._get_parameter(request.args, 'part', False);
part = 0
if part_number:
part = int(part_number)
view = self._get_view(vid)
# There part is offset by 1
if part > 0:
part = part - 1
data = pv_web_app.GetWebGLBinaryData(view.SMProxy, object_id, part);
if data:
request.setHeader('content-type', 'application/octet-stream+webgl')
request.setHeader('Cache-Control', 'max-age=99999');
data = base64.b64decode(data)
else:
raise Error(404, "Invalid request for WebGL object")
return data
def _render_GET_meta(self, vid, request):
"""
Handle GET request for meta data.
"""
view = self._get_view(vid)
data = pv_web_app.GetWebGLSceneMetaData(view.SMProxy)
if data:
request.setHeader('content-type', 'application/json')
else:
raise Error(404, "Invalid request for WebGL meta data")
return data
def render_GET(self, request):
"""
Handle GET requests, parse out q parameter to delegate to the correct
internal function.
There is two types of queries allowed:
- to get the meta-data as json-rpc message:
http://.../WebGL?q=meta&vid=456
- to get a binary webgl object:
http://.../WebGL?q=mesh&vid=456&id=1&part=0
vid : visualization view ID (GlobalID of the view Proxy)
id : id of the object in the scene
part: WebGL has a size limit, therefore an object can be splitted in several part. This is the part index.
"""
try:
q = self._get_parameter(request.args, 'q')
vid = self._get_parameter(request.args, 'vid', False)
if q == 'mesh':
return self._render_GET_mesh(vid, request)
elif q == 'meta':
return self._render_GET_meta(vid, request)
else:
raise Error(400, "Invalid query for the WebGL resource");
except Error as err:
request.setResponseCode(err.status)
return err.message