]> SALOME platform Git repositories - modules/paravis.git/blob - src/PV_SWIG/paravisSM.py
Salome HOME
Merge from V6_main_20120808 08Aug12
[modules/paravis.git] / src / PV_SWIG / paravisSM.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"""servermanager is a module for using paraview server manager in Python.
21 One can always use the server manager API directly. However, this module
22 provides an interface easier to use from Python by wrapping several VTK
23 classes around Python classes.
24
25 Note that, upon load, this module will create several sub-modules: sources,
26 filters and rendering. These modules can be used to instantiate specific
27 proxy types. For a list, try "dir(servermanager.sources)"
28
29 A simple example:
30   from paraview.servermanager import *
31
32   # Creates a new built-in session and makes it the active session.
33   Connect()
34
35   # Creates a new render view on the active session.
36   renModule = CreateRenderView()
37
38   # Create a new sphere proxy on the active session and register it
39   # in the sources group.
40   sphere = sources.SphereSource(registrationGroup="sources", ThetaResolution=16, PhiResolution=32)
41
42   # Create a representation for the sphere proxy and adds it to the render
43   # module.
44   display = CreateRepresentation(sphere, renModule)
45
46   renModule.StillRender()
47 """
48
49
50
51 import re, os, new, sys
52 from paravis import *
53
54
55
56 def _wrap_property(proxy, smproperty):
57     """ Internal function.
58     Given a server manager property and its domains, returns the
59     appropriate python object.
60     """
61     property = None
62     if smproperty.IsA("vtkSMStringVectorProperty"):
63         al = smproperty.GetDomain("array_list")
64         if  al and al.IsA("vtkSMArraySelectionDomain") and \
65             smproperty.GetRepeatable():
66             property = ArrayListProperty(proxy, smproperty)
67         elif al and al.IsA("vtkSMArrayListDomain") and smproperty.GetNumberOfElements() == 5:
68             property = ArraySelectionProperty(proxy, smproperty)
69         else:
70             iter = smproperty.NewDomainIterator()
71             isFileName = False
72             while not iter.IsAtEnd():
73                 # Refer to BUG #9710 to see why optional domains need to be
74                 # ignored.
75                 if iter.GetDomain().IsA("vtkSMFileListDomain") and \
76                   iter.GetDomain().GetIsOptional() == 0 :
77                     isFileName = True
78                     break
79                 iter.Next()
80             iter.UnRegister(None)
81             if isFileName:
82                 property = FileNameProperty(proxy, smproperty)
83             elif _make_name_valid(smproperty.GetXMLLabel()) == 'ColorArrayName':
84                 property = ColorArrayProperty(proxy, smproperty)
85             else:
86                 property = VectorProperty(proxy, smproperty)
87     elif smproperty.IsA("vtkSMVectorProperty"):
88         if smproperty.IsA("vtkSMIntVectorProperty") and \
89           smproperty.GetDomain("enum"):
90             property = EnumerationProperty(proxy, smproperty)
91         else:
92             property = VectorProperty(proxy, smproperty)
93     elif smproperty.IsA("vtkSMInputProperty"):
94         property = InputProperty(proxy, smproperty)
95     elif smproperty.IsA("vtkSMProxyProperty"):
96         property = ProxyProperty(proxy, smproperty)
97     else:
98         property = Property(proxy, smproperty)
99     return property
100
101 class Proxy(object):
102     """Proxy for a server side object. A proxy manages the lifetime of
103     one or more server manager objects. It also provides an interface
104     to set and get the properties of the server side objects. These
105     properties are presented as Python properties. For example,
106     you can set a property Foo using the following:
107      proxy.Foo = (1,2)
108     or
109      proxy.Foo.SetData((1,2))
110     or
111      proxy.Foo[0:2] = (1,2)
112     For more information, see the documentation of the property which
113     you can obtain with
114     help(proxy.Foo).
115
116     This class also provides an iterator which can be used to iterate
117     over all properties.
118     eg:
119       proxy = Proxy(proxy=smproxy)
120       for property in proxy:
121           print property
122
123     For advanced users:
124     This is a python class that wraps a vtkSMProxy.. Makes it easier to
125     set/get properties.
126     Instead of:
127      proxy.GetProperty("Foo").SetElement(0, 1)
128      proxy.GetProperty("Foo").SetElement(0, 2)
129     you can do:
130      proxy.Foo = (1,2)
131     or
132      proxy.Foo.SetData((1,2))
133     or
134      proxy.Foo[0:2] = (1,2)
135     Instead of:
136       proxy.GetProperty("Foo").GetElement(0)
137     you can do:
138       proxy.Foo.GetData()[0]
139     or
140       proxy.Foo[0]
141     For proxy properties, you can use append:
142      proxy.GetProperty("Bar").AddProxy(foo)
143     you can do:
144      proxy.Bar.append(foo)
145     Properties support most of the list API. See VectorProperty and
146     ProxyProperty documentation for details.
147
148     Please note that some of the methods accessible through the Proxy
149     class are not listed by help() because the Proxy objects forward
150     unresolved attributes to the underlying object. To get the full list,
151     see also dir(proxy.SMProxy). See also the doxygen based documentation
152     of the vtkSMProxy C++ class.
153     """
154
155     def __init__(self, **args):
156         """ Default constructor. It can be used to initialize properties
157         by passing keyword arguments where the key is the name of the
158         property. In addition registrationGroup and registrationName (optional)
159         can be specified (as keyword arguments) to automatically register
160         the proxy with the proxy manager. """
161         self.add_attribute('Observed', None)
162         self.add_attribute('ObserverTag', -1)
163         self.add_attribute('_Proxy__Properties', {})
164         self.add_attribute('_Proxy__LastAttrName', None)
165         self.add_attribute('SMProxy', None)
166         self.add_attribute('Port', 0)
167
168         if 'port' in args:
169             self.Port = args['port']
170             del args['port']
171
172         update = True
173         if 'no_update' in args:
174             if args['no_update']:
175                 update = False
176             del args['no_update']
177
178         if 'proxy' in args:
179             self.InitializeFromProxy(args['proxy'])
180             del args['proxy']
181         else:
182             self.Initialize(None, update)
183         if 'registrationGroup' in args:
184             registrationGroup = args['registrationGroup']
185             del args['registrationGroup']
186             registrationName = self.SMProxy.GetGlobalIDAsString()
187             if 'registrationName' in args:
188                 registrationName = args['registrationName']
189                 del args['registrationName']
190             pxm = ProxyManager()
191             pxm.RegisterProxy(registrationGroup, registrationName, self.SMProxy)
192         if update:
193             self.UpdateVTKObjects()
194         for key in args.keys():
195             setattr(self, key, args[key])
196         # Visit all properties so that they are created
197         for prop in self:
198             pass
199
200     def __setattr__(self, name, value):
201         try:
202             setter = getattr(self.__class__, name)
203             setter = setter.__set__
204         except AttributeError:
205             if not hasattr(self, name):
206                 raise AttributeError("Attribute %s does not exist. " % name +
207                   " This class does not allow addition of new attributes to avoid " +
208                   "mistakes due to typos. Use add_attribute() if you really want " +
209                   "to add this attribute.")
210             self.__dict__[name] = value
211         else:
212             setter(self, value)
213
214     def add_attribute(self, name, value):
215         self.__dict__[name] = value
216
217     def __del__(self):
218         """Destructor. Cleans up all observers as well as remove
219         the proxy from the _pyproxies dictionary"""
220         # Make sure that we remove observers we added
221         if self.Observed:
222             observed = self.Observed
223             tag = self.ObserverTag
224             self.Observed = None
225             self.ObserverTag = -1
226             observed.RemoveObserver(tag)
227         if self.SMProxy and (self.SMProxy, self.Port) in _pyproxies:
228             del _pyproxies[(self.SMProxy, self.Port)]
229
230     def InitializeFromProxy(self, aProxy, update=True):
231         """Constructor. Assigns proxy to self.SMProxy, updates the server
232         object as well as register the proxy in _pyproxies dictionary."""
233         import weakref
234         self.SMProxy = aProxy
235         if update:
236             self.SMProxy.UpdateVTKObjects()
237         _pyproxies[(self.SMProxy, self.Port)] = weakref.ref(self)
238
239     def Initialize(self):
240         "Overridden by the subclass created automatically"
241         pass
242
243     def __eq__(self, other):
244         "Returns true if the underlying SMProxies are the same."
245         if isinstance(other, Proxy):
246             try:
247                 if self.Port != other.Port:
248                     return False
249             except:
250                 pass
251             ## VSV using IsSame instead ==
252             return self.SMProxy.IsSame(other.SMProxy)
253         return self.SMProxy.IsSame(other)
254
255     def __ne__(self, other):
256         "Returns false if the underlying SMProxies are the same."
257         return not self.__eq__(other)
258
259     def __iter__(self):
260         "Creates an iterator for the properties."
261         return PropertyIterator(self)
262
263     def SetPropertyWithName(self, pname, arg):
264         """Generic method for setting the value of a property."""
265         prop = self.GetProperty(pname)
266         if prop is None:
267             raise RuntimeError, "Property %s does not exist. Please check the property name for typos." % pname
268         prop.SetData(arg)
269
270     def GetPropertyValue(self, name):
271         """Returns a scalar for properties with 1 elements, the property
272         itself for vectors."""
273         p = self.GetProperty(name)
274         if isinstance(p, VectorProperty):
275             if p.GetNumberOfElements() == 1 and not p.GetRepeatable():
276                 if p.SMProperty.IsA("vtkSMStringVectorProperty") or not p.GetArgumentIsArray():
277                     return p[0]
278         elif isinstance(p, InputProperty):
279             if not p.GetMultipleInput():
280                 if len(p) > 0:
281                     return p[0]
282                 else:
283                     return None
284         elif isinstance(p, ProxyProperty):
285             if not p.GetRepeatable():
286                 if len(p) > 0:
287                     return p[0]
288                 else:
289                     return None
290         return p
291
292     def GetProperty(self, name):
293         """Given a property name, returns the property object."""
294         if name in self.__Properties and self.__Properties[name]():
295             return self.__Properties[name]()
296         smproperty = self.SMProxy.GetProperty(name)
297         # Maybe they are looking by the label. Try to match that.
298         if not smproperty:
299             iter = PropertyIterator(self)
300             for prop in iter:
301                 if name == _make_name_valid(iter.PropertyLabel):
302                     smproperty = prop.SMProperty
303                     break
304         if smproperty:
305             property = _wrap_property(self, smproperty)
306             if property is not None:
307                 import weakref
308                 self.__Properties[name] = weakref.ref(property)
309             return property
310         return None
311
312     def ListProperties(self):
313         """Returns a list of all property names on this proxy."""
314         property_list = []
315         iter = self.__iter__()
316         for property in iter:
317             name = _make_name_valid(iter.PropertyLabel)
318             if name:
319                 property_list.append(name)
320         return property_list
321
322     def __ConvertArgumentsAndCall(self, *args):
323         """ Internal function.
324         Used to call a function on SMProxy. Converts input and
325         output values as appropriate.
326         """
327         newArgs = []
328         for arg in args:
329             if issubclass(type(arg), Proxy) or isinstance(arg, Proxy):
330                 newArgs.append(arg.SMProxy)
331             else:
332                 newArgs.append(arg)
333         func = getattr(self.SMProxy, self.__LastAttrName)
334         retVal = func(*newArgs)
335         if type(retVal) is type(self.SMProxy) and retVal.IsA("vtkSMProxy"):
336             return _getPyProxy(retVal)
337         elif type(retVal) is type(self.SMProxy) and retVal.IsA("vtkSMProperty"):
338             return _wrap_property(self, retVal)
339         else:
340             return retVal
341
342     def __GetActiveCamera(self):
343         """ This method handles GetActiveCamera specially. It adds
344         an observer to the camera such that everytime it is modified
345         the render view updated"""
346         import weakref
347         c = self.SMProxy.GetActiveCamera()
348         # VSV: Observers are not supported
349 ##         if not c.HasObserver("ModifiedEvent"):
350 ##             self.ObserverTag =c.AddObserver("ModifiedEvent", _makeUpdateCameraMethod(weakref.ref(self)))
351 ##             self.Observed = c
352         return c
353
354     def __getattr__(self, name):
355         """With the exception of a few overloaded methods,
356         returns the SMProxy method"""
357         if not self.SMProxy:
358             raise AttributeError("class %s has no attribute %s" % ("None", name))
359             return None
360         # Handle GetActiveCamera specially.
361         if name == "GetActiveCamera" and \
362            hasattr(self.SMProxy, "GetActiveCamera"):
363             return self.__GetActiveCamera
364         if name == "SaveDefinition" and hasattr(self.SMProxy, "SaveDefinition"):
365             return self.__SaveDefinition
366         # If not a property, see if SMProxy has the method
367         try:
368             proxyAttr = getattr(self.SMProxy, name)
369             self.__LastAttrName = name
370             return self.__ConvertArgumentsAndCall
371         except:
372             pass
373         return getattr(self.SMProxy, name)
374
375 class SourceProxy(Proxy):
376     """Proxy for a source object. This class adds a few methods to Proxy
377     that are specific to sources. It also provides access to the output
378     ports. Output ports can be accessed by name or index:
379     > op = source[0]
380     or
381     > op = source['some name'].
382     """
383     def UpdatePipeline(self, time=None):
384         """This method updates the server-side VTK pipeline and the associated
385         data information. Make sure to update a source to validate the output
386         meta-data."""
387         if time != None:
388             self.SMProxy.UpdatePipeline(time)
389         else:
390             self.SMProxy.UpdatePipeline()
391         # This is here to cause a receive
392         # on the client side so that progress works properly.
393         if ActiveConnection and ActiveConnection.IsRemote():
394             self.SMProxy.GetDataInformation()
395
396     def FileNameChanged(self):
397         "Called when the filename of a source proxy is changed."
398         self.UpdatePipelineInformation()
399
400     def UpdatePipelineInformation(self):
401         """This method updates the meta-data of the server-side VTK pipeline and
402         the associated information properties"""
403         self.SMProxy.UpdatePipelineInformation()
404
405     def GetDataInformation(self, idx=None):
406         """This method returns a DataInformation wrapper around a
407         vtkPVDataInformation"""
408         if idx == None:
409             idx = self.Port
410         if self.SMProxy:
411             return DataInformation( \
412                 self.SMProxy.GetDataInformation(idx), \
413                 self.SMProxy, idx)
414
415     def __getitem__(self, idx):
416         """Given a slice, int or string, returns the corresponding
417         output port"""
418         if isinstance(idx, slice):
419             indices = idx.indices(self.SMProxy.GetNumberOfOutputPorts())
420             retVal = []
421             for i in range(*indices):
422                 retVal.append(OutputPort(self, i))
423             return retVal
424         elif isinstance(idx, int):
425             if idx >= self.SMProxy.GetNumberOfOutputPorts() or idx < 0:
426                 raise IndexError
427             return OutputPort(self, idx)
428         else:
429             return OutputPort(self, self.SMProxy.GetOutputPortIndex(idx))
430
431     def GetPointDataInformation(self):
432         """Returns the associated point data information."""
433         self.UpdatePipeline()
434         return FieldDataInformation(self.SMProxy, self.Port, "PointData")
435
436     def GetCellDataInformation(self):
437         """Returns the associated cell data information."""
438         self.UpdatePipeline()
439         return FieldDataInformation(self.SMProxy, self.Port, "CellData")
440
441     def GetFieldDataInformation(self):
442         """Returns the associated cell data information."""
443         self.UpdatePipeline()
444         return FieldDataInformation(self.SMProxy, self.Port, "FieldData")
445
446     PointData = property(GetPointDataInformation, None, None, "Returns point data information")
447     CellData = property(GetCellDataInformation, None, None, "Returns cell data information")
448     FieldData = property(GetFieldDataInformation, None, None, "Returns field data information")
449
450
451 class ExodusIIReaderProxy(SourceProxy):
452     """Special class to define convenience functions for array
453     selection."""
454
455     def FileNameChanged(self):
456         "Called when the filename changes. Selects all variables."
457         SourceProxy.FileNameChanged(self)
458         self.SelectAllVariables()
459
460     def SelectAllVariables(self):
461         "Select all available variables for reading."
462         for prop in ('PointVariables', 'EdgeVariables', 'FaceVariables',
463                      'ElementVariables', 'GlobalVariables'):
464             f = getattr(self, prop)
465             f.SelectAll()
466
467     def DeselectAllVariables(self):
468         "Deselects all variables."
469         for prop in ('PointVariables', 'EdgeVariables', 'FaceVariables',
470                      'ElementVariables', 'GlobalVariables'):
471             f = getattr(self, prop)
472             f.DeselectAll()
473
474 class ViewLayoutProxy(Proxy):
475     """Special class to define convenience methods for View Layout"""
476
477     def SplitViewHorizontal(self, view, fraction=0.5):
478         """Split the cell containing the specified view horizontally.
479         If no fraction is specified, the frame is split into equal parts.
480         On success returns a positve number that identifying the new cell
481         location that can be used to assign view to, or split further.
482         Return -1 on failure."""
483         location = self.GetViewLocation(view)
484         if location == -1:
485             raise RuntimeError, "View is not present in this layout."
486         if fraction < 0.0 or fraction > 1.0:
487             raise RuntimeError, "'fraction' must be in the range [0.0, 1.0]"
488         return self.SMProxy.SplitHorizontal(location, fraction)
489
490     def SplitViewVertical(self, view=None, fraction=0.5):
491         """Split the cell containing the specified view horizontally.
492         If no view is specified, active view is used.
493         If no fraction is specified, the frame is split into equal parts.
494         On success returns a positve number that identifying the new cell
495         location that can be used to assign view to, or split further.
496         Return -1 on failure."""
497         location = self.GetViewLocation(view)
498         if location == -1:
499             raise RuntimeError, "View is not present in this layout."
500         if fraction < 0.0 or fraction > 1.0:
501             raise RuntimeError, "'fraction' must be in the range [0.0, 1.0]"
502         return self.SMProxy.SplitVertical(location, fraction)
503
504     def AssignView(self, location, view):
505         """Assign a view at a particular location. Note that the view's position may
506         be changed by subsequent Split() calls. Returns true on success."""
507         viewproxy = None
508         if isinstance(view, Proxy):
509             view = view.SMProxy
510         return self.SMProxy.AssignView(location, view)
511
512     def GetViewLocation(self, view):
513         if isinstance(view, Proxy):
514             view = view.SMProxy
515         return self.SMProxy.GetViewLocation(view)
516
517 class Property(object):
518     """Generic property object that provides access to one of the properties of
519     a server object. This class does not allow setting/getting any values but
520     provides an interface to update a property using __call__. This can be used
521     for command properties that correspond to function calls without arguments.
522     For example,
523     > proxy.Foo()
524     would push a Foo property which may cause the proxy to call a Foo method
525     on the actual VTK object.
526
527     For advanced users:
528     Python wrapper around a vtkSMProperty with a simple interface.
529     In addition to all method provided by vtkSMProperty (obtained by
530     forwarding unknown attributes requests to the underlying SMProxy),
531     Property and sub-class provide a list API.
532
533     Please note that some of the methods accessible through the Property
534     class are not listed by help() because the Property objects forward
535     unresolved attributes to the underlying object. To get the full list,
536     see also dir(proxy.SMProperty). See also the doxygen based documentation
537     of the vtkSMProperty C++ class.
538     """
539     def __init__(self, proxy, smproperty):
540         """Default constructor. Stores a reference to the proxy."""
541         import weakref
542         self.SMProperty = smproperty
543         self.Proxy = proxy
544
545     def __repr__(self):
546         """Returns a string representation containing property name
547         and value"""
548         if not type(self) is Property:
549             if self.GetData() is not None:
550                 repr = self.GetData().__repr__()
551             else:
552                 repr = "None"
553         else:
554             repr = "Property name= "
555             name = self.Proxy.GetPropertyName(self.SMProperty)
556             if name:
557                 repr += name
558             else:
559                 repr += "Unknown"
560
561         return repr
562
563     def __call__(self):
564         """Forces a property update using InvokeCommand."""
565         if type(self) is Property:
566             self.Proxy.SMProxy.InvokeCommand(self._FindPropertyName())
567         else:
568             raise RuntimeError, "Cannot invoke this property"
569
570     def _FindPropertyName(self):
571         "Returns the name of this property."
572         return self.Proxy.GetPropertyName(self.SMProperty)
573
574     def _UpdateProperty(self):
575         "Pushes the value of this property to the server."
576         # For now, we are updating all properties. This is due to an
577         # issue with the representations. Their VTK objects are not
578         # created until Input is set therefore, updating a property
579         # has no effect. Updating all properties everytime one is
580         # updated has the effect of pushing values set before Input
581         # when Input is updated.
582         # self.Proxy.SMProxy.UpdateProperty(self._FindPropertyName())
583         self.Proxy.SMProxy.UpdateVTKObjects()
584
585     def __getattr__(self, name):
586         "Unknown attribute requests get forwarded to SMProperty."
587         return getattr(self.SMProperty, name)
588
589     Name = property(_FindPropertyName, None, None,
590            "Returns the name for the property")
591
592 class GenericIterator(object):
593     """Iterator for container type objects"""
594
595     def __init__(self, obj):
596         self.Object = obj
597         self.index = 0
598
599     def __iter__(self):
600         return self
601
602     def next(self):
603         if self.index >= len(self.Object):
604             raise StopIteration
605
606         idx = self.index
607         self.index += 1
608         return self.Object[idx]
609
610 class VectorProperty(Property):
611     """A VectorProperty provides access to one or more values. You can use
612     a slice to get one or more property values:
613     > val = property[2]
614     or
615     > vals = property[0:5:2]
616     You can use a slice to set one or more property values:
617     > property[2] = val
618     or
619     > property[1:3] = (1,2)
620     """
621     def ConvertValue(self, value):
622         return value
623
624     def __len__(self):
625         """Returns the number of elements."""
626         return self.SMProperty.GetNumberOfElements()
627
628     def __iter__(self):
629         """Implementation of the sequence API"""
630         return GenericIterator(self)
631
632     def __setitem__(self, idx, value):
633         """Given a list or tuple of values, sets a slice of values [min, max)"""
634         if isinstance(idx, slice):
635             indices = idx.indices(len(self))
636             for i, j in zip(range(*indices), value):
637                 self.SMProperty.SetElement(i, self.ConvertValue(j))
638             self._UpdateProperty()
639         elif idx >= len(self) or idx < 0:
640             raise IndexError
641         else:
642             self.SMProperty.SetElement(idx, self.ConvertValue(value))
643             self._UpdateProperty()
644
645     def GetElement(self, index):
646         return self.SMProperty.GetElement(index)
647
648     def __getitem__(self, idx):
649         """Returns the range [min, max) of elements. Raises an IndexError
650         exception if an argument is out of bounds."""
651         ls = len(self)
652         if isinstance(idx, slice):
653             indices = idx.indices(ls)
654             retVal = []
655             for i in range(*indices):
656                retVal.append(self.GetElement(i))
657             return retVal
658         elif idx >= ls:
659             raise IndexError
660         elif idx < 0:
661             idx = ls + idx
662             if idx < 0:
663                 raise IndexError
664
665         return self.GetElement(idx)
666
667     def GetData(self):
668         "Returns all elements as either a list or a single value."
669         property = self.SMProperty
670         if property.GetRepeatable() or \
671            property.GetNumberOfElements() > 1:
672             return self[0:len(self)]
673         elif property.GetNumberOfElements() == 1:
674             return self.GetElement(0)
675
676     def SetData(self, values):
677         """Allows setting of all values at once. Requires a single value or
678         a iterable object."""
679         if not hasattr(values, "__iter__"):
680             values = (values,)
681         if not self.GetRepeatable() and len(values) != self.GetNumberOfElements():
682             raise RuntimeError("This property requires %d values." % self.GetNumberOfElements())
683         if self.GetRepeatable():
684             # Clean up first
685             self.SMProperty.SetNumberOfElements(0)
686         idx = 0
687         for val in values:
688             self.SMProperty.SetElement(idx, self.ConvertValue(val))
689             idx += 1
690         self._UpdateProperty()
691
692     def Clear(self):
693         "Removes all elements."
694         self.SMProperty().SetNumberOfElements(0)
695         self._UpdateProperty()
696
697 class ColorArrayProperty(VectorProperty):
698     """This subclass of VectorProperty handles setting of the array to
699     color by. It handles attribute type as well as well array name."""
700
701     def GetAvailable(self):
702         """Returns the list of available arrays as (attribute type, array name
703         tuples."""
704         arrays = []
705         for a in self.Proxy.Input.PointData:
706             arrays.append(('POINT_DATA', a.GetName()))
707         for a in self.Proxy.Input.CellData:
708             arrays.append(('CELL_DATA', a.GetName()))
709         return arrays
710
711     def SetData(self, value):
712         """Overwritten to enable setting attribute type (the ColorAttributeType
713         property and the array name. The argument should be the array name
714         (in which case the first appropriate attribute type is picked) or
715         a tuple of attribute type and array name."""
716         if isinstance(value, tuple) and len(value) == 2:
717             att = value[0]
718             arr = value[1]
719         elif isinstance(value, str):
720             att = None
721             arr = value
722         else:
723             raise ValueError("Expected a tuple of 2 values or a string.")
724
725         if not arr:
726             self.SMProperty.SetElement(0, '')
727             self._UpdateProperty()
728             return
729
730         found = False
731         for a in self.Available:
732             if a[1] == arr and (not att or att == a[0]):
733                 att = a[0]
734                 found = True
735                 break
736
737         if  not found:
738             pvoptions = vtkProcessModule.GetProcessModule().GetOptions()
739             # if this process is from a parallel batch run in symmetric mpi mode
740             # then we may not have any points or cells on some processes in which
741             # case we'll probably be missing the point and cell data too.  the
742             # check below makes sure that we avoid this situation.
743             if pvoptions.GetProcessType() != 0x40 or pvoptions.GetSymmetricMPIMode() == False \
744                     or len(self.Available) != 0:
745                 raise ValueError("Could not locate array %s in the input." % arr)
746
747         catt = self.Proxy.GetProperty("ColorAttributeType")
748         if att != None:
749             catt.SetData(att)
750         self.SMProperty.SetElement(0, arr)
751         self._UpdateProperty()
752
753     Available = property(GetAvailable, None, None, \
754         "This read-only property returns the list of arrays that can be colored by.")
755
756
757 class EnumerationProperty(VectorProperty):
758     """Subclass of VectorProperty that is applicable for enumeration type
759     properties."""
760
761     def GetElement(self, index):
762         """Returns the text for the given element if available. Returns
763         the numerical values otherwise."""
764         val = self.SMProperty.GetElement(index)
765         domain = self.SMProperty.GetDomain("enum")
766         for i in range(domain.GetNumberOfEntries()):
767             if domain.GetEntryValue(i) == val:
768                 return domain.GetEntryText(i)
769         return val
770
771     def ConvertValue(self, value):
772         """Converts value to type suitable for vtSMProperty::SetElement()"""
773         if type(value) == str:
774             domain = self.SMProperty.GetDomain("enum")
775             if domain.HasEntryText(value):
776                 return domain.GetEntryValueForText(value)
777             else:
778                 raise ValueError("%s is not a valid value." % value)
779         return VectorProperty.ConvertValue(self, value)
780
781     def GetAvailable(self):
782         "Returns the list of available values for the property."
783         retVal = []
784         domain = self.SMProperty.GetDomain("enum")
785         for i in range(domain.GetNumberOfEntries()):
786             retVal.append(domain.GetEntryText(i))
787         return retVal
788
789     Available = property(GetAvailable, None, None, \
790         "This read-only property contains the list of values that can be applied to this property.")
791
792
793 class FileNameProperty(VectorProperty):
794     """Property to set/get one or more file names.
795     This property updates the pipeline information everytime its value changes.
796     This is used to keep the array lists up to date."""
797
798     def _UpdateProperty(self):
799         "Pushes the value of this property to the server."
800         VectorProperty._UpdateProperty(self)
801         self.Proxy.FileNameChanged()
802
803 class ArraySelectionProperty(VectorProperty):
804     "Property to select an array to be processed by a filter."
805
806     def GetAssociation(self):
807         val = self.GetElement(3)
808         if val == "":
809             return None
810         for key, value in ASSOCIATIONS.iteritems():
811             if value == int(val):
812                 return key
813
814         return None
815
816     def GetArrayName(self):
817         return self.GetElement(4)
818
819     def __len__(self):
820         """Returns the number of elements."""
821         return 2
822
823     def __setitem__(self, idx, value):
824         raise RuntimeError, "This property cannot be accessed using __setitem__"
825
826     def __getitem__(self, idx):
827         """Returns attribute type for index 0, array name for index 1"""
828         if isinstance(idx, slice):
829             indices = idx.indices(len(self))
830             retVal = []
831             for i in range(*indices):
832                 if i >= 2 or i < 0:
833                     raise IndexError
834                 if i == 0:
835                     retVal.append(self.GetAssociation())
836                 else:
837                     retVal.append(self.GetArrayName())
838             return retVal
839         elif idx >= 2 or idx < 0:
840             raise IndexError
841
842         if i == 0:
843             return self.GetAssociation()
844         else:
845             return self.GetArrayName()
846
847     def SetData(self, values):
848         """Allows setting of all values at once. Requires a single value,
849         a tuple or list."""
850         if not isinstance(values, tuple) and \
851            not isinstance(values, list):
852             values = (values,)
853         if len(values) == 1:
854             self.SMProperty.SetElement(4, values[0])
855         elif len(values) == 2:
856             if isinstance(values[0], str):
857                 val = str(ASSOCIATIONS[values[0]])
858             else:
859                 # In case user didn't specify valid association,
860                 # just pick POINTS.
861                 val = str(ASSOCIATIONS['POINTS'])
862             self.SMProperty.SetElement(3,  str(val))
863             self.SMProperty.SetElement(4, values[1])
864         else:
865             raise RuntimeError, "Expected 1 or 2 values."
866         self._UpdateProperty()
867
868     def UpdateDefault(self):
869         "Helper method to set default values."
870         if self.SMProperty.GetNumberOfElements() != 5:
871             return
872         if self.GetElement(4) != '' or \
873             self.GetElement(3) != '':
874             return
875
876         for i in range(0,3):
877             if self.GetElement(i) == '':
878                 self.SMProperty.SetElement(i, '0')
879         al = self.SMProperty.GetDomain("array_list")
880         al.Update(self.SMProperty)
881         al.SetDefaultValues(self.SMProperty)
882
883 class ArrayListProperty(VectorProperty):
884     """This property provides a simpler interface for selecting arrays.
885     Simply assign a list of arrays that should be loaded by the reader.
886     Use the Available property to get a list of available arrays."""
887
888     def __init__(self, proxy, smproperty):
889         VectorProperty.__init__(self, proxy, smproperty)
890         self.__arrays = []
891
892     def GetAvailable(self):
893         "Returns the list of available arrays"
894         dm = self.GetDomain("array_list")
895         retVal = []
896         for i in range(dm.GetNumberOfStrings()):
897             retVal.append(dm.GetString(i))
898         return retVal
899
900     Available = property(GetAvailable, None, None, \
901         "This read-only property contains the list of items that can be read by a reader.")
902
903     def SelectAll(self):
904         "Selects all arrays."
905         self.SetData(self.Available)
906
907     def DeselectAll(self):
908         "Deselects all arrays."
909         self.SetData([])
910
911     def __iter__(self):
912         """Implementation of the sequence API"""
913         return GenericIterator(self)
914
915     def __len__(self):
916         """Returns the number of elements."""
917         return len(self.GetData())
918
919     def __setitem__(self, idx, value):
920       """Given a list or tuple of values, sets a slice of values [min, max)"""
921       self.GetData()
922       if isinstance(idx, slice):
923           indices = idx.indices(len(self))
924           for i, j in zip(range(*indices), value):
925               self.__arrays[i] = j
926           self.SetData(self.__arrays)
927       elif idx >= len(self) or idx < 0:
928           raise IndexError
929       else:
930           self.__arrays[idx] = self.ConvertValue(value)
931           self.SetData(self.__arrays)
932
933     def __getitem__(self, idx):
934       """Returns the range [min, max) of elements. Raises an IndexError
935       exception if an argument is out of bounds."""
936       self.GetData()
937       if isinstance(idx, slice):
938           indices = idx.indices(len(self))
939           retVal = []
940           for i in range(*indices):
941               retVal.append(self.__arrays[i])
942           return retVal
943       elif idx >= len(self) or idx < 0:
944           raise IndexError
945       return self.__arrays[idx]
946
947     def SetData(self, values):
948         """Allows setting of all values at once. Requires a single value,
949         a tuple or list."""
950         # Clean up first
951         iup = self.SMProperty.GetImmediateUpdate()
952         self.SMProperty.SetImmediateUpdate(False)
953         # Clean up first
954         self.SMProperty.SetNumberOfElements(0)
955         if not isinstance(values, tuple) and \
956            not isinstance(values, list):
957             values = (values,)
958         fullvalues = []
959         for i in range(len(values)):
960             val = self.ConvertValue(values[i])
961             fullvalues.append(val)
962             fullvalues.append('1')
963         for array in self.Available:
964             if not values.__contains__(array):
965                 fullvalues.append(array)
966                 fullvalues.append('0')
967         i = 0
968         for value in fullvalues:
969             self.SMProperty.SetElement(i, value)
970             i += 1
971
972         self._UpdateProperty()
973         self.SMProperty.SetImmediateUpdate(iup)
974
975     def GetData(self):
976         "Returns all elements as a list."
977         property = self.SMProperty
978         nElems = property.GetNumberOfElements()
979         if nElems%2 != 0:
980             raise ValueError, "The SMProperty with XML label '%s' has a size that is not a multiple of 2." % property.GetXMLLabel()
981         self.__arrays = []
982         for i in range(0, nElems, 2):
983             if self.GetElement(i+1) != '0':
984                 self.__arrays.append(self.GetElement(i))
985         return list(self.__arrays)
986
987 class ProxyProperty(Property):
988     """A ProxyProperty provides access to one or more proxies. You can use
989     a slice to get one or more property values:
990     > proxy = property[2]
991     or
992     > proxies = property[0:5:2]
993     You can use a slice to set one or more property values:
994     > property[2] = proxy
995     or
996     > property[1:3] = (proxy1, proxy2)
997     You can also append and delete:
998     > property.append(proxy)
999     and
1000     > del property[1:2]
1001
1002     You can also remove all elements with Clear().
1003
1004     Note that some properties expect only 1 proxy and will complain if
1005     you set the number of values to be something else.
1006     """
1007     def __init__(self, proxy, smproperty):
1008         """Default constructor.  Stores a reference to the proxy.  Also looks
1009         at domains to find valid values."""
1010         Property.__init__(self, proxy, smproperty)
1011         # Check to see if there is a proxy list domain and, if so,
1012         # initialize ourself. (Should this go in ProxyProperty?)
1013         listdomain = self.GetDomain('proxy_list')
1014         if listdomain:
1015             if listdomain.GetClassName() != 'vtkSMProxyListDomain':
1016                 raise ValueError, "Found a 'proxy_list' domain on an InputProperty that is not a ProxyListDomain."
1017             pm = ProxyManager()
1018             group = "pq_helper_proxies." + proxy.GetGlobalIDAsString()
1019             if listdomain.GetNumberOfProxies() == 0:
1020                 for i in xrange(listdomain.GetNumberOfProxyTypes()):
1021                     igroup = listdomain.GetProxyGroup(i)
1022                     name = listdomain.GetProxyName(i)
1023                     iproxy = CreateProxy(igroup, name)
1024                     listdomain.AddProxy(iproxy)
1025                     pm.RegisterProxy(group, proxy.GetPropertyName(smproperty), iproxy)
1026                 listdomain.SetDefaultValues(self.SMProperty)
1027
1028     def GetAvailable(self):
1029         """If this proxy has a list domain, then this function returns the
1030         strings you can use to select from the domain.  If there is no such
1031         list domain, the returned list is empty."""
1032         listdomain = self.GetDomain('proxy_list')
1033         retval = []
1034         if listdomain:
1035             for i in xrange(listdomain.GetNumberOfProxies()):
1036                 proxy = listdomain.GetProxy(i)
1037                 retval.append(proxy.GetXMLLabel())
1038         return retval
1039
1040     Available = property(GetAvailable, None, None,
1041                          """This read only property is a list of strings you can
1042                          use to select from the list domain.  If there is no
1043                          such list domain, the array is empty.""")
1044
1045     def __iter__(self):
1046         """Implementation of the sequence API"""
1047         return GenericIterator(self)
1048
1049     def __len__(self):
1050         """Returns the number of elements."""
1051         return self.SMProperty.GetNumberOfProxies()
1052
1053     def remove(self, proxy):
1054         """Removes the first occurence of the proxy from the property."""
1055         self.SMProperty.RemoveProxy(proxy.SMProxy)
1056         self._UpdateProperty()
1057         
1058     def __setitem__(self, idx, value):
1059       """Given a list or tuple of values, sets a slice of values [min, max)"""
1060       if isinstance(idx, slice):
1061         indices = idx.indices(len(self))
1062         for i, j in zip(range(*indices), value):
1063           self.SMProperty.SetProxy(i, j.SMProxy)
1064         self._UpdateProperty()
1065       elif idx >= len(self) or idx < 0:
1066         raise IndexError
1067       else:
1068         self.SMProperty.SetProxy(idx, value.SMProxy)
1069         self._UpdateProperty()
1070
1071     def __delitem__(self,idx):
1072       """Removes the element idx"""
1073       if isinstance(idx, slice):
1074         indices = idx.indices(len(self))
1075         # Collect the elements to delete to a new list first.
1076         # Otherwise indices are screwed up during the actual
1077         # remove loop.
1078         toremove = []
1079         for i in range(*indices):
1080           toremove.append(self[i])
1081         for i in toremove:
1082           self.SMProperty.RemoveProxy(i.SMProxy)
1083         self._UpdateProperty()
1084       elif idx >= len(self) or idx < 0:
1085         raise IndexError
1086       else:
1087         self.SMProperty.RemoveProxy(self[idx].SMProxy)
1088         self._UpdateProperty()
1089
1090     def __getitem__(self, idx):
1091       """Returns the range [min, max) of elements. Raises an IndexError
1092       exception if an argument is out of bounds."""
1093       if isinstance(idx, slice):
1094         indices = idx.indices(len(self))
1095         retVal = []
1096         for i in range(*indices):
1097           retVal.append(_getPyProxy(self.SMProperty.GetProxy(i)))
1098         return retVal
1099       elif idx >= len(self) or idx < 0:
1100         raise IndexError
1101       return _getPyProxy(self.SMProperty.GetProxy(idx))
1102
1103     def __getattr__(self, name):
1104         "Unknown attribute requests get forwarded to SMProperty."
1105         return getattr(self.SMProperty, name)
1106
1107     def index(self, proxy):
1108         idx = 0
1109         for px in self:
1110             ## VSV: ==
1111             if proxy.IsSame(px):
1112                 return idx
1113             idx += 1
1114         raise ValueError("proxy is not in the list.")
1115
1116     def append(self, proxy):
1117         "Appends the given proxy to the property values."
1118         self.SMProperty.AddProxy(proxy.SMProxy)
1119         self._UpdateProperty()
1120
1121     def GetData(self):
1122         "Returns all elements as either a list or a single value."
1123         property = self.SMProperty
1124         if property.GetRepeatable() or property.GetNumberOfProxies() > 1:
1125             return self[0:len(self)]
1126         else:
1127             if property.GetNumberOfProxies() > 0:
1128                 return _getPyProxy(property.GetProxy(0))
1129         return None
1130
1131     def SetData(self, values):
1132         """Allows setting of all values at once. Requires a single value,
1133         a tuple or list."""
1134         if isinstance(values, str):
1135             position = -1
1136             try:
1137                 position = self.Available.index(values)
1138             except:
1139                 raise ValueError, values + " is not a valid object in the domain."
1140             values = self.GetDomain('proxy_list').GetProxy(position)
1141         if not isinstance(values, tuple) and \
1142            not isinstance(values, list):
1143             values = (values,)
1144         self.SMProperty.RemoveAllProxies()
1145         for value in values:
1146             if isinstance(value, Proxy):
1147                 value_proxy = value.SMProxy
1148             else:
1149                 value_proxy = value
1150             self.SMProperty.AddProxy(value_proxy)
1151         self._UpdateProperty()
1152
1153     def Clear(self):
1154         "Removes all elements."
1155         self.SMProperty.RemoveAllProxies()
1156         self._UpdateProperty()
1157
1158 class InputProperty(ProxyProperty):
1159     """An InputProperty allows making pipeline connections. You can set either
1160     a source proxy or an OutputProperty to an input property:
1161
1162     > property[0] = proxy
1163     or
1164     > property[0] = OuputPort(proxy, 1)
1165
1166     > property.append(proxy)
1167     or
1168     > property.append(OutputPort(proxy, 0))
1169     """
1170     def __setitem__(self, idx, value):
1171       """Given a list or tuple of values, sets a slice of values [min, max)"""
1172       if isinstance(idx, slice):
1173         indices = idx.indices(len(self))
1174         for i, j in zip(range(*indices), value):
1175           op = value[i-min]
1176           self.SMProperty.SetInputConnection(i, op.SMProxy, op.Port)
1177         self._UpdateProperty()
1178       elif idx >= len(self) or idx < 0:
1179         raise IndexError
1180       else:
1181         self.SMProperty.SetInputConnection(idx, value.SMProxy, value.Port)
1182         self._UpdateProperty()
1183
1184     def __getitem__(self, idx):
1185       """Returns the range [min, max) of elements. Raises an IndexError
1186       exception if an argument is out of bounds."""
1187       if isinstance(idx, slice):
1188         indices = idx.indices(len(self))
1189         retVal = []
1190         for i in range(*indices):
1191             port = None
1192             if self.SMProperty.GetProxy(i):
1193                 port = OutputPort(_getPyProxy(self.SMProperty.GetProxy(i)),\
1194                                   self.SMProperty.GetOutputPortForConnection(i))
1195             retVal.append(port)
1196         return retVal
1197       elif idx >= len(self) or idx < 0:
1198         raise IndexError
1199       return OutputPort(_getPyProxy(self.SMProperty.GetProxy(idx)),\
1200                         self.SMProperty.GetOutputPortForConnection(idx))
1201
1202     def append(self, value):
1203         """Appends the given proxy to the property values.
1204         Accepts Proxy or OutputPort objects."""
1205         self.SMProperty.AddInputConnection(value.SMProxy, value.Port)
1206         self._UpdateProperty()
1207
1208     def GetData(self):
1209         """Returns all elements as either a list of OutputPort objects or
1210         a single OutputPort object."""
1211         property = self.SMProperty
1212         if property.GetRepeatable() or property.GetNumberOfProxies() > 1:
1213             return self[0:len(self)]
1214         else:
1215             if property.GetNumberOfProxies() > 0:
1216                 return OutputPort(_getPyProxy(property.GetProxy(0)),\
1217                                   self.SMProperty.GetOutputPortForConnection(0))
1218         return None
1219
1220     def SetData(self, values):
1221         """Allows setting of all values at once. Requires a single value,
1222         a tuple or list. Accepts Proxy or OutputPort objects."""
1223         if isinstance(values, str):
1224             ProxyProperty.SetData(self, values)
1225             return
1226         if not isinstance(values, tuple) and \
1227            not isinstance(values, list):
1228             values = (values,)
1229         self.SMProperty.RemoveAllProxies()
1230         for value in values:
1231             if value:
1232                 self.SMProperty.AddInputConnection(value.SMProxy, value.Port)
1233         self._UpdateProperty()
1234
1235     def _UpdateProperty(self):
1236         "Pushes the value of this property to the server."
1237         ProxyProperty._UpdateProperty(self)
1238         iter = PropertyIterator(self.Proxy)
1239         for prop in iter:
1240             if isinstance(prop, ArraySelectionProperty):
1241                 prop.UpdateDefault()
1242
1243
1244 class DataInformation(object):
1245     """DataInformation is a contained for meta-data associated with an
1246     output data.
1247
1248     DataInformation is a python wrapper around a vtkPVDataInformation.
1249     In addition to proving all methods of a vtkPVDataInformation, it provides
1250     a few convenience methods.
1251
1252     Please note that some of the methods accessible through the DataInformation
1253     class are not listed by help() because the DataInformation objects forward
1254     unresolved attributes to the underlying object. To get the full list,
1255     see also dir(proxy.DataInformation).
1256     See also the doxygen based documentation of the vtkPVDataInformation C++
1257     class.
1258     """
1259     def __init__(self, dataInformation, proxy, idx):
1260         """Default constructor. Requires a vtkPVDataInformation, a source proxy
1261         and an output port id."""
1262         self.DataInformation = dataInformation
1263         self.Proxy = proxy
1264         self.Idx = idx
1265
1266     def Update(self):
1267         """****Deprecated**** There is no reason anymore to use this method
1268         explicitly, it is called automatically when one gets any value from the
1269         data information object.
1270         Update the data information if necessary. Note that this
1271         does not cause execution of the underlying object. In certain
1272         cases, you may have to call UpdatePipeline() on the proxy."""
1273         if self.Proxy:
1274             self.Proxy.GetDataInformation(self.Idx)
1275
1276     def GetDataSetType(self):
1277         """Returns the dataset type as defined in vtkDataObjectTypes."""
1278         self.Update()
1279         if not self.DataInformation:
1280             raise RuntimeError, "No data information is available"
1281         if self.DataInformation.GetCompositeDataSetType() > -1:
1282             return self.DataInformation.GetCompositeDataSetType()
1283         return self.DataInformation.GetDataSetType()
1284
1285     def GetDataSetTypeAsString(self):
1286         """Returns the dataset type as a user-friendly string. This is
1287         not the same as the enumaration used by VTK"""
1288         return vtk.vtkDataObjectTypes.GetClassNameFromTypeId(self.GetDataSetType())
1289
1290     def __getattr__(self, name):
1291         """Forwards unknown attribute requests to the underlying
1292         vtkPVInformation."""
1293         if not self.DataInformation:
1294             raise AttributeError("class has no attribute %s" % name)
1295             return None
1296         self.Update()
1297         return getattr(self.DataInformation, name)
1298
1299 class ArrayInformation(object):
1300     """Meta-information associated with an array. Use the Name
1301     attribute to get the array name.
1302
1303     Please note that some of the methods accessible through the ArrayInformation
1304     class are not listed by help() because the ArrayInformation objects forward
1305     unresolved attributes to the underlying object.
1306     See the doxygen based documentation of the vtkPVArrayInformation C++
1307     class for a full list.
1308     """
1309     def __init__(self, proxy, field, name):
1310         self.Proxy = proxy
1311         self.FieldData = field
1312         self.Name = name
1313
1314     def __getattr__(self, name):
1315         """Forward unknown methods to vtkPVArrayInformation"""
1316         array = self.FieldData.GetFieldData().GetArrayInformation(self.Name)
1317         if not array: return None
1318         return getattr(array, name)
1319
1320     def __repr__(self):
1321         """Returns a user-friendly representation string."""
1322         return "Array: " + self.Name
1323
1324     def GetRange(self, component=0):
1325         """Given a component, returns its value range as a tuple of 2 values."""
1326         array = self.FieldData.GetFieldData().GetArrayInformation(self.Name)
1327         range = array.GetComponentRange(component)
1328         return (range[0], range[1])
1329
1330 class FieldDataInformationIterator(object):
1331     """Iterator for FieldDataInformation"""
1332
1333     def __init__(self, info, items=False):
1334         self.FieldDataInformation = info
1335         self.index = 0
1336         self.items = items
1337
1338     def __iter__(self):
1339         return self
1340
1341     def next(self):
1342         if self.index >= self.FieldDataInformation.GetNumberOfArrays():
1343             raise StopIteration
1344
1345         self.index += 1
1346         ai = self.FieldDataInformation[self.index-1]
1347         if self.items:
1348             return (ai.GetName(), ai)
1349         else:
1350             return ai
1351
1352
1353 class FieldDataInformation(object):
1354     """Meta-data for a field of an output object (point data, cell data etc...).
1355     Provides easy access to the arrays using the slice interface:
1356     > narrays = len(field_info)
1357     > for i in range(narrays):
1358     >   array_info = field_info[i]
1359
1360     Full slice interface is supported:
1361     > arrays = field_info[0:5:3]
1362     where arrays is a list.
1363
1364     Array access by name is also possible:
1365     > array_info = field_info['Temperature']
1366
1367     The number of arrays can also be accessed using the NumberOfArrays
1368     property.
1369     """
1370     def __init__(self, proxy, idx, field):
1371         self.Proxy = proxy
1372         self.OutputPort = idx
1373         self.FieldData = field
1374
1375     def GetFieldData(self):
1376         """Convenience method to get the underlying
1377         vtkPVDataSetAttributesInformation"""
1378         return getattr(self.Proxy.GetDataInformation(self.OutputPort), "Get%sInformation" % self.FieldData)()
1379
1380     def GetNumberOfArrays(self):
1381         """Returns the number of arrays."""
1382         self.Proxy.UpdatePipeline()
1383         return self.GetFieldData().GetNumberOfArrays()
1384
1385     def GetArray(self, idx):
1386         """Given an index or a string, returns an array information.
1387         Raises IndexError if the index is out of bounds."""
1388         self.Proxy.UpdatePipeline()
1389         if not self.GetFieldData().GetArrayInformation(idx):
1390             return None
1391         if isinstance(idx, str):
1392             return ArrayInformation(self.Proxy, self, idx)
1393         elif idx >= len(self) or idx < 0:
1394             raise IndexError
1395         return ArrayInformation(self.Proxy, self, self.GetFieldData().GetArrayInformation(idx).GetName())
1396
1397     def __len__(self):
1398         """Returns the number of arrays."""
1399         return self.GetNumberOfArrays()
1400
1401     def __getitem__(self, idx):
1402         """Implements the [] operator. Accepts an array name."""
1403         if isinstance(idx, slice):
1404             indices = idx.indices(self.GetNumberOfArrays())
1405             retVal = []
1406             for i in range(*indices):
1407                 retVal.append(self.GetArray(i))
1408             return retVal
1409         return self.GetArray(idx)
1410
1411     def keys(self):
1412         """Implementation of the dictionary API"""
1413         kys = []
1414         narrays = self.GetNumberOfArrays()
1415         for i in range(narrays):
1416             kys.append(self.GetArray(i).GetName())
1417         return kys
1418
1419     def values(self):
1420         """Implementation of the dictionary API"""
1421         vals = []
1422         narrays = self.GetNumberOfArrays()
1423         for i in range(narrays):
1424             vals.append(self.GetArray(i))
1425         return vals
1426
1427     def iteritems(self):
1428         """Implementation of the dictionary API"""
1429         return FieldDataInformationIterator(self, True)
1430
1431     def items(self):
1432         """Implementation of the dictionary API"""
1433         itms = []
1434         narrays = self.GetNumberOfArrays()
1435         for i in range(narrays):
1436             ai = self.GetArray(i)
1437             itms.append((ai.GetName(), ai))
1438         return itms
1439
1440     def has_key(self, key):
1441         """Implementation of the dictionary API"""
1442         if self.GetArray(key):
1443             return True
1444         return False
1445
1446     def __iter__(self):
1447         """Implementation of the dictionary API"""
1448         return FieldDataInformationIterator(self)
1449
1450     def __getattr__(self, name):
1451         """Forwards unknown attributes to the underlying
1452         vtkPVDataSetAttributesInformation"""
1453         array = self.GetArray(name)
1454         if array: return array
1455         raise AttributeError("class has no attribute %s" % name)
1456         return None
1457
1458     NumberOfArrays = property(GetNumberOfArrays, None, None, "Returns the number of arrays.")
1459
1460 def OutputPort(proxy, outputPort=0):
1461     if not Proxy:
1462         return None
1463     if isinstance(outputPort, str):
1464         outputPort = proxy.GetOutputPortIndex(outputPort)
1465     if outputPort >= proxy.GetNumberOfOutputPorts():
1466         return None
1467     if proxy.Port == outputPort:
1468         return proxy
1469     newinstance = _getPyProxy(proxy.SMProxy, outputPort)
1470     newinstance.Port = outputPort
1471     newinstance._Proxy__Properties = proxy._Proxy__Properties
1472     return newinstance
1473
1474 class ProxyManager(object):
1475     """When running scripts from the python shell in the ParaView application,
1476     registering proxies with the proxy manager is the only mechanism to
1477     notify the graphical user interface (GUI) that a proxy
1478     exists. Therefore, unless a proxy is registered, it will not show up in
1479     the user interface. Also, the proxy manager is the only way to get
1480     access to proxies created using the GUI. Proxies created using the GUI
1481     are automatically registered under an appropriate group (sources,
1482     filters, representations and views). To get access to these objects,
1483     you can use proxyManager.GetProxy(group, name). The name is the same
1484     as the name shown in the pipeline browser.
1485
1486     This class is a python wrapper for vtkSMProxyManager. Note that the
1487     underlying vtkSMProxyManager is a singleton. All instances of this
1488     class will refer to the same object. In addition to all methods provided by
1489     vtkSMProxyManager (all unknown attribute requests are forwarded
1490     to the vtkSMProxyManager), this class provides several convenience
1491     methods.
1492
1493     Please note that some of the methods accessible through the ProxyManager
1494     class are not listed by help() because the ProxyManager objects forwards
1495     unresolved attributes to the underlying object. To get the full list,
1496     see also dir(proxy.SMProxyManager). See also the doxygen based documentation
1497     of the vtkSMProxyManager C++ class.
1498     """
1499
1500     def __init__(self, session=None):
1501         """Constructor. Assigned self.SMProxyManager to
1502         vtkSMProxyManager.GetProxyManager()."""
1503         global ActiveConnection
1504         if not session:
1505             session = ActiveConnection.Session
1506         self.SMProxyManager = session.GetSessionProxyManager()
1507
1508     def RegisterProxy(self, group, name, aProxy):
1509         """Registers a proxy (either SMProxy or proxy) with the
1510         server manager"""
1511         if isinstance(aProxy, Proxy):
1512             self.SMProxyManager.RegisterProxy(group, name, aProxy.SMProxy)
1513         else:
1514             self.SMProxyManager.RegisterProxy(group, name, aProxy)
1515
1516     def NewProxy(self, group, name):
1517         """Creates a new proxy of given group and name and returns an SMProxy.
1518         Note that this is a server manager object. You should normally create
1519         proxies using the class objects. For example:
1520         obj = servermanager.sources.SphereSource()"""
1521         if not self.SMProxyManager:
1522             return None
1523         aProxy = self.SMProxyManager.NewProxy(group, name, "NULL")
1524         if not aProxy:
1525             return None
1526         aProxy.UnRegister(None)
1527         return aProxy
1528
1529     def GetProxy(self, group, name):
1530         """Returns a Proxy registered under a group and name"""
1531         if not self.SMProxyManager:
1532             return None
1533         aProxy = self.SMProxyManager.GetProxy(group, name)
1534         if not aProxy:
1535             return None
1536         return _getPyProxy(aProxy)
1537
1538     def GetPrototypeProxy(self, group, name):
1539         """Returns a prototype proxy given a group and name. This is an
1540         SMProxy. This is a low-level method. You should not normally
1541         have to call it."""
1542         if not self.SMProxyManager:
1543             return None
1544         aProxy = self.SMProxyManager.GetPrototypeProxy(group, name)
1545         if not aProxy:
1546             return None
1547         return aProxy
1548
1549     def GetProxiesInGroup(self, groupname):
1550         """Returns a map of proxies in a particular group."""
1551         proxies = {}
1552         iter = self.NewGroupIterator(groupname)
1553         for aProxy in iter:
1554             proxies[(iter.GetKey(), aProxy.GetGlobalIDAsString())] = aProxy
1555         return proxies
1556
1557     def UnRegisterProxy(self, groupname, proxyname, aProxy):
1558         """Unregisters a proxy."""
1559         if not self.SMProxyManager:
1560             return
1561         if aProxy != None and isinstance(aProxy,Proxy):
1562             aProxy = aProxy.SMProxy
1563         if aProxy:
1564             self.SMProxyManager.UnRegisterProxy(groupname, proxyname, aProxy)
1565
1566     def GetProxies(self, groupname, proxyname):
1567         """Returns all proxies registered under the given group with the
1568         given name. Note that it is possible to register more than one
1569         proxy with the same name in the same group. Because the proxies
1570         are different, there is no conflict. Use this method instead of
1571         GetProxy() if you know that there are more than one proxy registered
1572         with this name."""
1573         if not self.SMProxyManager:
1574             return []
1575         collection = vtk.vtkCollection()
1576         result = []
1577         self.SMProxyManager.GetProxies(groupname, proxyname, collection)
1578         for i in range(0, collection.GetNumberOfItems()):
1579             aProxy = _getPyProxy(collection.GetItemAsObject(i))
1580             if aProxy:
1581                 result.append(aProxy)
1582
1583         return result
1584
1585     def __iter__(self):
1586         """Returns a new ProxyIterator."""
1587         iter = ProxyIterator()
1588         iter.Begin()
1589         return iter
1590
1591     def NewGroupIterator(self, group_name):
1592         """Returns a ProxyIterator for a group. The resulting object
1593         can be used to traverse the proxies that are in the given
1594         group."""
1595         iter = self.__iter__()
1596         iter.SetModeToOneGroup()
1597         iter.Begin(group_name)
1598         return iter
1599
1600     def NewDefinitionIterator(self, groupname=None):
1601         """Returns an iterator that can be used to iterate over
1602            all groups and types of proxies that the proxy manager
1603            can create."""
1604         iter = None
1605         if groupname != None:
1606             iter = ProxyDefinitionIterator(self.GetProxyDefinitionManager().NewSingleGroupIterator(groupname,0))
1607         else:
1608             iter = ProxyDefinitionIterator(self.GetProxyDefinitionManager().NewIterator(0))
1609
1610         return iter
1611
1612     def __ConvertArgumentsAndCall(self, *args):
1613       newArgs = []
1614       for arg in args:
1615           if issubclass(type(arg), Proxy) or isinstance(arg, Proxy):
1616               newArgs.append(arg.SMProxy)
1617           else:
1618               newArgs.append(arg)
1619       func = getattr(self.SMProxyManager, self.__LastAttrName)
1620       retVal = func(*newArgs)
1621       if type(retVal) is type(self.SMProxyManager) and retVal.IsA("vtkSMProxy"):
1622           return _getPyProxy(retVal)
1623       else:
1624           return retVal
1625
1626     def __getattr__(self, name):
1627         """Returns attribute from the ProxyManager"""
1628         try:
1629             pmAttr = getattr(self.SMProxyManager, name)
1630             self.__LastAttrName = name
1631             return self.__ConvertArgumentsAndCall
1632         except:
1633             pass
1634         return getattr(self.SMProxyManager, name)
1635
1636     def LoadState(self, filename, loader = None):
1637         self.SMProxyManager.LoadXMLState(filename, loader)
1638
1639     def SaveState(self, filename):
1640         self.SMProxyManager.SaveXMLState(filename)
1641
1642 class PropertyIterator(object):
1643     """Wrapper for a vtkSMPropertyIterator class to satisfy
1644        the python iterator protocol. Note that the list of
1645        properties can also be obtained from the class object's
1646        dictionary.
1647        See the doxygen documentation for vtkSMPropertyIterator C++
1648        class for details.
1649        """
1650
1651     def __init__(self, aProxy):
1652         self.SMIterator = aProxy.NewPropertyIterator()
1653         if self.SMIterator:
1654             self.SMIterator.UnRegister(None)
1655             self.SMIterator.Begin()
1656         self.Key = None
1657         self.PropertyLabel = None
1658         self.Proxy = aProxy
1659
1660     def __iter__(self):
1661         return self
1662
1663     def next(self):
1664         if not self.SMIterator:
1665             raise StopIteration
1666
1667         if self.SMIterator.IsAtEnd():
1668             self.Key = None
1669             raise StopIteration
1670         self.Key = self.SMIterator.GetKey()
1671         self.PropertyLabel = self.SMIterator.GetPropertyLabel()
1672         self.SMIterator.Next()
1673         return self.Proxy.GetProperty(self.Key)
1674
1675     def GetProxy(self):
1676         """Returns the proxy for the property last returned by the call to
1677         'next()'"""
1678         return self.Proxy
1679
1680     def GetKey(self):
1681         """Returns the key for the property last returned by the call to
1682         'next()' """
1683         return self.Key
1684
1685     def GetProperty(self):
1686         """Returns the property last returned by the call to 'next()' """
1687         return self.Proxy.GetProperty(self.Key)
1688
1689     def __getattr__(self, name):
1690         """returns attributes from the vtkSMPropertyIterator."""
1691         return getattr(self.SMIterator, name)
1692
1693 class ProxyDefinitionIterator(object):
1694     """Wrapper for a vtkPVProxyDefinitionIterator class to satisfy
1695        the python iterator protocol.
1696        See the doxygen documentation of the vtkPVProxyDefinitionIterator
1697        C++ class for more information."""
1698     def __init__(self, iter):
1699         self.SMIterator = iter
1700         if self.SMIterator:
1701             self.SMIterator.UnRegister(None)
1702             self.SMIterator.InitTraversal()
1703         self.Group = None
1704         self.Key = None
1705
1706     def __iter__(self):
1707         return self
1708
1709     def next(self):
1710         if self.SMIterator.IsDoneWithTraversal():
1711             self.Group = None
1712             self.Key = None
1713             raise StopIteration
1714         self.Group = self.SMIterator.GetGroupName()
1715         self.Key = self.SMIterator.GetProxyName()
1716         self.SMIterator.GoToNextItem()
1717         return {"group": self.Group, "key":self.Key }
1718
1719     def GetProxyName(self):
1720         """Returns the key for the proxy definition last returned by the call
1721         to 'next()' """
1722         return self.Key
1723
1724     def GetGroup(self):
1725         """Returns the group for the proxy definition last returned by the
1726         call to 'next()' """
1727         return self.Group
1728
1729     def __getattr__(self, name):
1730         """returns attributes from the vtkPVProxyDefinitionIterator."""
1731         return getattr(self.SMIterator, name)
1732
1733
1734 class ProxyIterator(object):
1735     """Wrapper for a vtkSMProxyIterator class to satisfy the
1736      python iterator protocol.
1737      See the doxygen documentation of vtkSMProxyIterator C++ class for
1738      more information.
1739      """
1740     def __init__(self):
1741         self.SMIterator = vtkSMProxyIterator()
1742         self.SMIterator.SetSession(ActiveConnection.Session)
1743         self.SMIterator.Begin()
1744         self.AProxy = None
1745         self.Group = None
1746         self.Key = None
1747
1748     def __iter__(self):
1749         return self
1750
1751     def next(self):
1752         if self.SMIterator.IsAtEnd():
1753             self.AProxy = None
1754             self.Group = None
1755             self.Key = None
1756             raise StopIteration
1757             return None
1758         self.AProxy = _getPyProxy(self.SMIterator.GetProxy())
1759         self.Group = self.SMIterator.GetGroup()
1760         self.Key = self.SMIterator.GetKey()
1761         self.SMIterator.Next()
1762         return self.AProxy
1763
1764     def GetProxy(self):
1765         """Returns the proxy last returned by the call to 'next()'"""
1766         return self.AProxy
1767
1768     def GetKey(self):
1769         """Returns the key for the proxy last returned by the call to
1770         'next()' """
1771         return self.Key
1772
1773     def GetGroup(self):
1774         """Returns the group for the proxy last returned by the call to
1775         'next()' """
1776         return self.Group
1777
1778     def __getattr__(self, name):
1779         """returns attributes from the vtkSMProxyIterator."""
1780         return getattr(self.SMIterator, name)
1781
1782 # Caution: Observers must be global methods otherwise we run into memory
1783 #          leak when the interpreter get reset from the C++ layer.
1784 def _update_definitions(caller, event):
1785     updateModules(ActiveConnection.Modules)
1786
1787 class Connection(object):
1788     """
1789       This is a python representation for a session/connection.
1790     """
1791     def __init__(self, connectionId, session):
1792         """Default constructor. Creates a Connection with the given
1793         ID, all other data members initialized to None."""
1794         global MultiServerConnections
1795         global ActiveConnection
1796         self.ID = connectionId
1797         self.Session = session
1798         self.Modules = PVModule()
1799         self.Alive = True
1800         self.DefinitionObserverTag = 0
1801         self.CustomDefinitionObserverTag = 0
1802         if MultiServerConnections == None and ActiveConnection:
1803             raise RuntimeError, "Concurrent connections not supported!"
1804         if MultiServerConnections != None and not self in MultiServerConnections:
1805            MultiServerConnections.append(self)
1806         ActiveConnection = self
1807         __InitAfterConnect__(self)
1808         __exposeActiveModules__()
1809
1810     def __eq__(self, other):
1811         "Returns true if the connection ids are the same."
1812         return (self.ID == other.ID)
1813
1814     def __repr__(self):
1815         """User friendly string representation"""
1816         return "Connection (%s) [%d]" % (self.Session.GetURI(), self.ID)
1817
1818     def GetURI(self):
1819         """Get URI of the connection"""
1820         return self.Session.GetURI()
1821
1822     def IsRemote(self):
1823         """Returns True if the connection to a remote server, False if
1824         it is local (built-in)"""
1825         if self.Session.IsA("vtkSMSessionClient"):
1826             return True
1827         return False
1828
1829     def GetNumberOfDataPartitions(self):
1830         """Returns the number of partitions on the data server for this
1831            connection"""
1832         return self.Session.GetServerInformation().GetNumberOfProcesses()
1833
1834     def AttachDefinitionUpdater(self):
1835         """Attach observer to automatically update modules when needed."""
1836         # VTN: Observers are not supported
1837         # ProxyDefinitionsUpdated = 2000
1838 ##        self.DefinitionObserverTag = self.Session.GetProxyDefinitionManager().AddObserver(2000, _update_definitions)
1839         # CompoundProxyDefinitionsUpdated = 2001
1840 ##        self.CustomDefinitionObserverTag = self.Session.GetProxyDefinitionManager().AddObserver(2001, _update_definitions)
1841         pass
1842
1843     def close(self):
1844         if self.DefinitionObserverTag:
1845             self.Session.GetProxyDefinitionManager().RemoveObserver(self.DefinitionObserverTag)
1846             self.Session.GetProxyDefinitionManager().RemoveObserver(self.CustomDefinitionObserverTag)
1847         self.Session = None
1848         self.Modules = None
1849         self.Alive = False
1850
1851     def __del__(self):
1852         if self.Alive:
1853            self.close()
1854
1855 def SaveState(filename):
1856     """Given a state filename, saves the state of objects registered
1857     with the proxy manager."""
1858     pm = ProxyManager()
1859     pm.SaveState(filename)
1860
1861 def LoadState(filename, connection=None):
1862     """Given a state filename and an optional connection, loads the server
1863     manager state."""
1864     if not connection:
1865         connection = ActiveConnection
1866     if not connection:
1867         raise RuntimeError, "Cannot load state without a connection"
1868     pm = ProxyManager()
1869     pm.LoadState(filename, None)
1870     views = GetRenderViews()
1871     for view in views:
1872         # Make sure that the client window size matches the
1873         # ViewSize property. In paraview, the GUI takes care
1874         # of this.
1875         if view.GetClassName() == "vtkSMIceTDesktopRenderViewProxy":
1876             view.GetRenderWindow().SetSize(view.ViewSize[0], \
1877                                            view.ViewSize[1])
1878
1879 def InitFromGUI():
1880     """
1881     Method used to initialize the Python Shell from the ParaView GUI.
1882     """
1883     global fromGUI, ActiveConnection
1884     if not fromGUI:
1885        print "from paraview.simple import *"
1886     fromGUI = True
1887     # ToggleProgressPrinting() ### FIXME COLLABORATION
1888     enableMultiServer(vtkProcessModule.GetProcessModule().GetMultipleSessionsSupport())
1889     iter = vtkProcessModule.GetProcessModule().NewSessionIterator();
1890     iter.InitTraversal()
1891     ActiveConnection = None
1892     activeSession = vtkSMProxyManager.GetProxyManager().GetActiveSession()
1893     tmpActiveConnection = None
1894     while not iter.IsDoneWithTraversal():
1895        c = Connection(iter.GetCurrentSessionId(), iter.GetCurrentSession())
1896        if c.Session == activeSession:
1897           tmpActiveConnection = c
1898        iter.GoToNextItem()
1899     iter.UnRegister(None)
1900     if tmpActiveConnection:
1901        ActiveConnection = tmpActiveConnection
1902
1903 def Connect(ds_host=None, ds_port=11111, rs_host=None, rs_port=22221):
1904     """
1905     Use this function call to create a new session. On success,
1906     it returns a vtkSMSession object that abstracts the connection.
1907     Otherwise, it returns None.
1908     There are several ways in which this function can be called:
1909     * When called with no arguments, it creates a new session
1910      to the built-in server on the client itself.
1911     * When called with ds_host and ds_port arguments, it
1912       attempts to connect to a server(data and render server on the same server)
1913       on the indicated host:port.
1914     * When called with ds_host, ds_port, rs_host, rs_port, it
1915       creates a new connection to the data server on ds_host:ds_port and to the
1916       render server on rs_host: rs_port.
1917     """
1918     global fromGUI
1919     if fromGUI:
1920         raise RuntimeError, "Cannot create a session through python. Use the GUI to setup the connection."
1921     if ds_host == None:
1922         session = vtkSMSession()
1923     elif rs_host == None:
1924         session = vtkSMSessionClient()
1925         session.Connect("cs://%s:%d" % (ds_host, ds_port))
1926     else:
1927         session = vtkSMSessionClient()
1928         session.Connect("cdsrs://%s:%d/%s:%d" % (ds_host, ds_port, rs_host, rs_port))
1929     id = vtkProcessModule.GetProcessModule().RegisterSession(session)
1930     connection = Connection(id, session)
1931     return connection
1932
1933 def ReverseConnect(port=11111):
1934     """
1935     Use this function call to create a new session. On success,
1936     it returns a Session object that abstracts the connection.
1937     Otherwise, it returns None.
1938     In reverse connection mode, the client waits for a connection
1939     from the server (client has to be started first). The server
1940     then connects to the client (run pvserver with -rc and -ch
1941     option).
1942     The optional port specified the port to listen to.
1943     """
1944     global fromGUI
1945     if fromGUI:
1946         raise RuntimeError, "Cannot create a connection through python. Use the GUI to setup the connection."
1947     session = vtkSMSessionClient()
1948     session.Connect("csrc://hostname:" + port)
1949     id = vtkProcessModule.GetProcessModule().RegisterSession(session)
1950     connection = Connection(id, session)
1951     return connection
1952
1953 def Disconnect(session=None):
1954     """Disconnects the connection. Make sure to clear the proxy manager
1955     first."""
1956     global ActiveConnection
1957     global MultiServerConnections
1958     global fromGUI
1959     if fromGUI:
1960         raise RuntimeError, "Cannot disconnect through python. Use the GUI to disconnect."
1961     if ActiveConnection and (not session or session == ActiveConnection.Session):
1962         session = ActiveConnection.Session
1963         if MultiServerConnections:
1964            MultiServerConnections.remove(ActiveConnection)
1965            ActiveConnection.close()
1966            ActiveConnection = None
1967            switchActiveConnection()
1968         else:
1969            ActiveConnection.close()
1970            ActiveConnection = None
1971     elif MultiServerConnections:
1972         for connection in MultiServerConnections:
1973           if connection.Session == session:
1974             connection.close()
1975             MultiServerConnections.remove(connection)
1976     if session:
1977       vtkProcessModule.GetProcessModule().UnRegisterSession(session)
1978     return
1979
1980 def CreateProxy(xml_group, xml_name, session=None):
1981     """Creates a proxy. If session is set, the proxy's session is
1982     set accordingly. If session is None, the current Session is used, if
1983     present. You should not have to use method normally. Instantiate the
1984     appropriate class from the appropriate module, for example:
1985     sph = servermanager.sources.SphereSource()"""
1986     global ActiveConnection
1987     if not session:
1988         session = ActiveConnection.Session
1989     if not session:
1990         raise RuntimeError, "Cannot create objects without a session."
1991     pxm = ProxyManager(session)
1992     return pxm.NewProxy(xml_group, xml_name)
1993
1994 def GetRenderView(connection=None):
1995     """Return the render view in use.  If more than one render view is in
1996     use, return the first one."""
1997
1998     render_module = None
1999     for aProxy in ProxyManager():
2000         if aProxy.IsA("vtkSMRenderViewProxy"):
2001             render_module = aProxy
2002             break
2003     return render_module
2004
2005 def GetRenderViews(connection=None):
2006     """Returns the set of all render views."""
2007     render_modules = []
2008     for aProxy in ProxyManager():
2009         if aProxy.IsA("vtkSMRenderViewProxy"):
2010             render_modules.append(aProxy)
2011     return render_modules
2012
2013 def GetContextViews(connection=None):
2014     """Returns the set of all context views."""
2015     context_modules = []
2016     for aProxy in ProxyManager():
2017         if aProxy.IsA("vtkSMContextViewProxy"):
2018             context_modules.append(aProxy)
2019     return context_modules
2020
2021 def CreateRenderView(session=None, **extraArgs):
2022     """Creates a render window on the particular session. If session
2023     is not specified, then the active session is used, if available.
2024
2025     This method can also be used to initialize properties by passing
2026     keyword arguments where the key is the name of the property. In addition
2027     registrationGroup and registrationName (optional) can be specified (as
2028     keyword arguments) to automatically register the proxy with the proxy
2029     manager."""
2030     return _create_view("RenderView", session, **extraArgs)
2031
2032 def _create_view(view_xml_name, session=None, **extraArgs):
2033     """Creates a view on the particular session. If session
2034     is not specified, then the active session is used, if available.
2035     This method can also be used to initialize properties by passing
2036     keyword arguments where the key is the name of the property."""
2037     if not session:
2038         session = ActiveConnection.Session
2039     if not session:
2040         raise RuntimeError, "Cannot create view without session."
2041     pxm = ProxyManager()
2042     view_module = None
2043     if view_xml_name:
2044         view_module = CreateProxy("views", view_xml_name, session)
2045     if not view_module:
2046         return None
2047     extraArgs['proxy'] = view_module
2048     python_proxy_name = _make_name_valid(view_module.GetXMLName())
2049     proxy = rendering.__dict__[python_proxy_name](**extraArgs)
2050     return proxy
2051
2052 def GetRepresentation(aProxy, view):
2053     for rep in view.Representations:
2054         #VSV: ==
2055         try: isRep = rep.Input.IsSame(aProxy)
2056         except: isRep = False
2057         if isRep: return rep
2058     return None
2059
2060 def CreateRepresentation(aProxy, view, **extraArgs):
2061     """Creates a representation for the proxy and adds it to the render
2062     module.
2063
2064     This method can also be used to initialize properties by passing
2065     keyword arguments where the key is the name of the property.In addition
2066     registrationGroup and registrationName (optional) can be specified (as
2067     keyword arguments) to automatically register the proxy with the proxy
2068     manager.
2069
2070     This method tries to create the best possible representation for the given
2071     proxy in the given view. Additionally, the user can specify proxyName
2072     (optional) to create a representation of a particular type."""
2073
2074     global rendering
2075     if not aProxy:
2076         raise RuntimeError, "proxy argument cannot be None."
2077     if not view:
2078         raise RuntimeError, "view argument cannot be None."
2079     if "proxyName" in extraArgs:
2080       display = CreateProxy("representations", extraArgs['proxyName'], None)
2081       del extraArgs['proxyName']
2082     else:
2083       display = view.SMProxy.CreateDefaultRepresentation(aProxy.SMProxy, 0)
2084       if display:
2085         display.UnRegister(None)
2086     if not display:
2087         return None
2088     extraArgs['proxy'] = display
2089     proxy = rendering.__dict__[display.GetXMLName()](**extraArgs)
2090     proxy.Input = aProxy
2091     proxy.UpdateVTKObjects()
2092     view.Representations.append(proxy)
2093     return proxy
2094
2095 class _ModuleLoader(object):
2096     def find_module(self, fullname, path=None):
2097         if vtkPVPythonModule.HasModule(fullname):
2098             return self
2099         else:
2100             return None
2101     def load_module(self, fullname):
2102         import imp
2103         moduleInfo = vtkPVPythonModule.GetModule(fullname)
2104         if not moduleInfo:
2105             raise ImportError
2106         module = sys.modules.setdefault(fullname, imp.new_module(fullname))
2107         module.__file__ = "<%s>" % moduleInfo.GetFullName()
2108         module.__loader__ = self
2109         if moduleInfo.GetIsPackage:
2110             module.__path__ = moduleInfo.GetFullName()
2111         code = compile(moduleInfo.GetSource(), module.__file__, 'exec')
2112         exec code in module.__dict__
2113         return module
2114
2115 def LoadXML(xmlstring):
2116     """DEPRECATED. Given a server manager XML as a string, parse and process it."""
2117     raise RuntimeError, "Deprecated. Use LoadPlugin(...) instead."
2118
2119
2120 def LoadPlugin(filename,  remote=True, connection=None):
2121     """ Given a filename and a session (optional, otherwise uses
2122     ActiveConnection), loads a plugin. It then updates the sources,
2123     filters and rendering modules."""
2124
2125     if not connection:
2126         connection = ActiveConnection
2127     if not connection:
2128         raise RuntimeError, "Cannot load a plugin without a connection."
2129     plm = vtkSMProxyManager.GetProxyManager().GetPluginManager()
2130
2131     if remote:
2132         status = plm.LoadRemotePlugin(filename, connection.Session)
2133     else:
2134         status = plm.LoadLocalPlugin(filename)
2135
2136     # shouldn't the extension check happend before attempting to load the plugin?
2137     if not status:
2138         raise RuntimeError, "Problem loading plugin %s" % (filename)
2139     else:
2140         # we should never have to call this. The modules should update automatically.
2141         updateModules(connection.Modules)
2142
2143
2144 def Fetch(input, arg1=None, arg2=None, idx=0):
2145     """
2146     A convenience method that moves data from the server to the client,
2147     optionally performing some operation on the data as it moves.
2148     The input argument is the name of the (proxy for a) source or filter
2149     whose output is needed on the client.
2150
2151     You can use Fetch to do three things:
2152
2153     If arg1 is None (the default) then all of the data is brought to the client.
2154     In parallel runs an appropriate append Filter merges the
2155     data on each processor into one data object. The filter chosen will be
2156     vtkAppendPolyData for vtkPolyData, vtkAppendRectilinearGrid for
2157     vtkRectilinearGrid, vtkMultiBlockDataGroupFilter for vtkCompositeData,
2158     and vtkAppendFilter for anything else.
2159
2160     If arg1 is an integer then one particular processor's output is brought to
2161     the client. In serial runs the arg is ignored. If you have a filter that
2162     computes results in parallel and brings them to the root node, then set
2163     arg to be 0.
2164
2165     If arg1 and arg2 are a algorithms, for example vtkMinMax, the algorithm
2166     will be applied to the data to obtain some result. Here arg1 will be
2167     applied pre-gather and arg2 will be applied post-gather. In parallel
2168     runs the algorithm will be run on each processor to make intermediate
2169     results and then again on the root processor over all of the
2170     intermediate results to create a global result.
2171
2172     Optional argument idx is used to specify the output port number to fetch the
2173     data from. Default is port 0.
2174     """
2175
2176     import types
2177
2178     reducer = filters.ReductionFilter(Input=OutputPort(input,idx))
2179
2180     #create the pipeline that reduces and transmits the data
2181     if arg1 == None:
2182         cdinfo = input.GetDataInformation(idx).GetCompositeDataInformation()
2183         if cdinfo.GetDataIsComposite():
2184             print "use composite data append"
2185             reducer.PostGatherHelperName = "vtkMultiBlockDataGroupFilter"
2186
2187         elif input.GetDataInformation(idx).GetDataClassName() == "vtkPolyData":
2188             print "use append poly data filter"
2189             reducer.PostGatherHelperName = "vtkAppendPolyData"
2190
2191         elif input.GetDataInformation(idx).GetDataClassName() == "vtkRectilinearGrid":
2192             print "use append rectilinear grid filter"
2193             reducer.PostGatherHelperName = "vtkAppendRectilinearGrid"
2194
2195         elif input.GetDataInformation(idx).IsA("vtkDataSet"):
2196             print "use unstructured append filter"
2197             reducer.PostGatherHelperName = "vtkAppendFilter"
2198
2199     elif type(arg1) is types.IntType:
2200         reducer.PassThrough = arg1
2201
2202     else:
2203         reducer.PreGatherHelper = arg1
2204         reducer.PostGatherHelper = arg2
2205
2206     # reduce
2207     reducer.UpdatePipeline()
2208     dataInfo = reducer.GetDataInformation(0)
2209     dataType = dataInfo.GetDataSetType()
2210     if dataInfo.GetCompositeDataSetType() > 0:
2211       dataType = dataInfo.GetCompositeDataSetType()
2212
2213     fetcher = filters.ClientServerMoveData(Input=reducer)
2214     fetcher.OutputDataType = dataType
2215     fetcher.WholeExtent = dataInfo.GetExtent()[:]
2216     #fetch
2217     fetcher.UpdatePipeline()
2218
2219     op = fetcher.GetClientSideObject().GetOutputDataObject(0)
2220     opc = op.NewInstance()
2221     opc.ShallowCopy(op)
2222     opc.UnRegister(None)
2223     return opc
2224
2225 def AnimateReader(reader, view, filename=None):
2226     """This is a utility function that, given a reader and a view
2227     animates over all time steps of the reader. If the optional
2228     filename is provided, a movie is created (type depends on the
2229     extension of the filename."""
2230     if not reader:
2231         raise RuntimeError, "No reader was specified, cannot animate."
2232     if not view:
2233         raise RuntimeError, "No view was specified, cannot animate."
2234     # Create an animation scene
2235     scene = animation.AnimationScene()
2236
2237     # We need to have the reader and the view registered with
2238     # the time keeper. This is how the scene gets its time values.
2239     try:
2240         tk = ProxyManager().GetProxiesInGroup("timekeeper").values()[0]
2241         scene.TimeKeeper = tk
2242     except IndexError:
2243         tk = misc.TimeKeeper()
2244         scene.TimeKeeper = tk
2245
2246     if not reader in tk.TimeSources:
2247         tk.TimeSources.append(reader)
2248     if not view in tk.Views:
2249         tk.Views.append(view)
2250
2251
2252     # with 1 view
2253     scene.ViewModules = [view]
2254     # Update the reader to get the time information
2255     reader.UpdatePipelineInformation()
2256     # Animate from 1st time step to last
2257     scene.StartTime = reader.TimestepValues.GetData()[0]
2258     scene.EndTime = reader.TimestepValues.GetData()[-1]
2259
2260     # Each frame will correspond to a time step
2261     scene.PlayMode = 2 #Snap To Timesteps
2262
2263     # Create a special animation cue for time.
2264     cue = animation.TimeAnimationCue()
2265     cue.AnimatedProxy = view
2266     cue.AnimatedPropertyName = "ViewTime"
2267     scene.Cues = [cue]
2268
2269     if filename:
2270         writer = vtkSMAnimationSceneImageWriter()
2271         writer.SetFileName(filename)
2272         writer.SetFrameRate(1)
2273         writer.SetAnimationScene(scene.SMProxy)
2274
2275         # Now save the animation.
2276         if not writer.Save():
2277             raise RuntimeError, "Saving of animation failed!"
2278     else:
2279         scene.Play()
2280     return scene
2281
2282 def GetProgressPrintingIsEnabled():
2283     return progressObserverTag is not None
2284
2285 def SetProgressPrintingEnabled(value):
2286     """Is not supported because of not supported observers"""
2287     pass
2288
2289 def ToggleProgressPrinting():
2290     """Turn on/off printing of progress.  See SetProgressPrintingEnabled."""
2291     SetProgressPrintingEnabled(not GetProgressPrintingIsEnabled())
2292
2293 def Finalize():
2294     """Although not required, this can be called at exit to cleanup."""
2295     global progressObserverTag
2296     # Make sure to remove the observer
2297     if progressObserverTag:
2298         ToggleProgressPrinting()
2299     vtkInitializationHelper.Finalize()
2300
2301 # Internal methods
2302
2303 def _getPyProxy(smproxy, outputPort=0):
2304     """Returns a python wrapper for a server manager proxy. This method
2305     first checks if there is already such an object by looking in the
2306     _pyproxies group and returns it if found. Otherwise, it creates a
2307     new one. Proxies register themselves in _pyproxies upon creation."""
2308     if not smproxy:
2309         return None
2310     if (smproxy, outputPort) in _pyproxies:
2311         return _pyproxies[(smproxy, outputPort)]()
2312
2313     xmlName = smproxy.GetXMLName()
2314     if smproxy.GetXMLLabel():
2315         xmlName = smproxy.GetXMLLabel()
2316     classForProxy = _findClassForProxy(_make_name_valid(xmlName), smproxy.GetXMLGroup())
2317     if classForProxy:
2318         retVal = classForProxy(proxy=smproxy, port=outputPort)
2319     else:
2320         retVal = Proxy(proxy=smproxy, port=outputPort)
2321     return retVal
2322
2323 def _makeUpdateCameraMethod(rv):
2324     """ This internal method is used to create observer methods """
2325     if not hasattr(rv(), "BlockUpdateCamera"):
2326         rv().add_attribute("BlockUpdateCamera", False)
2327     def UpdateCamera(obj, string):
2328         if not rv().BlockUpdateCamera:
2329           # used to avoid some nasty recursion that occurs when interacting in
2330           # the GUI.
2331           rv().BlockUpdateCamera = True
2332           rv().SynchronizeCameraProperties()
2333           rv().BlockUpdateCamera = False
2334     return UpdateCamera
2335
2336 def _createInitialize(group, name):
2337     """Internal method to create an Initialize() method for the sub-classes
2338     of Proxy"""
2339     pgroup = group
2340     pname = name
2341     def aInitialize(self, connection=None, update=True):
2342         if not connection:
2343             connection = ActiveConnection
2344         if not connection:
2345             raise RuntimeError,\
2346                   'Cannot create a proxy without a session.'
2347         if not connection.Session.GetProxyDefinitionManager().HasDefinition(pgroup, pname):
2348             error_msg = "The connection does not provide any definition for %s." % pname
2349             raise RuntimeError, error_msg
2350         self.InitializeFromProxy(\
2351             CreateProxy(pgroup, pname, connection.Session), update)
2352     return aInitialize
2353
2354 def _createGetProperty(pName):
2355     """Internal method to create a GetXXX() method where XXX == pName."""
2356     propName = pName
2357     def getProperty(self):
2358         return self.GetPropertyValue(propName)
2359     return getProperty
2360
2361 def _createSetProperty(pName):
2362     """Internal method to create a SetXXX() method where XXX == pName."""
2363     propName = pName
2364     def setProperty(self, value):
2365         return self.SetPropertyWithName(propName, value)
2366     return setProperty
2367
2368 def _findClassForProxy(xmlName, xmlGroup):
2369     """Given the xmlName for a proxy, returns a Proxy class. Note
2370     that if there are duplicates, the first one is returned."""
2371     global sources, filters, writers, rendering, animation, implicit_functions,\
2372            piecewise_functions, extended_sources, misc
2373     if not xmlName:
2374         return None
2375     if xmlGroup == "sources":
2376         return sources.__dict__[xmlName]
2377     elif xmlGroup == "filters":
2378         return filters.__dict__[xmlName]
2379     elif xmlGroup == "implicit_functions":
2380         return implicit_functions.__dict__[xmlName]
2381     elif xmlGroup == "piecewise_functions":
2382         return piecewise_functions.__dict__[xmlName]
2383     elif xmlGroup == "writers":
2384         return writers.__dict__[xmlName]
2385     elif xmlGroup == "extended_sources":
2386         return extended_sources.__dict__[xmlName]
2387     elif xmlName in rendering.__dict__:
2388         return rendering.__dict__[xmlName]
2389     elif xmlName in animation.__dict__:
2390         return animation.__dict__[xmlName]
2391     elif xmlName in misc.__dict__:
2392         return misc.__dict__[xmlName]
2393     else:
2394         return None
2395
2396 def _printProgress(caller, event):
2397     """The default event handler for progress. Prints algorithm
2398     name and 1 '.' per 10% progress."""
2399     global currentAlgorithm, currentProgress
2400
2401     pm = vtkProcessModule.GetProcessModule()
2402     progress = pm.GetLastProgress() / 10
2403     # If we got a 100% as the first thing, ignore
2404     # This is to get around the fact that some vtk
2405     # algorithms report 100% more than once (which is
2406     # a bug)
2407     if not currentAlgorithm and progress == 10:
2408         return
2409     alg = pm.GetLastProgressName()
2410     if alg != currentAlgorithm and alg:
2411         if currentAlgorithm:
2412             while currentProgress <= 10:
2413                 import sys
2414                 sys.stdout.write(".")
2415                 currentProgress += 1
2416             print "]"
2417             currentProgress = 0
2418         print alg, ": [ ",
2419         currentAlgorithm = alg
2420     while currentProgress <= progress:
2421         import sys
2422         sys.stdout.write(".")
2423         #sys.stdout.write("%d " % pm.GetLastProgress())
2424         currentProgress += 1
2425     if progress == 10:
2426         print "]"
2427         currentAlgorithm = None
2428         currentProgress = 0
2429
2430 def updateModules(m):
2431     """Called when a plugin is loaded, this method updates
2432     the proxy class object in all known modules."""
2433
2434     createModule("sources", m.sources)
2435     createModule("filters", m.filters)
2436     createModule("writers", m.writers)
2437     createModule("representations", m.rendering)
2438     createModule("views", m.rendering)
2439     createModule("lookup_tables", m.rendering)
2440     createModule("textures", m.rendering)
2441     createModule('cameramanipulators', m.rendering)
2442     createModule("animation", m.animation)
2443     createModule("misc", m.misc)
2444     createModule('animation_keyframes', m.animation)
2445     createModule('implicit_functions', m.implicit_functions)
2446     createModule('piecewise_functions', m.piecewise_functions)
2447     createModule("extended_sources", m.extended_sources)
2448     createModule("incremental_point_locators", m.misc)
2449
2450 def _createModules(m):
2451     """Called when the module is loaded, this creates sub-
2452     modules for all know proxy groups."""
2453
2454     m.sources = createModule('sources')
2455     m.filters = createModule('filters')
2456     m.writers = createModule('writers')
2457     m.rendering = createModule('representations')
2458     createModule('views', m.rendering)
2459     createModule("lookup_tables", m.rendering)
2460     createModule("textures", m.rendering)
2461     createModule('cameramanipulators', m.rendering)
2462     m.animation = createModule('animation')
2463     createModule('animation_keyframes', m.animation)
2464     m.implicit_functions = createModule('implicit_functions')
2465     m.piecewise_functions = createModule('piecewise_functions')
2466     m.extended_sources = createModule("extended_sources")
2467     m.misc = createModule("misc")
2468     createModule("incremental_point_locators", m.misc)
2469
2470 class PVModule(object):
2471     pass
2472
2473 def _make_name_valid(name):
2474     """Make a string into a valid Python variable name."""
2475     if not name:
2476         return None
2477     import string
2478     valid_chars = "_%s%s" % (string.ascii_letters, string.digits)
2479     name = str().join([c for c in name if c in valid_chars])
2480     if not name[0].isalpha():
2481         name = 'a' + name
2482     return name
2483
2484 def createModule(groupName, mdl=None):
2485     """Populates a module with proxy classes defined in the given group.
2486     If mdl is not specified, it also creates the module"""
2487     global ActiveConnection
2488
2489     if not ActiveConnection:
2490       raise RuntimeError, "Please connect to a server using \"Connect\""
2491
2492     pxm = ProxyManager()
2493     # Use prototypes to find all proxy types.
2494     pxm.InstantiateGroupPrototypes(groupName)
2495
2496     debug = False
2497     if not mdl:
2498         debug = True
2499         mdl = PVModule()
2500     definitionIter = pxm.NewDefinitionIterator(groupName)
2501     for i in definitionIter:
2502         proxyName = i['key']
2503         proto = pxm.GetPrototypeProxy(groupName, proxyName)
2504         if not proto:
2505            print "Error while loading %s/%s %s"%(groupName, i['group'], proxyName)
2506            continue
2507         pname = proxyName
2508         if proto.GetXMLLabel():
2509             pname = proto.GetXMLLabel()
2510         pname = _make_name_valid(pname)
2511         if not pname:
2512             continue
2513         if pname in mdl.__dict__:
2514             if debug:
2515                 print "Warning: %s is being overwritten. This may point to an issue in the ParaView configuration files" % pname
2516         cdict = {}
2517         # Create an Initialize() method for this sub-class.
2518         cdict['Initialize'] = _createInitialize(groupName, proxyName)
2519         iter = PropertyIterator(proto)
2520         # Add all properties as python properties.
2521         for prop in iter:
2522             propName = iter.GetKey()
2523             if (prop.GetInformationOnly() and propName != "TimestepValues" ) \
2524                    or prop.GetIsInternal():
2525                 continue
2526             names = [propName]
2527             names = [iter.PropertyLabel]
2528                 
2529             propDoc = None
2530             if prop.GetDocumentation():
2531                 propDoc = prop.GetDocumentation().GetDescription()
2532             for name in names:
2533                 name = _make_name_valid(name)
2534                 if name:
2535                     cdict[name] = property(_createGetProperty(propName),
2536                                            _createSetProperty(propName),
2537                                            None,
2538                                            propDoc)
2539         # Add the documentation as the class __doc__
2540         if proto.GetDocumentation() and \
2541            proto.GetDocumentation().GetDescription():
2542             doc = proto.GetDocumentation().GetDescription()
2543         else:
2544             doc = Proxy.__doc__
2545         cdict['__doc__'] = doc
2546         # Create the new type
2547         if proto.GetXMLName() == "ExodusIIReader":
2548             superclasses = (ExodusIIReaderProxy,)
2549         elif proto.IsA("vtkSMSourceProxy"):
2550             superclasses = (SourceProxy,)
2551         elif proto.IsA("vtkSMViewLayoutProxy"):
2552             superclasses = (ViewLayoutProxy,)
2553         else:
2554             superclasses = (Proxy,)
2555
2556         cobj = type(pname, superclasses, cdict)
2557         # Add it to the modules dictionary
2558         mdl.__dict__[pname] = cobj
2559     return mdl
2560
2561
2562 def __determineGroup(proxy):
2563     """Internal method"""
2564     if not proxy:
2565         return None
2566     xmlgroup = proxy.GetXMLGroup()
2567     xmlname = proxy.GetXMLName()
2568     if xmlgroup == "sources":
2569         if xmlname in ["BlockSelectionSource",
2570                        "FrustumSelectionSource",
2571                        "GlobalIDSelectionSource",
2572                        "PedigreeIDSelectionSource",
2573                        "IDSelectionSource",
2574                        "CompositeDataIDSelectionSource",
2575                        "HierarchicalDataIDSelectionSource",
2576                        "ThresholdSelectionSource",
2577                        "LocationSelectionSource"]:
2578             return "selection_sources"
2579         return "sources"
2580     elif xmlgroup == "filters":
2581         return "sources"
2582     elif xmlgroup == "representations":
2583         if xmlname == "ScalarBarWidgetRepresentation":
2584             return "scalar_bars"
2585         return "representations"
2586     elif xmlgroup == "animation_keyframes":
2587         return "animation"
2588     return xmlgroup
2589
2590 __nameCounter = {}
2591 def __determineName(proxy, group):
2592     global __nameCounter
2593     name = _make_name_valid(proxy.GetXMLLabel())
2594     if not name:
2595         return None
2596     if not __nameCounter.has_key(name):
2597         __nameCounter[name] = 1
2598         val = 1
2599     else:
2600         __nameCounter[name] += 1
2601         val = __nameCounter[name]
2602     return "%s%d" % (name, val)
2603
2604 def __getName(proxy, group):
2605     pxm = ProxyManager(proxy.GetSession())
2606     if isinstance(proxy, Proxy):
2607         proxy = proxy.SMProxy
2608     return pxm.GetProxyName(group, proxy)
2609
2610 class MissingRegistrationInformation(Exception):
2611     """Exception for missing registration information. Raised when a name or group 
2612     is not specified or when a group cannot be deduced."""
2613     pass
2614
2615 class MissingProxy(Exception):
2616     """Exception fired when the requested proxy is missing."""
2617     pass
2618     
2619 def Register(proxy, **extraArgs):
2620     """Registers a proxy with the proxy manager. If no 'registrationGroup' is
2621     specified, then the group is inferred from the type of the proxy.
2622     'registrationName' may be specified to register with a particular name
2623     otherwise a default name will be created."""
2624     # TODO: handle duplicate registration
2625     if "registrationGroup" in extraArgs:
2626         registrationGroup = extraArgs["registrationGroup"]
2627     else:
2628         registrationGroup = __determineGroup(proxy)
2629
2630     if "registrationName" in extraArgs:
2631         registrationName = extraArgs["registrationName"]
2632     else:
2633         registrationName = __determineName(proxy, registrationGroup)
2634     if registrationGroup and registrationName:
2635         pxm = ProxyManager()
2636         pxm.RegisterProxy(registrationGroup, registrationName, proxy)
2637     else:
2638         raise MissingRegistrationInformation, "Registration error %s %s." % (registrationGroup, registrationName)
2639     return (registrationGroup, registrationName)
2640
2641 def UnRegister(proxy, **extraArgs):
2642     """UnRegisters proxies registered using Register()."""
2643     if "registrationGroup" in extraArgs:
2644         registrationGroup = extraArgs["registrationGroup"]
2645     else:
2646         registrationGroup = __determineGroup(proxy)
2647
2648     if "registrationName" in extraArgs:
2649         registrationName = extraArgs["registrationName"]
2650     else:
2651         registrationName = __getName(proxy, registrationGroup)
2652
2653     if registrationGroup and registrationName:
2654         pxm = ProxyManager()
2655         pxm.UnRegisterProxy(registrationGroup, registrationName, proxy)
2656     else:
2657         raise RuntimeError, "UnRegistration error."
2658     return (registrationGroup, registrationName)
2659
2660 def demo1():
2661     """This simple demonstration creates a sphere, renders it and delivers
2662     it to the client using Fetch. It returns a tuple of (data, render
2663     view)"""
2664     if not ActiveConnection:
2665         Connect()
2666     ss = sources.Sphere(Radius=2, ThetaResolution=32)
2667     shr = filters.Shrink(Input=OutputPort(ss,0))
2668     cs = sources.Cone()
2669     app = filters.AppendDatasets()
2670     app.Input = [shr, cs]
2671     rv = CreateRenderView()
2672     rep = CreateRepresentation(app, rv)
2673     rv.ResetCamera()
2674     rv.StillRender()
2675     data = Fetch(ss)
2676
2677     return (data, rv)
2678
2679 def demo2(fname="/Users/berk/Work/ParaViewData/Data/disk_out_ref.ex2"):
2680     """This method demonstrates the user of a reader, representation and
2681     view. It also demonstrates how meta-data can be obtained using proxies.
2682     Make sure to pass the full path to an exodus file. Also note that certain
2683     parameters are hard-coded for disk_out_ref.ex2 which can be found
2684     in ParaViewData. This method returns the render view."""
2685     if not ActiveConnection:
2686         Connect()
2687     # Create the exodus reader and specify a file name
2688     reader = sources.ExodusIIReader(FileName=fname)
2689     # Get the list of point arrays.
2690     arraySelection = reader.PointVariables
2691     print arraySelection.Available
2692     # Select all arrays
2693     arraySelection.SetData(arraySelection.Available)
2694
2695     # Next create a default render view appropriate for the session type.
2696     rv = CreateRenderView()
2697     # Create the matching representation
2698     rep = CreateRepresentation(reader, rv)
2699     rep.Representation = 1 # Wireframe
2700     # Black background is not pretty
2701     rv.Background = [0.4, 0.4, 0.6]
2702     rv.StillRender()
2703     # Reset the camera to include the whole thing
2704     rv.ResetCamera()
2705     rv.StillRender()
2706     # Change the elevation of the camera. See VTK documentation of vtkCamera
2707     # for camera parameters.
2708     c = rv.GetActiveCamera()
2709     c.Elevation(45)
2710     rv.StillRender()
2711     # Now that the reader execute, let's get some information about it's
2712     # output.
2713     pdi = reader[0].PointData
2714     # This prints a list of all read point data arrays as well as their
2715     # value ranges.
2716     print 'Number of point arrays:', len(pdi)
2717     for i in range(len(pdi)):
2718         ai = pdi[i]
2719         print "----------------"
2720         print "Array:", i, ai.Name, ":"
2721         numComps = ai.GetNumberOfComponents()
2722         print "Number of components:", numComps
2723         for j in range(numComps):
2724             print "Range:", ai.GetRange(j)
2725     # White is boring. Let's color the geometry using a variable.
2726     # First create a lookup table. This object controls how scalar
2727     # values are mapped to colors. See VTK documentation for
2728     # details.
2729     lt = rendering.PVLookupTable()
2730     # Assign it to the representation
2731     rep.LookupTable = lt
2732     # Color by point array called Pres
2733     rep.ColorAttributeType = 0 # point data
2734     rep.ColorArrayName = "Pres"
2735     # Add to RGB points. These are tuples of 4 values. First one is
2736     # the scalar values, the other 3 the RGB values. This list has
2737     # 2 points: Pres: 0.00678, color: blue, Pres: 0.0288, color: red
2738     lt.RGBPoints = [0.00678, 0, 0, 1, 0.0288, 1, 0, 0]
2739     lt.ColorSpace = 1 # HSV
2740     rv.StillRender()
2741     return rv
2742
2743 def demo3():
2744     """This method demonstrates the use of servermanager with numpy as
2745     well as pylab for plotting. It creates an artificial data sources,
2746     probes it with a line, delivers the result to the client using Fetch
2747     and plots it using pylab. This demo requires numpy and pylab installed.
2748     It returns a tuple of (data, render view)."""
2749     import paraview.numpy_support
2750     import pylab
2751
2752     if not ActiveConnection:
2753         Connect()
2754     # Create a synthetic data source
2755     source = sources.Wavelet()
2756     # Let's get some information about the data. First, for the
2757     # source to execute
2758     source.UpdatePipeline()
2759
2760     di = source.GetDataInformation()
2761     print "Data type:", di.GetPrettyDataTypeString()
2762     print "Extent:", di.GetExtent()
2763     print "Array name:", \
2764           source[0].PointData[0].Name
2765
2766     rv = CreateRenderView()
2767
2768     rep1 = CreateRepresentation(source, rv)
2769     rep1.Representation = 3 # outline
2770
2771     # Let's apply a contour filter
2772     cf = filters.Contour(Input=source, ContourValues=[200])
2773
2774     # Select the array to contour by
2775     #cf.SelectInputScalars = 'RTData'
2776
2777     rep2 = CreateRepresentation(cf, rv)
2778
2779     rv.Background = (0.4, 0.4, 0.6)
2780     # Reset the camera to include the whole thing
2781     rv.StillRender()
2782     rv.ResetCamera()
2783     rv.StillRender()
2784
2785     # Now, let's probe the data
2786     probe = filters.ResampleWithDataset(Input=source)
2787     # with a line
2788     line = sources.Line(Resolution=60)
2789     # that spans the dataset
2790     bounds = di.GetBounds()
2791     print "Bounds: ", bounds
2792     line.Point1 = bounds[0:6:2]
2793     line.Point2 = bounds[1:6:2]
2794
2795     probe.Source = line
2796
2797     # Render with the line
2798     rep3 = CreateRepresentation(line, rv)
2799     rv.StillRender()
2800
2801     # Now deliver it to the client. Remember, this is for small data.
2802     data = Fetch(probe)
2803     # Convert it to a numpy array
2804     data = paraview.numpy_support.vtk_to_numpy(
2805       data.GetPointData().GetArray("RTData"))
2806     # Plot it using matplotlib
2807     pylab.plot(data)
2808     pylab.show()
2809
2810     return (data, rv, probe)
2811
2812 def demo4(fname="/Users/berk/Work/ParaViewData/Data/can.ex2"):
2813     """This method demonstrates the user of AnimateReader for
2814     creating animations."""
2815     if not ActiveConnection:
2816         Connect()
2817     reader = sources.ExodusIIReader(FileName=fname)
2818     view = CreateRenderView()
2819     repr = CreateRepresentation(reader, view)
2820     view.StillRender()
2821     view.ResetCamera()
2822     view.StillRender()
2823     c = view.GetActiveCamera()
2824     c.Elevation(95)
2825     return AnimateReader(reader, view)
2826
2827
2828 def demo5():
2829     """ Simple sphere animation"""
2830     if not ActiveConnection:
2831         Connect()
2832     sphere = sources.Sphere()
2833     view = CreateRenderView()
2834     repr = CreateRepresentation(sphere, view)
2835
2836     view.StillRender()
2837     view.ResetCamera()
2838     view.StillRender()
2839
2840     # Create an animation scene
2841     scene = animation.AnimationScene()
2842     # Add 1 view
2843     scene.ViewModules = [view]
2844
2845     # Create a cue to animate the StartTheta property
2846     cue = animation.KeyFrameAnimationCue()
2847     cue.AnimatedProxy = sphere
2848     cue.AnimatedPropertyName = "StartTheta"
2849     # Add it to the scene's cues
2850     scene.Cues = [cue]
2851
2852     # Create 2 keyframes for the StartTheta track
2853     keyf0 = animation.CompositeKeyFrame()
2854     keyf0.Type = 2 # Set keyframe interpolation type to Ramp.
2855     # At time = 0, value = 0
2856     keyf0.KeyTime = 0
2857     keyf0.KeyValues= [0]
2858
2859     keyf1 = animation.CompositeKeyFrame()
2860     # At time = 1.0, value = 200
2861     keyf1.KeyTime = 1.0
2862     keyf1.KeyValues= [200]
2863
2864     # Add keyframes.
2865     cue.KeyFrames = [keyf0, keyf1]
2866
2867     scene.Play()
2868     return scene
2869
2870 ASSOCIATIONS = { 'POINTS' : 0, 'CELLS' : 1, 'VERTICES' : 4, 'EDGES' : 5, 'ROWS' : 6}
2871
2872 # Users can set the active connection which will be used by API
2873 # to create proxies etc when no connection argument is passed.
2874 # Connect() automatically sets this if it is not already set.
2875 ActiveConnection = None
2876
2877 # Fields for multi-server support
2878 MultiServerConnections = None
2879
2880 # API for multi-server support
2881 def enableMultiServer(multiServer=True):
2882   """This method enable the current servermanager to support several
2883   connections. Once we enable the multi-server support, the user can create
2884   as many connection as he want and switch from one to another in order to
2885   create and manage proxy."""
2886   global MultiServerConnections, ActiveConnection
2887   if not multiServer and MultiServerConnections:
2888       raise RuntimeError, "Once we enable Multi-Server support we can not get back"
2889   MultiServerConnections = []
2890   if ActiveConnection:
2891     MultiServerConnections.append(ActiveConnection)
2892
2893 def switchActiveConnection(newActiveConnection=None):
2894   """Switch active connection to be the provided one or if none just pick the
2895   other one"""
2896   global MultiServerConnections, ActiveConnection
2897   if MultiServerConnections == None:
2898     raise RuntimeError, "enableMultiServer() must be called before"
2899
2900   # Manage the case when no connection is provided
2901   if newActiveConnection:
2902     ActiveConnection = newActiveConnection
2903     __exposeActiveModules__()
2904     # Update active session for ParaView
2905     if vtkSMProxyManager.GetProxyManager().GetActiveSession() != ActiveConnection.Session:
2906        vtkSMProxyManager.GetProxyManager().SetActiveSession(ActiveConnection.Session)
2907     return ActiveConnection
2908   else:
2909     for connection in MultiServerConnections:
2910       if connection != ActiveConnection:
2911          ActiveConnection = connection
2912          __exposeActiveModules__()
2913          # Update active session for ParaView
2914          if vtkSMProxyManager.GetProxyManager().GetActiveSession() != ActiveConnection.Session:
2915             vtkSMProxyManager.GetProxyManager().SetActiveSession(ActiveConnection.Session)
2916          return ActiveConnection
2917   return None
2918
2919 # Needs to be called when paraview module is loaded from python instead
2920 # of pvpython, pvbatch or GUI.
2921 if not vtkProcessModule.GetProcessModule():
2922 #    pvoptions = None Not applicable for SALOME Python console
2923 #    if paraview.options.batch:
2924 #      pvoptions = vtkPVOptions();
2925 #      pvoptions.SetProcessType(0x40)
2926 #      if paraview.options.symmetric:
2927 #        pvoptions.SetSymmetricMPIMode(True)
2928     vtkInitializationHelper.Initialize(sys.executable,
2929         vtkProcessModule.PROCESS_CLIENT, pvoptions)
2930
2931 # Initialize progress printing. Can be turned off by calling
2932 # ToggleProgressPrinting() again.
2933 progressObserverTag = None
2934 currentAlgorithm = False
2935 currentProgress = 0
2936 fromGUI = False
2937 ToggleProgressPrinting()
2938
2939 _pyproxies = {}
2940
2941 # Create needed sub-modules
2942 # We can no longer create modules, unless we have connected to a server.
2943 # _createModules()
2944
2945 # Set up our custom importer (if possible)
2946 loader = _ModuleLoader()
2947 sys.meta_path.append(loader)
2948
2949 def __InitAfterConnect__(connection):
2950     """
2951     This function is called everytime after a server connection is made.
2952     Since the ProxyManager and all proxy definitions are changed every time a
2953     new connection is made, we re-create all the modules
2954     """
2955     _createModules(connection.Modules)
2956     ## VSV fromFilter is alwais False for SALOME because it can't be changed from ParaView code
2957     #if not paraview.fromFilter:
2958         # fromFilter is set when this module is imported from the programmable
2959         # filter
2960 #    global _defUpdater
2961 #    _defUpdater = __DefinitionUpdater()
2962     connection.AttachDefinitionUpdater()
2963     pass
2964
2965 def __exposeActiveModules__():
2966     """Update servermanager submodules to point to the current
2967     ActiveConnection.Modules.*"""
2968     # Expose all active module to the current servermanager module
2969     if ActiveConnection:
2970        for m in [mName for mName in dir(ActiveConnection.Modules) if mName[0] != '_' ]:
2971           exec "global %s;%s = ActiveConnection.Modules.%s" % (m,m,m)
2972
2973 # Definitions for working in SALOME GUI mode
2974 #aParams = myParavis.GetConnectionParameters()
2975 #ActiveConnection = Connect()
2976 ##Connection(aParams[0])
2977 #ActiveConnection.SetHost(aParams[1], aParams[2], aParams[3], aParams[4], aParams[5])
2978 #ToggleProgressPrinting()
2979 #fromGUI = True
2980
2981 InitFromGUI()
2982
2983 if hasattr(sys, "ps1"):
2984     # session is interactive.
2985     print vtkSMProxyManager.GetParaViewSourceVersion();
2986
2987 def GetConnectionFromId(id):
2988    for connection in MultiServerConnections:
2989       if connection.ID == id:
2990          return connection
2991    return None
2992
2993 def GetConnectionFromSession(session):
2994    for connection in MultiServerConnections:
2995       if connection.Session == session:
2996          return connection
2997    return None
2998
2999 def GetConnectionAt(index):
3000    return MultiServerConnections[index]
3001
3002 def GetNumberOfConnections():
3003    return len(MultiServerConnections)