[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
Re: [ice-dev] ParaView Web Visualizer shared sessions
|
Yes, we can have multiple open at once in Eclipse, though the server will pop open a new window for each additional file, so perhaps each one is its own ParaView session internally?
How can I check the http and ws endpoints to make sure they are active?
I've attached the server file.
Robert
From: Sebastien Jourdain <sebastien.jourdain@xxxxxxxxxxx>
Sent: Friday, April 22, 2016 5:17 PM
To: Smith, Robert W.
Cc: ice-dev@xxxxxxxxxxx
Subject: Re: ParaView Web Visualizer shared sessions
Can you have 2 different views inside your eclipse while you have only one server?
Moreover, you need to make sure your http_server does provide the same protocols as the pv_web_visualizer.py.
On top of that, you need to make sure you both have the http and ws endpoint active.
As I don't remember what you have in your http_pvw_server.py,
could you send it to me so I can look at it?
Seb
|
import json, re, os, inspect, sys
# Imports need to run a simple webserver
from twisted.web import server, resource, http
from twisted.web.resource import Resource
from twisted.internet import reactor
from twisted.web.static import File
# import paraview modules.
from paraview.web import wamp as pv_wamp
from paraview.web import protocols as pv_protocols
from paraview import simple
from paraview import servermanager
# import RPC annotation
from autobahn.wamp import register as exportRpc
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.
import _argparse as argparse
# Module-level regex object won't have to be recompiled on each POST request
# The first regex group is the RPC call, e.g., viewport.image.render
# The second (optional) regex group is the view id. If not there, assume -1.
endpoint = 'rpc-http'
urlMatcher = re.compile(endpoint + '/([^/]+)')
#urlMatcher = re.compile(endpoint + '/([^/]+)' + '(?:/([0-9]*))?')
# =============================================================================
# Convenience method to parse out the rpc method name from the path. In order
# to find the method name, the server expects the path to contain:
#
# /hpcmp/rpc.method.name
#
# =============================================================================
def extractRpcMethod(path):
m = urlMatcher.search(path)
if m:
return m.group(1) #, m.group(2)
else:
return None
# =============================================================================
# Custom visualization application session
# =============================================================================
class _BasicServer(pv_wamp.PVServerProtocol):
@staticmethod
def add_arguments(parser):
parser.add_argument("--host", type=str, default='localhost', help="the interface for the web-server to listen on (default: localhost)")
parser.add_argument("--port", default=8080, type=int, help="Which port to listen on", dest="port")
@staticmethod
def configure(args):
pass
def initialize(self):
# Set the base directory to the user's home area.
baseDir = os.path.expanduser("~")
# Bring used components
self.registerVtkWebProtocol(pv_protocols.ParaViewWebMouseHandler())
self.registerVtkWebProtocol(pv_protocols.ParaViewWebViewPort())
self.registerVtkWebProtocol(pv_protocols.ParaViewWebViewPortImageDelivery())
self.registerVtkWebProtocol(pv_protocols.ParaViewWebFileListing(baseDir,baseDir))
#self.registerVtkWebProtocol(pv_protocols.ParaViewWebProxyManager(None,baseDir))
self.proxyManager = pv_protocols.ParaViewWebProxyManager(None,baseDir)
self.registerVtkWebProtocol(self.proxyManager)
self.colorManager = pv_protocols.ParaViewWebColorManager()
self.registerVtkWebProtocol(self.colorManager)
self.registerVtkWebProtocol(pv_protocols.ParaViewWebTimeHandler())
# The below dictionaries are keyed on global IDs obtained from
# GetGlobalIDAsString() methods.
# Each entry looks like: view, proxyId, repId, animScene
self.views = {}
# Each entry contains a single file proxy.
self.proxies = {}
# Each entry contains a single representation proxy.
self.representations = {}
def createView(self, fullPath):
# Find the relative path for the call to proxyManager.open(relativePath).
# TODO
relativePath = fullPath
# Create a new view.
view = simple.CreateRenderView()
viewId = int(view.GetGlobalIDAsString())
self.views[viewId] = (view, None, None, None)
# Open the file. Throw an error if the file could not be read.
response = self.proxyManager.open(relativePath)
try:
proxyId = int(response['id'])
except ValueError:
self.disposeView(viewId)
return { "success": False, "error": response['reason'] }
proxy = self.proxyManager.mapIdToProxy(proxyId)
self.proxies[proxyId] = proxy
# Find the corresponding representation proxy.
rep = simple.GetRepresentation(proxy=proxy, view=view)
repId = int(rep.GetGlobalIDAsString())
self.representations[repId] = rep
# Create a new AnimationScene just for this view.
# TODO
animScene = None
# Store the view metadata currently associated with the view's ID.
self.views[viewId] = (view, proxyId, repId, animScene)
# Hide all other proxies that for whatever reason are automatically added to this view.
self._hideOtherViews(proxyId, view)
self.activateView(viewId)
# Return a JSON object containing the view ID, the proxy ID, and the representation ID.
return { "viewId": viewId, "proxyId": proxyId, "repId": repId }
def activateView(self, id):
# TODO Add some error handling
# Find the view.
viewAssociations = self.views[id]
view = viewAssociations[0]
proxyId = viewAssociations[1]
proxy = self.proxies[proxyId]
# Make it the active view.
# Render it.
# TODO Why don't we need to hide the other proxies?
#self._hideOtherViews(proxyId, view)
simple.SetActiveView(view)
simple.Show()
simple.Render()
return { "success": True }
def refreshScalarBars(self, viewId):
# Try to look up the view, throwing an error if the ID is not an
# integer or if the ID was not a valid key for the dictionary.
try:
view = self.views[int(viewId)][0]
except ValueError:
error = "Invalid view ID:", viewId
return { "success": False, "error": error }
except LookupError:
error = "View with ID", viewId, "not found"
return { "success": False, "error": error }
# Hide all of the irrelevant scalar bars/legends.
simple.HideUnusedScalarBars(view)
return { "success": True }
def disposeView(self, id):
# TODO Add some error handling.
# TODO Figure out how to actually dispose the ParaView resources.
viewAssociations = self.views[id]
# Dispose the view itself
self.views[id] = None
# Dispose the proxies
proxyId = viewAssociations[1]
if proxyId:
proxy = self.proxies[proxyId]
# TODO
self.proxies[proxyId] = None
repId = viewAssociations[2]
if repId:
rep = self.representations[repId]
# TODO
self.representations[repId] = None
animScene = viewAssociations[3]
# TODO
sys.exit()
return { "success": True }
def _hideOtherViews(self, proxyId, view):
proxies = servermanager.ProxyManager().GetProxiesInGroup("sources")
for key in proxies:
if key[1] != proxyId:
simple.Hide(proxies[key], view)
return
def changeTime(self, id, action):
# Find the AnimationScene for the specified view.
viewAssociations = self.views[id]
view = viewAssociations[0]
# Return an error result if necessary.
if not view:
return { "time": -1, "error": "Invalid view with id {0}.".format(id) }
animationScene = viewAssociations[3]
currentTime = view.ViewTime
# Update the AnimationScene depending on the action string.
# This code comes (almost) straight from the ParaView protocols python script.
if action == "next":
animationScene.GoToNext()
if currentTime == view.ViewTime:
animationScene.GoToFirst()
elif action == "prev":
animationScene.GoToPrevious()
if currentTime == view.ViewTime:
animationScene.GoToLast()
elif action == "first":
animationScene.GoToFirst()
elif action == "last":
animationScene.GoToLast()
else:
return { "time": -1, "error": "Invalid action {0}.".format(action) }
# Return a JSON object that contains a "success" boolean and a "reason" string.
return view.ViewTime
# =============================================================================
# Simple web server endpoint handling POST requests to execute rpc methods
# =============================================================================
class HttpRpcResource(resource.Resource, object):
def __init__(self, serverProtocol):
super(HttpRpcResource, self).__init__()
self.functionMap = {}
# Build the rpc method dictionary
protocolList = serverProtocol.getVtkWebProtocols()
protocolList.append(serverProtocol) # so the exit methods get "registered"
for protocolObject in protocolList:
test = lambda x: inspect.ismethod(x) or inspect.isfunction(x)
for k in inspect.getmembers(protocolObject.__class__, test):
proc = k[1]
if "_wampuris" in proc.__dict__:
pat = proc.__dict__["_wampuris"][0]
if pat.is_endpoint():
uri = pat.uri()
# TODO Remove this line
print uri
self.functionMap[uri] = (protocolObject, proc)
# Register the custom server methods.
self.functionMap["createView"] = (None, serverProtocol.createView)
self.functionMap["activateView"] = (None, serverProtocol.activateView)
self.functionMap["disposeView"] = (None, serverProtocol.disposeView)
self.functionMap["refreshScalarBars"] = (None, serverProtocol.refreshScalarBars)
def getChild(self, path, request):
return self
def render_GET(self, request):
return ""
def render_POST(self, request):
payload = json.loads(request.content.getvalue())
args = payload['args']
methodName = extractRpcMethod(request.path)
print methodName
obj,func = self.functionMap[methodName]
if obj:
results = func(obj, *args)
else:
results = func(*args)
return json.dumps(results)
# =============================================================================
# Parse arguments, create protocol server, and start webserver
# =============================================================================
if __name__ == "__main__":
# Create argument parser
parser = argparse.ArgumentParser(description="ParaView Web Visualizer")
# Add arguments
_BasicServer.add_arguments(parser)
args = parser.parse_args()
_BasicServer.configure(args)
# Create the application session
serverProtocol = _BasicServer(None)
# Start up the web server
web_resource = resource.Resource()
web_resource.putChild(endpoint, HttpRpcResource(serverProtocol))
site = server.Site(web_resource)
reactor.listenTCP(args.port, site, interface=args.host)
reactor.run()