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