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