Salome HOME
Merge akl/tests_update: update tests
[modules/paravis.git] / src / PV_SWIG / VTKWrapping / pvsimple.py
1 # Copyright (C) 2010-2014  CEA/DEN, EDF R&D
2 #
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Lesser General Public
5 # License as published by the Free Software Foundation; either
6 # version 2.1 of the License, or (at your option) any later version.
7 #
8 # This library is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 # Lesser General Public License for more details.
12 #
13 # You should have received a copy of the GNU Lesser General Public
14 # License along with this library; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 #
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 #
19
20 r"""simple is a module for using paraview server manager in Python. It 
21 provides a simple convenience layer to functionality provided by the
22 C++ classes wrapped to Python as well as the servermanager module.
23
24 A simple example:
25   from paraview.simple import *
26
27   # Create a new sphere proxy on the active connection and register it
28   # in the sources group.
29   sphere = Sphere(ThetaResolution=16, PhiResolution=32)
30
31   # Apply a shrink filter
32   shrink = Shrink(sphere)
33   
34   # Turn the visiblity of the shrink object on.
35   Show(shrink)
36   
37   # Render the scene
38   Render()
39 """
40
41 import paravisSM
42
43 servermanager = paravisSM
44
45 def enableMultiServer():
46     servermanager.enableMultiServer()
47
48 def switchActiveConnection(newActiveConnection=None, ns=None):
49     if not ns:
50        ns = globals()
51     _remove_functions(ns)
52     servermanager.switchActiveConnection(newActiveConnection)
53     _add_functions(ns)
54
55 def Disconnect(ns=None, force=True):
56     if servermanager.ActiveConnection and (force or servermanager.MultiServerConnections == None):
57        if ns:
58           _remove_functions(ns)
59        _remove_functions(globals())
60        if not servermanager.fromGUI:
61           servermanager.ProxyManager().DisableStateUpdateNotification()
62           servermanager.ProxyManager().UnRegisterProxies()
63        active_objects.view = None
64        active_objects.source = None
65        servermanager.Disconnect()
66        if not servermanager.fromGUI:
67           import gc
68           gc.collect()
69
70 def Connect(ds_host=None, ds_port=11111, rs_host=None, rs_port=11111):
71     """Creates a connection to a server. Example usage:
72     > Connect("amber") # Connect to a single server at default port
73     > Connect("amber", 12345) # Connect to a single server at port 12345
74     > Connect("amber", 11111, "vis_cluster", 11111) # connect to data server, render server pair"""
75     Disconnect(globals(), False)
76     connection = servermanager.Connect(ds_host, ds_port, rs_host, rs_port)
77     _add_functions(globals())
78
79     servermanager.ProxyManager().DisableStateUpdateNotification()
80     servermanager.ProxyManager().UpdateFromRemote()
81     tk = servermanager.ProxyManager().GetProxy("timekeeper", "TimeKeeper")
82     if not tk:
83        try:
84            tk = servermanager.misc.TimeKeeper()
85            servermanager.ProxyManager().RegisterProxy("timekeeper", "TimeKeeper", tk)
86        except AttributeError:
87            print "Error: Could not create TimeKeeper"
88
89     scene = servermanager.ProxyManager().GetProxy("animation", "AnimationScene")
90     if not scene:
91        try:
92            scene = AnimationScene()
93            scene.TimeKeeper = tk
94        except NameError:
95            print "Error: Could not create AnimationScene"
96
97     servermanager.ProxyManager().EnableStateUpdateNotification()
98     servermanager.ProxyManager().TriggerStateUpdate()
99
100     return connection
101
102 def ReverseConnect(port=11111):
103     """Create a reverse connection to a server.  Listens on port and waits for
104     an incoming connection from the server."""
105     Disconnect(globals(), False)
106     connection = servermanager.ReverseConnect(port)
107     _add_functions(globals())
108
109     servermanager.ProxyManager().DisableStateUpdateNotification()
110     servermanager.ProxyManager().UpdateFromRemote()
111     tk = servermanager.ProxyManager().GetProxy("timekeeper", "TimeKeeper")
112     if not tk:
113        tk = servermanager.misc.TimeKeeper()
114        servermanager.ProxyManager().RegisterProxy("timekeeper", "TimeKeeper", tk)
115
116     scene = servermanager.ProxyManager().GetProxy("animation", "AnimationScene")
117     if not scene:
118        scene = AnimationScene()
119        scene.TimeKeeper = tk
120
121     servermanager.ProxyManager().EnableStateUpdateNotification()
122     servermanager.ProxyManager().TriggerStateUpdate()
123
124     return connection
125
126 def _create_view(view_xml_name):
127     "Creates and returns a 3D render view."
128     view = servermanager._create_view(view_xml_name)
129     servermanager.ProxyManager().RegisterProxy("views", \
130       "my_view%d" % _funcs_internals.view_counter, view)
131     active_objects.view = view
132     _funcs_internals.view_counter += 1
133
134     tk = servermanager.ProxyManager().GetProxiesInGroup("timekeeper").values()[0]
135     views = tk.Views
136     if not view in views:
137         views.append(view)
138     try:
139         scene = GetAnimationScene()
140         if not view in scene.ViewModules:
141             scene.ViewModules.append(view)
142     except servermanager.MissingProxy:
143         pass
144     return view
145
146 def CreateRenderView():
147     return _create_view("RenderView")
148
149 def CreateXYPlotView():
150     return _create_view("XYChartView")
151
152 def CreateBarChartView():
153     return _create_view("XYBarChartView")
154
155 def CreateComparativeRenderView():
156     return _create_view("ComparativeRenderView")
157
158 def CreateComparativeXYPlotView():
159     return _create_view("ComparativeXYPlotView")
160  
161 def CreateComparativeBarChartView():
162     return _create_view("ComparativeBarChartView")
163
164 def CreateParallelCoordinatesChartView():
165     return _create_view("ParallelCoordinatesChartView")
166
167 def Create2DRenderView():
168     return _create_view("2DRenderView")
169
170 def OpenDataFile(filename, **extraArgs):
171     """Creates a reader to read the give file, if possible.
172        This uses extension matching to determine the best reader possible.
173        If a reader cannot be identified, then this returns None."""
174     session = servermanager.ActiveConnection.Session
175     reader_factor = servermanager.vtkSMProxyManager.GetProxyManager().GetReaderFactory()
176     if reader_factor.GetNumberOfRegisteredPrototypes() == 0:
177       reader_factor.RegisterPrototypes(session, "sources")
178     first_file = filename
179     if type(filename) == list:
180         first_file = filename[0]
181     if not reader_factor.TestFileReadability(first_file, session):
182         msg = "File not readable: %s " % first_file
183         raise RuntimeError, msg
184     if not reader_factor.CanReadFile(first_file, session):
185         msg = "File not readable. No reader found for '%s' " % first_file
186         raise RuntimeError, msg
187     prototype = servermanager.ProxyManager().GetPrototypeProxy(
188       reader_factor.GetReaderGroup(), reader_factor.GetReaderName())
189     # [ABN]: bug fix for Christian VW (temporary - pvsimple should disappear soon) 
190     from paraview import make_name_valid  # make_name_valid is not in paravisSM
191     xml_name = make_name_valid(prototype.GetXMLLabel())
192     reader_func = _create_func(xml_name, servermanager.sources)
193     if prototype.GetProperty("FileNames"):
194       reader = reader_func(FileNames=filename, **extraArgs)
195     else :
196       reader = reader_func(FileName=filename, **extraArgs)
197     return reader
198
199 def CreateWriter(filename, proxy=None, **extraArgs):
200     """Creates a writer that can write the data produced by the source proxy in
201        the given file format (identified by the extension). If no source is
202        provided, then the active source is used. This doesn't actually write the
203        data, it simply creates the writer and returns it."""
204     if not filename:
205        raise RuntimeError, "filename must be specified"
206     session = servermanager.ActiveConnection.Session
207     writer_factory = servermanager.vtkSMProxyManager.GetProxyManager().GetWriterFactory()
208     if writer_factory.GetNumberOfRegisteredPrototypes() == 0:
209         writer_factory.RegisterPrototypes(session, "writers")
210     if not proxy:
211         proxy = GetActiveSource()
212     if not proxy:
213         raise RuntimeError, "Could not locate source to write"
214     writer_proxy = writer_factory.CreateWriter(filename, proxy.SMProxy, proxy.Port)
215     return servermanager._getPyProxy(writer_proxy)
216
217 def GetRenderView():
218     """Returns the active view if there is one. Else creates and returns a new view."""
219     view = active_objects.view
220     if not view:
221         # it's possible that there's no active view, but a render view exists.
222         # If so, locate that and return it (before trying to create a new one).
223         view = servermanager.GetRenderView()
224     if not view:
225         view = CreateRenderView()
226     return view
227
228 def GetRenderViews():
229     """Returns all render views as a list."""
230     return servermanager.GetRenderViews()
231
232 def GetRepresentation(proxy=None, view=None):
233     """Given a pipeline object and view, returns the corresponding representation object.
234     If pipeline object and view are not specified, active objects are used."""
235     if not view:
236         view = active_objects.view
237     if not proxy:
238         proxy = active_objects.source
239     rep = servermanager.GetRepresentation(proxy, view)
240     if not rep:
241         rep = servermanager.CreateRepresentation(proxy, view)
242         servermanager.ProxyManager().RegisterProxy("representations", \
243           "my_representation%d" % _funcs_internals.rep_counter, rep)
244         _funcs_internals.rep_counter += 1
245     return rep
246     
247 def GetDisplayProperties(proxy=None, view=None):
248     """Given a pipeline object and view, returns the corresponding representation object.
249     If pipeline object and/or view are not specified, active objects are used."""
250     return GetRepresentation(proxy, view)
251     
252 def Show(proxy=None, view=None, **params):
253     """Turns the visibility of a given pipeline object on in the given view.
254     If pipeline object and/or view are not specified, active objects are used."""
255     if proxy == None:
256         proxy = GetActiveSource()
257     if proxy == None:
258         raise RuntimeError, "Show() needs a proxy argument or that an active source is set."
259     if not view and not active_objects.view:
260         CreateRenderView()
261     rep = GetDisplayProperties(proxy, view)
262     if rep == None:
263         raise RuntimeError, "Could not create a representation object for proxy %s" % proxy.GetXMLLabel()
264     for param in params.keys():
265         setattr(rep, param, params[param])
266     rep.Visibility = 1
267     return rep
268
269 def Hide(proxy=None, view=None):
270     """Turns the visibility of a given pipeline object off in the given view.
271     If pipeline object and/or view are not specified, active objects are used."""
272     rep = GetDisplayProperties(proxy, view)
273     rep.Visibility = 0
274
275 def Render(view=None):
276     """Renders the given view (default value is active view)"""
277     if not view:
278         view = active_objects.view
279     view.StillRender()
280     if _funcs_internals.first_render:
281         # Not all views have a ResetCamera method
282         try:
283             view.ResetCamera()
284             view.StillRender()
285         except AttributeError: pass
286         _funcs_internals.first_render = False
287     return view
288         
289 def ResetCamera(view=None):
290     """Resets the settings of the camera to preserver orientation but include
291     the whole scene. If an argument is not provided, the active view is
292     used."""
293     if not view:
294         view = active_objects.view
295     if hasattr(view, "ResetCamera"):
296         view.ResetCamera()
297     if hasattr(view, "ResetDisplay"):
298         view.ResetDisplay()
299     Render(view)
300
301 def _DisableFirstRenderCameraReset():
302     """Disable the first render camera reset.  Normally a ResetCamera is called
303     automatically when Render is called for the first time after importing
304     this module."""
305     _funcs_internals.first_render = False
306
307 def SetProperties(proxy=None, **params):
308     """Sets one or more properties of the given pipeline object. If an argument
309     is not provided, the active source is used. Pass a list of property_name=value
310     pairs to this function to set property values. For example:
311      SetProperties(Center=[1, 2, 3], Radius=3.5)
312     """
313     if not proxy:
314         proxy = active_objects.source
315     for param in params.keys():
316         if not hasattr(proxy, param):
317             raise AttributeError("object has no property %s" % param)
318         setattr(proxy, param, params[param])
319
320 def GetProperty(*arguments, **keywords):
321     """Get one property of the given pipeline object. If keywords are used,
322        you can set the proxy and the name of the property that you want to get
323        like in the following example :
324             GetProperty({proxy=sphere, name="Radius"})
325        If it's arguments that are used, then you have two case:
326          - if only one argument is used that argument will be
327            the property name.
328          - if two arguments are used then the first one will be
329            the proxy and the second one the property name.
330        Several example are given below:
331            GetProperty({name="Radius"})
332            GetProperty({proxy=sphereProxy, name="Radius"})
333            GetProperty( sphereProxy, "Radius" )
334            GetProperty( "Radius" )
335     """
336     name = None
337     proxy = None
338     for key in keywords:
339         if key == "name":
340             name = keywords[key]
341         if key == "proxy":
342             proxy = keywords[key]
343     if len(arguments) == 1 :
344         name = arguments[0]
345     if len(arguments) == 2 :
346         proxy = arguments[0]
347         name  = arguments[1]
348     if not name:
349         raise RuntimeError, "Expecting at least a property name as input. Otherwise keyword could be used to set 'proxy' and property 'name'"
350     if not proxy:
351         proxy = active_objects.source
352     return proxy.GetProperty(name)
353
354 def SetDisplayProperties(proxy=None, view=None, **params):
355     """Sets one or more display properties of the given pipeline object. If an argument
356     is not provided, the active source is used. Pass a list of property_name=value
357     pairs to this function to set property values. For example:
358      SetProperties(Color=[1, 0, 0], LineWidth=2)
359     """
360     rep = GetDisplayProperties(proxy, view)
361     SetProperties(rep, **params)
362
363 def SetViewProperties(view=None, **params):
364     """Sets one or more properties of the given view. If an argument
365     is not provided, the active view is used. Pass a list of property_name=value
366     pairs to this function to set property values. For example:
367      SetProperties(Background=[1, 0, 0], UseImmediateMode=0)
368     """
369     if not view:
370         view = active_objects.view
371     SetProperties(view, **params)
372
373 def RenameSource(newName, proxy=None):
374     """Renames the given source.  If the given proxy is not registered
375     in the sources group this method will have no effect.  If no source is
376     provided, the active source is used."""
377     if not proxy:
378         proxy = active_objects.source
379     pxm = servermanager.ProxyManager()
380     oldName = pxm.GetProxyName("sources", proxy)
381     if oldName:
382       pxm.RegisterProxy("sources", newName, proxy)
383       pxm.UnRegisterProxy("sources", oldName, proxy)
384
385 def FindSource(name):
386     return servermanager.ProxyManager().GetProxy("sources", name)
387
388 def GetSources():
389     """Given the name of a source, return its Python object."""
390     return servermanager.ProxyManager().GetProxiesInGroup("sources")
391
392 def GetRepresentations():
393     """Returns all representations (display properties)."""
394     return servermanager.ProxyManager().GetProxiesInGroup("representations")
395
396 def UpdatePipeline(time=None, proxy=None):
397     """Updates (executes) the given pipeline object for the given time as
398     necessary (i.e. if it did not already execute). If no source is provided,
399     the active source is used instead."""
400     if not proxy:
401         proxy = active_objects.source
402     if time:
403         proxy.UpdatePipeline(time)
404     else:
405         proxy.UpdatePipeline()
406
407 def Delete(proxy=None):
408     """Deletes the given pipeline object or the active source if no argument
409     is specified."""
410     if not proxy:
411         proxy = active_objects.source
412     # Unregister any helper proxies stored by a vtkSMProxyListDomain
413     for prop in proxy:
414         listdomain = prop.GetDomain('proxy_list')
415         if listdomain:
416             if listdomain.GetClassName() != 'vtkSMProxyListDomain':
417                 continue
418             group = "pq_helper_proxies." + proxy.GetGlobalIDAsString()
419             for i in xrange(listdomain.GetNumberOfProxies()):
420                 pm = servermanager.ProxyManager()
421                 iproxy = listdomain.GetProxy(i)
422                 name = pm.GetProxyName(group, iproxy)
423                 if iproxy and name:
424                     pm.UnRegisterProxy(group, name, iproxy)
425                     
426     # Remove source/view from time keeper
427     tk = servermanager.ProxyManager().GetProxiesInGroup("timekeeper").values()[0]
428     if isinstance(proxy, servermanager.SourceProxy):
429         try:
430             idx = tk.TimeSources.index(proxy)
431             del tk.TimeSources[idx]
432         except ValueError:
433             pass
434     else:
435         try:
436             idx = tk.Views.index(proxy)
437             del tk.Views[idx]
438         except ValueError:
439             pass
440     servermanager.UnRegister(proxy)
441     
442     # If this is a representation, remove it from all views.
443     if proxy.SMProxy.IsA("vtkSMRepresentationProxy") or \
444         proxy.SMProxy.IsA("vtkSMNewWidgetRepresentationProxy"):
445         for view in GetRenderViews():
446             view.Representations.remove(proxy)
447     # If this is a source, remove the representation iff it has no consumers
448     # Also change the active source if necessary
449     elif proxy.SMProxy.IsA("vtkSMSourceProxy"):
450         sources = servermanager.ProxyManager().GetProxiesInGroup("sources")
451         for i in range(proxy.GetNumberOfConsumers()):
452             if proxy.GetConsumerProxy(i) in sources:
453                 raise RuntimeError("Source has consumers. It cannot be deleted " +
454                   "until all consumers are deleted.")
455         #VSV:==
456         if proxy.IsSame(GetActiveSource()):
457             if hasattr(proxy, "Input") and proxy.Input:
458                 if isinstance(proxy.Input, servermanager.Proxy):
459                     SetActiveSource(proxy.Input)
460                 else:
461                     SetActiveSource(proxy.Input[0])
462             else: SetActiveSource(None)
463         for rep in GetRepresentations().values():
464             #VSV:==
465             if rep.Input.IsSame(proxy):
466                 Delete(rep)
467     # Change the active view if necessary
468     elif proxy.SMProxy.IsA("vtkSMRenderViewProxy"):
469         ##VSV:==
470         if proxy.IsSame(GetActiveView()):
471             if len(GetRenderViews()) > 0:
472                 SetActiveView(GetRenderViews()[0])
473             else:
474                 SetActiveView(None)
475
476 def CreateLookupTable(**params):
477     """Create and return a lookup table.  Optionally, parameters can be given
478     to assign to the lookup table.
479     """
480     lt = servermanager.rendering.PVLookupTable()
481     servermanager.Register(lt)
482     SetProperties(lt, **params)
483     return lt
484
485 def CreatePiecewiseFunction(**params):
486     """Create and return a piecewise function.  Optionally, parameters can be
487     given to assign to the piecewise function.
488     """
489     pfunc = servermanager.piecewise_functions.PiecewiseFunction()
490     servermanager.Register(pfunc)
491     SetProperties(pfunc, **params)
492     return pfunc
493
494 def GetLookupTableForArray(arrayname, num_components, **params):
495     """Used to get an existing lookuptable for a array or to create one if none
496     exists. Keyword arguments can be passed in to initialize the LUT if a new
497     one is created."""
498     proxyName = "%d.%s.PVLookupTable" % (int(num_components), arrayname)
499     lut = servermanager.ProxyManager().GetProxy("lookup_tables", proxyName)
500     if lut:
501         return lut
502     # No LUT exists for this array, create a new one.
503     # TODO: Change this to go a LookupTableManager that is shared with the GUI,
504     # so that the GUI and python end up create same type of LUTs. For now,
505     # python will create a Blue-Red LUT, unless overridden by params.
506     lut = servermanager.rendering.PVLookupTable(
507             ColorSpace="HSV", RGBPoints=[0, 0, 0, 1, 1, 1, 0, 0])
508     SetProperties(lut, **params)
509     servermanager.Register(lut, registrationName=proxyName)
510     return lut
511
512 def CreateScalarBar(**params):
513     """Create and return a scalar bar widget.  The returned widget may
514     be added to a render view by appending it to the view's representations
515     The widget must have a valid lookup table before it is added to a view.
516     It is possible to pass the lookup table (and other properties) as arguments
517     to this method:
518     
519     lt = MakeBlueToRedLt(3.5, 7.5)
520     bar = CreateScalarBar(LookupTable=lt, Title="Velocity")
521     GetRenderView().Representations.append(bar)
522     
523     By default the returned widget is selectable and resizable.
524     """
525     sb = servermanager.rendering.ScalarBarWidgetRepresentation()
526     servermanager.Register(sb)
527     sb.Selectable = 1
528     sb.Resizable = 1
529     sb.Enabled = 1
530     sb.Title = "Scalars"
531     SetProperties(sb, **params)
532     return sb
533
534 # TODO: Change this to take the array name and number of components. Register 
535 # the lt under the name ncomp.array_name
536 def MakeBlueToRedLT(min, max):
537     # Define RGB points. These are tuples of 4 values. First one is
538     # the scalar values, the other 3 the RGB values. 
539     rgbPoints = [min, 0, 0, 1, max, 1, 0, 0]
540     return CreateLookupTable(RGBPoints=rgbPoints, ColorSpace="HSV")
541     
542 def _find_writer(filename):
543     """Internal function."""
544     extension = None
545     parts = filename.split('.')
546     if len(parts) > 1:
547         extension = parts[-1]
548     else:
549         raise RuntimeError, "Filename has no extension, please specify a write"
550         
551     if extension == 'png':
552         return 'vtkPNGWriter'
553     elif extension == 'bmp':
554         return 'vtkBMPWriter'
555     elif extension == 'ppm':
556         return 'vtkPNMWriter'
557     elif extension == 'tif' or extension == 'tiff':
558         return 'vtkTIFFWriter'
559     elif extension == 'jpg' or extension == 'jpeg':
560         return 'vtkJPEGWriter'
561     else:
562         raise RuntimeError, "Cannot infer filetype from extension:", extension
563
564 def AddCameraLink(viewProxy, viewProxyOther, linkName):
565     """Create a camera link between two view proxies.  A name must be given
566     so that the link can be referred to by name.  If a link with the given
567     name already exists it will be removed first."""
568     if not viewProxyOther: viewProxyOther = GetActiveView()
569     link = servermanager.vtkSMCameraLink()
570     link.AddLinkedProxy(viewProxy.SMProxy, 1)
571     link.AddLinkedProxy(viewProxyOther.SMProxy, 2)
572     link.AddLinkedProxy(viewProxyOther.SMProxy, 1)
573     link.AddLinkedProxy(viewProxy.SMProxy, 2)
574     RemoveCameraLink(linkName)
575     servermanager.ProxyManager().RegisterLink(linkName, link)
576
577 def RemoveCameraLink(linkName):
578     """Remove a camera link with the given name."""
579     servermanager.ProxyManager().UnRegisterLink(linkName)
580
581 def WriteImage(filename, view=None, **params):
582     """Saves the given view (or the active one if none is given) as an
583     image. Optionally, you can specify the writer and the magnification
584     using the Writer and Magnification named arguments. For example:
585      WriteImage("foo.mypng", aview, Writer=vtkPNGWriter, Magnification=2)
586     If no writer is provided, the type is determined from the file extension.
587     Currently supported extensions are png, bmp, ppm, tif, tiff, jpg and jpeg.
588     The writer is a VTK class that is capable of writing images.
589     Magnification is used to determine the size of the written image. The size
590     is obtained by multiplying the size of the view with the magnification.
591     Rendering may be done using tiling to obtain the correct size without
592     resizing the view."""
593     if not view:
594         view = active_objects.view
595     writer = None
596     if params.has_key('Writer'):
597         writer = params['Writer']
598     mag = 1
599     if params.has_key('Magnification'):
600         mag = int(params['Magnification'])
601     if not writer:
602         writer = _find_writer(filename)
603     view.WriteImage(filename, writer, mag)
604
605 def AnimateReader(reader=None, view=None, filename=None):
606     """This is a utility function that, given a reader and a view
607     animates over all time steps of the reader. If the optional
608     filename is provided, a movie is created (type depends on the
609     extension of the filename."""
610     if not reader:
611         reader = active_objects.source
612     if not view:
613         view = active_objects.view
614         
615     return servermanager.AnimateReader(reader, view, filename)
616
617
618 def _create_func(key, module):
619     """Internal function."""
620
621     def CreateObject(*input, **params):
622         """This function creates a new proxy. For pipeline objects that accept inputs,
623         all non-keyword arguments are assumed to be inputs. All keyword arguments are
624         assumed to be property,value pairs and are passed to the new proxy."""
625
626         # Instantiate the actual object from the given module.
627         px = module.__dict__[key]()
628
629         # Make sure non-keyword arguments are valid
630         for inp in input:
631             if inp != None and not isinstance(inp, servermanager.Proxy):
632                 if px.GetProperty("Input") != None:
633                     raise RuntimeError, "Expecting a proxy as input."
634                 else:
635                     raise RuntimeError, "This function does not accept non-keyword arguments."
636
637         # Assign inputs
638         if px.GetProperty("Input") != None:
639             if len(input) > 0:
640                 px.Input = input
641             else:
642                 # If no input is specified, try the active pipeline object
643                 if px.GetProperty("Input").GetRepeatable() and active_objects.get_selected_sources():
644                     px.Input = active_objects.get_selected_sources()
645                 elif active_objects.source:
646                     px.Input = active_objects.source
647         else:
648             if len(input) > 0:
649                 raise RuntimeError, "This function does not expect an input."
650
651         registrationName = None
652         for nameParam in ['registrationName', 'guiName']:
653           if nameParam in params:
654               registrationName = params[nameParam]
655               del params[nameParam]
656
657         # Pass all the named arguments as property,value pairs
658         for param in params.keys():
659             setattr(px, param, params[param])
660
661         try:
662             # Register the proxy with the proxy manager.
663             if registrationName:
664                 group, name = servermanager.Register(px, registrationName=registrationName)
665             else:
666                 group, name = servermanager.Register(px)
667
668
669             # Register pipeline objects with the time keeper. This is used to extract time values
670             # from sources. NOTE: This should really be in the servermanager controller layer.
671             if group == "sources":
672                 has_tk = True
673                 try:
674                     tk = servermanager.ProxyManager().GetProxiesInGroup("timekeeper").values()[0]
675                 except IndexError:
676                     has_tk = False
677                 if has_tk:
678                     sources = tk.TimeSources
679                     if not px in sources:
680                         sources.append(px)
681
682                 active_objects.source = px
683         except servermanager.MissingRegistrationInformation:
684             pass
685
686         return px
687
688     return CreateObject
689
690 def _create_doc(new, old):
691     """Internal function."""
692     import string
693     res = ""
694     for doc in (new, old):
695         ts = []
696         strpd = doc.split('\n')
697         for s in strpd:
698             ts.append(s.lstrip())
699         res += string.join(ts)
700         res += '\n'
701     return res
702     
703 def _func_name_valid(name):
704     """Internal function."""
705     valid = True
706     for c in name:
707         if c == '(' or c ==')':
708             valid = False
709             break
710     return valid
711
712 def _add_functions(g):
713     activeModule = servermanager.ActiveConnection.Modules
714     for m in [activeModule.filters, activeModule.sources,
715               activeModule.writers, activeModule.animation]:
716         dt = m.__dict__
717         for key in dt.keys():
718             cl = dt[key]
719             if not isinstance(cl, str):
720                 if not key in g and _func_name_valid(key):
721                     g[key] = _create_func(key, m)
722                     exec "g[key].__doc__ = _create_doc(m.%s.__doc__, g[key].__doc__)" % key
723
724 def _remove_functions(g):
725     list = []
726     if servermanager.ActiveConnection:
727        list = [m for m in dir(servermanager.ActiveConnection.Modules) if m[0] != '_']
728
729     for m in list:
730         dt = servermanager.ActiveConnection.Modules.__dict__[m].__dict__
731         for key in dt.keys():
732             cl = dt[key]
733             if not isinstance(cl, str) and g.has_key(key):
734                 g.pop(key)
735                 #print "remove %s function" % key
736
737 def GetActiveView():
738     """Returns the active view."""
739     return active_objects.view
740     
741 def SetActiveView(view):
742     """Sets the active view."""
743     active_objects.view = view
744     
745 def GetActiveSource():
746     """Returns the active source."""
747     return active_objects.source
748     
749 def SetActiveSource(source):
750     """Sets the active source."""
751     active_objects.source = source
752     
753 def GetActiveCamera():
754     """Returns the active camera for the active view. The returned object
755     is an instance of vtkCamera."""
756     return GetActiveView().GetActiveCamera()
757
758 def GetAnimationScene():
759     """Returns the application-wide animation scene. ParaView has only one
760     global animation scene. This method provides access to that. Users are
761     free to create additional animation scenes directly, but those scenes
762     won't be shown in the ParaView GUI."""
763     animation_proxies = servermanager.ProxyManager().GetProxiesInGroup("animation")
764     scene = None
765     for aProxy in animation_proxies.values():
766         if aProxy.GetXMLName() == "AnimationScene":
767             scene = aProxy
768             break
769     if not scene:
770         raise servermanager.MissingProxy, "Could not locate global AnimationScene."
771     return scene
772
773 def WriteAnimation(filename, **params):
774     """Writes the current animation as a file. Optionally one can specify
775     arguments that qualify the saved animation files as keyword arguments.
776     Accepted options are as follows:
777     * Magnification (integer) : set the maginification factor for the saved
778       animation.
779     * Quality (0 [worst] or 1 or 2 [best]) : set the quality of the generated
780       movie (if applicable).
781     * Subsampling (integer) : setting whether the movie encoder should use
782       subsampling of the chrome planes or not, if applicable. Since the human
783       eye is more sensitive to brightness than color variations, subsampling
784       can be useful to reduce the bitrate. Default value is 0.
785     * BackgroundColor (3-tuple of doubles) : set the RGB background color to
786       use to fill empty spaces in the image.
787     * FrameRate (double): set the frame rate (if applicable)."""
788     scene = GetAnimationScene()
789     # ensures that the TimeKeeper track is created.
790     GetTimeTrack()
791     iw = servermanager.vtkSMAnimationSceneImageWriter()
792     iw.SetAnimationScene(scene.SMProxy)
793     iw.SetFileName(filename)
794     if params.has_key("Magnification"):
795         iw.SetMagnification(int(params["Magnification"]))
796     if params.has_key("Quality"):
797         iw.SetQuality(int(params["Quality"]))
798     if params.has_key("Subsampling"):
799         iw.SetSubsampling(int(params["Subsampling"]))
800     if params.has_key("BackgroundColor"):
801         iw.SetBackgroundColor(params["BackgroundColor"])
802     if params.has_key("FrameRate"):
803         iw.SetFrameRate(float(params["FrameRate"]))
804     iw.Save()
805
806 def _GetRepresentationAnimationHelper(sourceproxy):
807     """Internal method that returns the representation animation helper for a
808        source proxy. It creates a new one if none exists."""
809     # ascertain that proxy is a source proxy
810     if not sourceproxy in GetSources().values():
811         return None
812     for proxy in servermanager.ProxyManager():
813         if proxy.GetXMLName() == "RepresentationAnimationHelper" and\
814            proxy.GetProperty("Source").IsProxyAdded(sourceproxy.SMProxy):
815              return proxy
816     # create a new helper
817     proxy = servermanager.misc.RepresentationAnimationHelper(
818       Source=sourceproxy)
819     servermanager.ProxyManager().RegisterProxy(
820       "pq_helper_proxies.%s" % sourceproxy.GetGlobalIDAsString(),
821       "RepresentationAnimationHelper", proxy)
822     return proxy
823
824 def GetAnimationTrack(propertyname_or_property, index=None, proxy=None):
825     """Returns an animation cue for the property. If one doesn't exist then a
826     new one will be created.
827     Typical usage:
828         track = GetAnimationTrack("Center", 0, sphere) or
829         track = GetAnimationTrack(sphere.GetProperty("Radius")) or
830
831         # this returns the track to animate visibility of the active source in
832         # all views.
833         track = GetAnimationTrack("Visibility")
834
835      For animating properties on implicit planes etc., use the following
836      signatures:
837         track = GetAnimationTrack(slice.SliceType.GetProperty("Origin"), 0) or
838         track = GetAnimationTrack("Origin", 0, slice.SliceType)
839
840     """
841     if not proxy:
842         proxy = GetActiveSource()
843     if not isinstance(proxy, servermanager.Proxy):
844         raise TypeError, "proxy must be a servermanager.Proxy instance"
845     if isinstance(propertyname_or_property, str):
846         propertyname = propertyname_or_property
847     elif isinstance(propertyname_or_property, servermanager.Property):
848         prop = propertyname_or_property
849         propertyname = prop.Name
850         proxy = prop.Proxy
851     else:
852         raise TypeError, "propertyname_or_property must be a string or servermanager.Property"
853
854     # To handle the case where the property is actually a "display" property, in
855     # which case we are actually animating the "RepresentationAnimationHelper"
856     # associated with the source.
857     if propertyname in ["Visibility", "Opacity"]:
858         proxy = _GetRepresentationAnimationHelper(proxy)
859     if not proxy or not proxy.GetProperty(propertyname):
860         raise AttributeError, "Failed to locate property %s" % propertyname
861
862     scene = GetAnimationScene()
863     for cue in scene.Cues:
864         try:
865             if cue.AnimatedProxy.IsSame(proxy) and\
866                cue.AnimatedPropertyName == propertyname:
867                 if index == None or index.IsSame(cue.AnimatedElement): ##index == cue.AnimatedElement:
868                     return cue
869         except AttributeError:
870             pass
871
872     # matching animation track wasn't found, create a new one.
873     cue = KeyFrameAnimationCue()
874     cue.AnimatedProxy = proxy
875     cue.AnimatedPropertyName = propertyname
876     if index != None:
877         cue.AnimatedElement = index
878     scene.Cues.append(cue)
879     return cue
880
881 def GetCameraTrack(view=None):
882     """Returns the camera animation track for the given view. If no view is
883     specified, active view will be used. If no exisiting camera animation track
884     is found, a new one will be created."""
885     if not view:
886         view = GetActiveView()
887     if not view:
888         raise ValueError, "No view specified"
889     scene = GetAnimationScene()
890     for cue in scene.Cues:
891         if cue.AnimatedProxy.IsSame(view) and\
892            cue.GetXMLName() == "CameraAnimationCue":
893             return cue
894     # no cue was found, create a new one.
895     cue = CameraAnimationCue()
896     cue.AnimatedProxy = view
897     scene.Cues.append(cue)
898     return cue
899
900 def GetTimeTrack():
901     """Returns the animation track used to control the time requested from all
902     readers/filters during playback.
903     This is the "TimeKeeper - Time" track shown in ParaView's 'Animation View'.
904     If none exists, a new one will be created."""
905     scene = GetAnimationScene()
906     tk = scene.TimeKeeper
907     for cue in scene.Cues:
908         if cue.GetXMLName() == "TimeAnimationCue" and cue.AnimatedProxy.IsSame(tk)\
909             and cue.AnimatedPropertyName == "Time":
910             return cue
911     # no cue was found, create a new one.
912     cue = TimeAnimationCue()
913     cue.AnimatedProxy = tk
914     cue.AnimatedPropertyName = "Time"
915     scene.Cues.append(cue)
916     return cue
917
918 def LoadXML(xmlstring, ns=None):
919     """Given a server manager XML as a string, parse and process it.
920     If you loaded the simple module with from paraview.simple import *,
921     make sure to pass globals() as the second arguments:
922     LoadXML(xmlstring, globals())
923     Otherwise, the new functions will not appear in the global namespace."""
924     if not ns:
925         ns = globals()
926     servermanager.LoadXML(xmlstring)
927     _add_functions(ns)
928
929 def LoadPlugin(filename, remote=True, ns=None):
930     """Loads a ParaView plugin and updates this module with new constructors
931     if any. The remote argument (default to True) is to specify whether 
932     the plugin will be loaded on client (remote=False) or on server (remote=True).
933     If you loaded the simple module with from paraview.simple import *,
934     make sure to pass globals() as an argument:
935     LoadPlugin("myplugin", False, globals()), to load on client;
936     LoadPlugin("myplugin", True, globals()), to load on server; 
937     LoadPlugin("myplugin", ns=globals()), to load on server.
938     Otherwise, the new functions will not appear in the global namespace."""
939     
940     if not ns:
941         ns = globals()
942     servermanager.LoadPlugin(filename, remote)
943     _add_functions(ns)
944
945 def LoadDistributedPlugin(pluginname, remote=True, ns=None):
946     """Loads a plugin that's distributed with the executable. This uses the
947     information known about plugins distributed with ParaView to locate the
948     shared library for the plugin to load. Raises a RuntimeError if the plugin
949     was not found."""
950     if not servermanager.ActiveConnection:
951         raise RuntimeError, "Cannot load a plugin without a session."
952     plm = servermanager.vtkSMProxyManager.GetProxyManager().GetPluginManager()
953     if remote:
954         session = servermanager.ActiveConnection.Session
955         info = plm.GetRemoteInformation(session)
956     else:
957         info = plm.GetLocalInformation()
958     for cc in range(0, info.GetNumberOfPlugins()):
959         if info.GetPluginName(cc) == pluginname:
960             return LoadPlugin(info.GetPluginFileName(cc), remote, ns)
961     raise RuntimeError, "Plugin '%s' not found" % pluginname
962
963 def GetLayouts():
964     """Returns the layout proxies on the active session.
965     Layout proxies are used to place views in a grid."""
966     return servermanager.ProxyManager().GetProxiesInGroup("layouts")
967
968 def GetLayout(view=None):
969     """Return the layout containing the give view, if any.
970     If no view is specified, active view is used.
971     """
972     if not view:
973         view = GetActiveView()
974     if not view:
975         raise RuntimeError, "No active view was found."
976     layouts = GetLayouts()
977     for layout in layouts.values():
978         if layout.GetViewLocation(view) != -1:
979             return layout
980     return None
981
982
983 def SelectCells(query=None, proxy=None):
984     """Select cells satisfying the query. If query is None, then all cells are
985        selected. If proxy is None, then the active source is used."""
986     if not proxy:
987         proxy = GetActiveSource()
988     if not proxy:
989         raise RuntimeError, "No active source was found."
990
991     if not query:
992         # This ends up being true for all cells.
993         query = "id >= 0"
994
995     # Note, selSource is not registered with the proxy manager.
996     selSource = servermanager.sources.SelectionQuerySource()
997     selSource.FieldType = "CELL"
998     selSource.QueryString = str(query)
999     proxy.SMProxy.SetSelectionInput(proxy.Port, selSource.SMProxy, 0)
1000     return selSource
1001
1002 def ClearSelection(proxy=None):
1003     """Clears the selection on the active source."""
1004     if not proxy:
1005         proxy = GetActiveSource()
1006     if not proxy:
1007         raise RuntimeError, "No active source was found."
1008     proxy.SMProxy.SetSelectionInput(proxy.Port, None, 0)
1009
1010 class ActiveObjects(object):
1011     """This class manages the active objects (source and view). The active
1012     objects are shared between Python and the user interface. This class
1013     is for internal use. Use the Set/Get methods for setting and getting
1014     active objects."""
1015     def __get_selection_model(self, name, session=None):
1016         "Internal method."
1017         if session and not servermanager.ActiveConnection.Session.IsSame(session):
1018             raise RuntimeError, "Try to set an active object with invalid active connection."
1019         pxm = servermanager.ProxyManager(session)
1020         model = pxm.GetSelectionModel(name)
1021         if not model:
1022             model = servermanager.vtkSMProxySelectionModel()
1023             pxm.RegisterSelectionModel(name, model)
1024         return model
1025
1026     def set_view(self, view):
1027         "Sets the active view."
1028         active_view_model = self.__get_selection_model("ActiveView")
1029         if view:
1030             active_view_model = self.__get_selection_model("ActiveView", view.GetSession())
1031             active_view_model.SetCurrentProxy(view.SMProxy, 0)
1032         else:
1033             active_view_model = self.__get_selection_model("ActiveView")
1034             active_view_model.SetCurrentProxy(None, 0)
1035
1036     def get_view(self):
1037         "Returns the active view."
1038         return servermanager._getPyProxy(
1039             self.__get_selection_model("ActiveView").GetCurrentProxy())
1040
1041     def set_source(self, source):
1042         "Sets the active source."
1043         active_sources_model = self.__get_selection_model("ActiveSources")
1044         if source:
1045             # 3 == CLEAR_AND_SELECT
1046             active_sources_model = self.__get_selection_model("ActiveSources", source.GetSession())
1047             active_sources_model.SetCurrentProxy(source.SMProxy, 3)
1048         else:
1049             active_sources_model = self.__get_selection_model("ActiveSources")
1050             active_sources_model.SetCurrentProxy(None, 3)
1051
1052     def __convert_proxy(self, px):
1053         "Internal method."
1054         if not px:
1055             return None
1056         if px.IsA("vtkSMSourceProxy"):
1057             return servermanager._getPyProxy(px)
1058         else:
1059             return servermanager.OutputPort(
1060               servermanager._getPyProxy(px.GetSourceProxy()),
1061               px.GetPortIndex())
1062         
1063     def get_source(self):
1064         "Returns the active source."
1065         return self.__convert_proxy(
1066           self.__get_selection_model("ActiveSources").GetCurrentProxy())
1067
1068     def get_selected_sources(self):
1069         "Returns the set of sources selected in the pipeline browser."
1070         model = self.__get_selection_model("ActiveSources")
1071         proxies = []
1072         for i in xrange(model.GetNumberOfSelectedProxies()):
1073             proxies.append(self.__convert_proxy(model.GetSelectedProxy(i)))
1074         return proxies
1075
1076     view = property(get_view, set_view)
1077     source = property(get_source, set_source)
1078
1079 class _funcs_internals:
1080     """Internal class."""
1081     first_render = True
1082     view_counter = 0
1083     rep_counter = 0
1084
1085 def demo1():
1086     """Simple demo that create the following pipeline
1087     sphere - shrink - \
1088                        - append
1089     cone            - /
1090     """
1091     # Create a sphere of radius = 2, theta res. = 32
1092     # This object becomes the active source.
1093     ss = Sphere(Radius=2, ThetaResolution=32)
1094     # Apply the shrink filter. The Input property is optional. If Input
1095     # is not specified, the filter is applied to the active source.
1096     shr = Shrink(Input=ss)
1097     # Create a cone source.
1098     cs = Cone()
1099     # Append cone and shrink
1100     app = AppendDatasets()
1101     app.Input = [shr, cs]
1102     # Show the output of the append filter. The argument is optional
1103     # as the app filter is now the active object.
1104     Show(app)
1105     # Render the default view.
1106     Render()
1107
1108 def demo2(fname="/Users/berk/Work/ParaView/ParaViewData/Data/disk_out_ref.ex2"):
1109     """This demo shows the use of readers, data information and display
1110     properties."""
1111     
1112     # Create the exodus reader and specify a file name
1113     reader = ExodusIIReader(FileName=fname)
1114     # Get the list of point arrays.
1115     avail = reader.PointVariables.Available
1116     print avail
1117     # Select all arrays
1118     reader.PointVariables = avail
1119
1120     # Turn on the visibility of the reader
1121     Show(reader)
1122     # Set representation to wireframe
1123     SetDisplayProperties(Representation = "Wireframe")
1124     # Black background is not pretty
1125     SetViewProperties(Background = [0.4, 0.4, 0.6])
1126     Render()
1127     # Change the elevation of the camera. See VTK documentation of vtkCamera
1128     # for camera parameters.
1129     # NOTE: THIS WILL BE SIMPLER
1130     GetActiveCamera().Elevation(45)
1131     Render()
1132     # Now that the reader executed, let's get some information about it's
1133     # output.
1134     pdi = reader[0].PointData
1135     # This prints a list of all read point data arrays as well as their
1136     # value ranges.
1137     print 'Number of point arrays:', len(pdi)
1138     for i in range(len(pdi)):
1139         ai = pdi[i]
1140         print "----------------"
1141         print "Array:", i, " ", ai.Name, ":"
1142         numComps = ai.GetNumberOfComponents()
1143         print "Number of components:", numComps
1144         for j in range(numComps):
1145             print "Range:", ai.GetRange(j)
1146     # White is boring. Let's color the geometry using a variable.
1147     # First create a lookup table. This object controls how scalar
1148     # values are mapped to colors. See VTK documentation for
1149     # details.
1150     # Map min (0.00678) to blue, max (0.0288) to red
1151     SetDisplayProperties(LookupTable = MakeBlueToRedLT(0.00678, 0.0288))
1152     # Color by point array called Pres
1153     SetDisplayProperties(ColorAttributeType = "POINT_DATA")
1154     SetDisplayProperties(ColorArrayName = "Pres")
1155     Render()
1156
1157 def PrintTrace():
1158     print paravisSM.myParavis.GetTrace()
1159
1160 def SaveTrace(fileName):
1161     paravisSM.myParavis.SaveTrace(fileName)
1162
1163
1164 if not servermanager.ActiveConnection:
1165     Connect()
1166 else:
1167     _add_functions(globals())
1168
1169 def ImportFile(theFileName):
1170     paravisSM.ImportFile(theFileName)
1171
1172 active_objects = ActiveObjects()
1173 active_objects.view = GetRenderView()