在Paraview中,simple.py承接着与外界用户接口的任务,一个最基本的使用Paraview例子就是:
from paraview.simple import *
# Create a new sphere proxy on the active connection and register it
# in the sources group.
sphere = Sphere(ThetaResolution=16, PhiResolution=32)
# Apply a shrink filter
shrink = Shrink(sphere)
# Turn the visiblity of the shrink object on.
Show(shrink)
# Render the scene
Render()
def Show(proxy=None, view=None, **params):
"""Turns the visibility of a given pipeline object on in the given view.
If pipeline object and/or view are not specified, active objects are used."""
if proxy == None:
proxy = GetActiveSource()
if proxy == None:
raise RuntimeError, "Show() needs a proxy argument or that an active source is set."
if not view:
# it here's now active view, controller.Show() will create a new preferred view.
# if possible.
view = active_objects.view
controller = servermanager.ParaViewPipelineController()
rep = controller.Show(proxy, proxy.Port, view)
if rep == None:
raise RuntimeError, "Could not create a representation object for proxy %s" % proxy.GetXMLLabel()
for param in params.keys():
setattr(rep, param, params[param])
return rep
这个方法其中有一行
raise RuntimeError, "Could not create a representation object for proxy %s" % proxy.GetXMLLabel()
告诉我们,其实rep就是一个representation。所以它就是把这个filter处理后的source绑定到当前的view和代理上。产生一个representation。
最后是Render函数:def Render(view=None):
"""Renders the given view (default value is active view)"""
if not view:
view = active_objects.view
view.StillRender()
if _funcs_internals.first_render:
# Not all views have a ResetCamera method
try:
view.ResetCamera()
view.StillRender()
except AttributeError: pass
_funcs_internals.first_render = False
return view
其实就是开始渲染,调用了
view.StillRender()
进行渲染。
from paraview.servermanager import *
# Creates a new built-in session and makes it the active session.
Connect()
# Creates a new render view on the active session.
renModule = CreateRenderView()
# Create a new sphere proxy on the active session and register it
# in the sources group.
sphere = sources.SphereSource(registrationGroup="sources", ThetaResolution=16, PhiResolution=32)
# Create a representation for the sphere proxy and adds it to the render
# module.
display = CreateRepresentation(sphere, renModule)
renModule.StillRender()
下面我们根据这一段Python代码来分析,当数据已经处理完成之后的渲染的一个过程。
Connect建立服务器连接,这个不用赘述。
renModule = CreateRenderView()
这个函数是:
def CreateRenderView(session=None, **extraArgs):
"""Creates a render window on the particular session. If session
is not specified, then the active session is used, if available.
This method can also be used to initialize properties by passing
keyword arguments where the key is the name of the property. In addition
registrationGroup and registrationName (optional) can be specified (as
keyword arguments) to automatically register the proxy with the proxy
manager."""
return _create_view("RenderView", session, **extraArgs)
可以看到它直接调用了内部函数_create_view("RenderView", session, **extraArgs)
def _create_view(view_xml_name, session=None, **extraArgs):
"""Creates a view on the particular session. If session
is not specified, then the active session is used, if available.
This method can also be used to initialize properties by passing
keyword arguments where the key is the name of the property."""
if not session:
session = ActiveConnection.Session
if not session:
raise RuntimeError, "Cannot create view without session."
pxm = ProxyManager()
view_module = None
if view_xml_name:
view_module = CreateProxy("views", view_xml_name, session)
if not view_module:
return None
return _getPyProxy(view_module)
在这个函数中,session如果过没有会自动查找当前连接的活动session,前面没有,所以就是当前的ActiveConnection.Session。
pxm = ProxyManager()
这一句我们需要注意:
ProxyManager是一个类,它是对后台c++中的vtkSMProxyManager类的一个python封装。它大多数的方法都是使用的这个c++类的。且这是一个单例类。它的实例化方法就是获得当前 self.SMProxyManager = session.GetSessionProxyManager()的代理管理对象。所以这里的pxm就是一个全局的代理管理对象。这是在客户端的,通过它对所有的代理进行管理,在前端进行增删改查,后台就要做出相应的update()。在这里写下这个函数,应该是确认已初始化建立。
我们可以看到,这个函数,返回的是
return _getPyProxy(view_module)
在这之中的,view_module是由
CreateProxy("views", view_xml_name, session)
这个函数:
def CreateProxy(xml_group, xml_name, session=None):
"""Creates a proxy. If session is set, the proxy's session is
set accordingly. If session is None, the current Session is used, if
present. You should not have to use method normally. Instantiate the
appropriate class from the appropriate module, for example:
sph = servermanager.sources.SphereSource()"""
global ActiveConnection
if not session:
session = ActiveConnection.Session
if not session:
raise RuntimeError, "Cannot create objects without a session."
pxm = ProxyManager(session)
return pxm.NewProxy(xml_group, xml_name)
可以看到,“views”是xml_group的一个,xml_group一共有:“source”,“filters”,“representation”,“views”四种。这里根据前面的传值xml_name为:“RenderView”。
def NewProxy(self, group, name):
"""Creates a new proxy of given group and name and returns an SMProxy.
Note that this is a server manager object. You should normally create
proxies using the class objects. For example:
obj = servermanager.sources.SphereSource()"""
if not self.SMProxyManager:
return None
aProxy = self.SMProxyManager.NewProxy(group, name)
if not aProxy:
return None
aProxy.UnRegister(None)
return aProxy
vtkSMProxy* vtkSMProxyManager::NewProxy(const char* groupName,
const char* proxyName, const char* subProxyName)
{
if (vtkSMSessionProxyManager* pxm = this->GetActiveSessionProxyManager())
{
return pxm->NewProxy(groupName, proxyName, subProxyName);
}
vtkErrorMacro("No active session found.");
return NULL;
}
可以看到这个函数返回的是vtkSMSessionProxyManager* pxm = this->GetActiveSessionProxyManager(),GetActiveSessionProxyManager()也就是当前session的代理管理对象。赋值到vtkSMSessionProxyManager类的pxm上。
然后根据其:
pxm->NewProxy(groupName, proxyName, subProxyName);
方法去建立相应的代理对象:
vtkSMProxy* vtkSMSessionProxyManager::NewProxy(vtkPVXMLElement* pelement,
const char* groupname,
const char* proxyname,
const char* subProxyName)
{
vtkObject* object = 0;
vtksys_ios::ostringstream cname;
cname << "vtkSM" << pelement->GetName() << ends;
object = vtkPVInstantiator::CreateInstance(cname.str().c_str());
vtkSMProxy* proxy = vtkSMProxy::SafeDownCast(object);
if (proxy)
{
// XMLName/XMLGroup should be set before ReadXMLAttributes so sub proxy
// can be found based on their names when sent to the PM Side
proxy->SetXMLGroup(groupname);
proxy->SetXMLName(proxyname);
proxy->SetXMLSubProxyName(subProxyName);
proxy->SetSession(this->GetSession());
proxy->ReadXMLAttributes(this, pelement);
else
{
vtkWarningMacro("Creation of new proxy " << cname.str() << " failed ("
<< groupname << ", " << proxyname << ").");
}
return proxy;
}
在这个函数之前还有一个检测这个代理是否能够被建立的函数,去代理定义,xml文件中查找的一个函数,这里就不赘述,这个函数返回的是一个vtkSMProxy类的一个对象。并且设置了这个proxy的一些属性。
下面我们看
return _getPyProxy(view_module)
def _getPyProxy(smproxy, outputPort=0):
"""Returns a python wrapper for a server manager proxy. This method
first checks if there is already such an object by looking in the
_pyproxies group and returns it if found. Otherwise, it creates a
new one. Proxies register themselves in _pyproxies upon creation."""
if not smproxy:
return None
try:
# is argument is already a Proxy instance, this takes care of it.
return _getPyProxy(smproxy.SMProxy, outputPort)
except AttributeError:
pass
if (smproxy, outputPort) in _pyproxies:
return _pyproxies[(smproxy, outputPort)]()
xmlName = smproxy.GetXMLName()
if paraview.compatibility.GetVersion() >= 3.5:
if smproxy.GetXMLLabel():
xmlName = smproxy.GetXMLLabel()
classForProxy = _findClassForProxy(_make_name_valid(xmlName), smproxy.GetXMLGroup())
if classForProxy:
retVal = classForProxy(proxy=smproxy, port=outputPort)
else:
retVal = Proxy(proxy=smproxy, port=outputPort)
return retVal
这个函数也就是说,如果这个代理对象实例化了,那么对它子代理对象再进行实例化,没有,则实例化它。_pyproxies是一个代理集合,如果存在直接返回这个代理,没有则继续并且把这个代理对象注册到_pyproxies中。然后把这个新创建的proxy实例化并且返回。其实返回的还是就是这个代理对象。
所以我推测renMoudle其实就是一个“views”类的“RenderView"的代理对象
最后进行渲染,调用
renModule.StillRender()
但是找遍了整个servermanager.py文件,也没找到这个函数,所以去找vtkSMProxy类,但是在这个函数中也没有找到。
classForProxy = _findClassForProxy(_make_name_valid(xmlName), smproxy.GetXMLGroup())
所以我们看看这个函数:
def _findClassForProxy(xmlName, xmlGroup):
"""Given the xmlName for a proxy, returns a Proxy class. Note
that if there are duplicates, the first one is returned."""
global sources, filters, writers, rendering, animation, implicit_functions,\
piecewise_functions, extended_sources, misc
if not xmlName:
return None
if xmlGroup == "sources":
return sources.__dict__[xmlName]
elif xmlGroup == "filters":
return filters.__dict__[xmlName]
elif xmlGroup == "implicit_functions":
return implicit_functions.__dict__[xmlName]
elif xmlGroup == "piecewise_functions":
return piecewise_functions.__dict__[xmlName]
elif xmlGroup == "writers":
return writers.__dict__[xmlName]
elif xmlGroup == "extended_sources":
return extended_sources.__dict__[xmlName]
elif xmlName in rendering.__dict__:
return rendering.__dict__[xmlName]
elif xmlName in animation.__dict__:
return animation.__dict__[xmlName]
elif xmlName in misc.__dict__:
return misc.__dict__[xmlName]
else:
return None
不知道它是否属于,这里的xml_name为RenderView
rendering.__dict__:
所以,这里也不知道返回了啥。
如果找不到,则调用
retVal = Proxy(proxy=smproxy, port=outputPort)
Proxy是一个python类。它在这种情况下创建一个代理对象,它的self.SMProxy是view_module。
剩下的这两个方向都断了线