/[escript]/trunk/pyvisi/py_src/datacollector.py
ViewVC logotype

Diff of /trunk/pyvisi/py_src/datacollector.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1147 by ksteube, Wed May 16 06:39:11 2007 UTC revision 1197 by jongui, Mon Jun 18 02:08:34 2007 UTC
# Line 1  Line 1 
1  """  """
2  @author: John NGUI  @var __author__: name of author
3    @var __copyright__: copyrights
4    @var __license__: licence agreement
5    @var __url__: url entry point on documentation
6    @var __version__: version
7    @var __date__: date of the version
8  """  """
9    
10    __author__="John Ngui, john.ngui@uq.edu.au"
11    __copyright__="""  Copyright (c) 2006 by ACcESS MNRF
12                        http://www.access.edu.au
13                    Primary Business: Queensland, Australia"""
14    __license__="""Licensed under the Open Software License version 3.0
15                 http://www.opensource.org/licenses/osl-3.0.php"""
16    __url__="http://www.iservo.edu.au/esys"
17    __version__="$Revision$"
18    __date__="$Date$"
19    
20    
21  import vtk  import vtk
22  import tempfile, os, sys  import tempfile, os, sys
23  from constant import Source, VizType, ColorMode  from constant import Source, ColorMode
24  try:  try:
25      import esys.escript      import esys.escript
26  except ImportError:  except ImportError:
27      print "Warning: importing esys.escript failed."      print "Warning: importing esys.escript failed."
28    
 try:  
      PYVISI_WORKDIR=os.environ['PYVISI_WORKDIR']  
 except KeyError:  
      PYVISI_WORKDIR='.'  
 try:  
      PYVISI_TEST_DATA_ROOT=os.environ['PYVISI_TEST_DATA_ROOT']  
 except KeyError:  
      PYVISI_TEST_DATA_ROOT='.'  
       
29  class DataCollector:  class DataCollector:
30      """      """
31      Class that defines a data collector. A data collector is used to read      Class that defines a data collector. A data collector is used to read
32      data from an XML file or from an escript object directly.      data from a XML file or from an escript object directly. Writing XML
33        files are expensive, but this approach has the advantage given that the
34        results can be analyzed easily after the simulation has completed.  
35    
36      @attention: A DataCollector instance can only be used to specify one      @attention: A DataCollector instance can only be used to specify one
37      scalar, vector and tensor attribute from a source at any one time. If a      scalar, vector and tensor attribute from a source at any one time. If a
38      second scalar, vector or tensor attribute needs to be specified from the      second scalar, vector or tensor attribute needs to be specified from the
39      same source, a second DataCollector instance must be created.      same source, a second DataCollector instance must be created.
   
     @attention: When a series of XML files or escript objects are read  
     (using 'setFileName' or 'setData' in a for-loop), the 'setActiveScalar' /  
     'setActiveVector' / 'setActiveTensor' have to be called for each new file  
     (provided a specific field needs to be loaded) as all active fields  
     specified from the previous file goes back to the default once a new file  
     is read.  
40      """      """
41    
42      def __init__(self, source = Source.XML):      def __init__(self, source = Source.XML):
# Line 46  class DataCollector: Line 48  class DataCollector:
48          """          """
49    
50          self.__source = source          self.__source = source
51          self.__count = 0 # Keeps track of the number of files/sources read.          # Keeps track on whether DataCollector have been modified.
52            self.__modified = True
53            # Keeps track of the number of times the 'setFileName' or 'setData'
54            # method have been executed.
55            self.__count = 0
56            # Keeps track on whether any specific scalar, vector or tensor
57            # field have been specified.
58            self.__set_scalar = False
59            self.__set_vector= False
60            self.__set_tensor= False
61    
62          if(source == Source.XML): # Source is an XML file.          if(source == Source.XML): # Source is an XML file.
63              self.__vtk_xml_reader = vtk.vtkXMLUnstructuredGridReader()              self.__vtk_xml_reader = vtk.vtkXMLUnstructuredGridReader()
# Line 72  class DataCollector: Line 83  class DataCollector:
83          @param file_name: Name of the file to read          @param file_name: Name of the file to read
84          """          """
85    
86            self.__modified = True
87            self.__count += 1
88    
89          if(self.__source == Source.XML):          if(self.__source == Source.XML):
90              # Check whether the specified file exists, otherwise exit.              # Check whether the specified file exists, otherwise exit.
91              if not(os.access(file_name, os.F_OK)):              if not(os.access(file_name, os.F_OK)):
92                  raise IOError("ERROR: '%s' file does NOT exists." % file_name)                        raise IOError("\nERROR: '%s' file does NOT exists.\n" % \
93                            file_name)
94    
95              self.__vtk_xml_reader.SetFileName(file_name)              self.__vtk_xml_reader.SetFileName(file_name)
96              # Update must be called after SetFileName to make the reader              # Update must be called after SetFileName to make the reader
97              # up-to-date. Otherwise, some output values may be incorrect.              # up-to-date. Otherwise, some output values may be incorrect.
98              self.__vtk_xml_reader.Update()              self.__vtk_xml_reader.Update()
             self.__output = self.__vtk_xml_reader.GetOutput()  
99              self.__get_attribute_lists()              self.__get_attribute_lists()
               
             # Count has to be larger than zero because when setFileName is  
             # called for the first time, the data set mapper has not yet been  
             # instantiated. Therefore, the range of the mapper can only be  
             # updated after the first file/source has been read.  
             if(self.__count > 0):  
                 self._updateRange()  
   
             self.__count+=1  
   
100          else:          else:
101              raise ValueError("Source type %s does not support \              raise ValueError("Source type %s does not support \
102              'setFileName'\n" % self.__source)              'setFileName'\n" % self.__source)
# Line 103  class DataCollector: Line 107  class DataCollector:
107          that the data will be given in the appropriate format.          that the data will be given in the appropriate format.
108          """          """
109    
110            self.__modified = True
111            self.__count += 1
112    
113          if self.__source == Source.ESCRIPT:          if self.__source == Source.ESCRIPT:
114              esys.escript.saveVTK(self.__tmp_file,**args)              esys.escript.saveVTK(self.__tmp_file,**args)
115              self.__vtk_xml_reader.SetFileName(self.__tmp_file)              self.__vtk_xml_reader.SetFileName(self.__tmp_file)
116    
117              # Modified must be called for setData but NOT for              # Modified must be called for setData but NOT for
118              # setFileName. If Modified is not called, only the first file              # setFileName. If Modified is not called, only the first file
119              # will always be displayed. The reason Modified is used is              # will always be displayed. The reason Modified is used is
# Line 113  class DataCollector: Line 121  class DataCollector:
121              # (previous file is overwritten). Modified MUST NOT be used in              # (previous file is overwritten). Modified MUST NOT be used in
122              # setFileName, it can cause incorrect output such as map.              # setFileName, it can cause incorrect output such as map.
123              self.__vtk_xml_reader.Modified()              self.__vtk_xml_reader.Modified()
124    
125              # Update must be called after Modified. If Update is called before              # Update must be called after Modified. If Update is called before
126              # Modified, then the first/second image(s) may not be updated              # Modified, then the first/second image(s) may not be updated
127              # correctly.              # correctly.
128              self.__vtk_xml_reader.Update()              self.__vtk_xml_reader.Update()
             self.__output = self.__vtk_xml_reader.GetOutput()  
129              self.__get_attribute_lists()              self.__get_attribute_lists()
   
             if(self.__count > 0):  
                 self._updateRange()  
   
             self.__count+=1  
130          else:          else:
131              raise ValueError("Source type %s does not support 'setData'\n" \              raise ValueError("Source type %s does not support 'setData'\n" \
132                      % self.__source)                      % self.__source)
133    
134        # This method is used to delay the execution of setting the active scalar
135        # until 'setFileName' or 'setData' have been executed.
136      def setActiveScalar(self, scalar):      def setActiveScalar(self, scalar):
137          """          """
138          Specify the scalar field to load.          Specify the scalar field to load.
# Line 135  class DataCollector: Line 140  class DataCollector:
140          @type scalar: String          @type scalar: String
141          @param scalar: Scalar field to load from the file.          @param scalar: Scalar field to load from the file.
142          """          """
143            
144            self.__set_scalar = True
145            self.__active_scalar = scalar
146    
147        def _setActiveScalar(self):
148            """
149            Load the specified scalar field.
150            """
151    
152          # Check whether the specified scalar is available in either point          # Check whether the specified scalar is available in either point
153          # or cell data. If not available, program exits.          # or cell data. If not available, error is raised.
154    
155          # NOTE: This check is similar to the check used in _getScalarRange          # NOTE: This check is similar to the check used in _getScalarRange
156          # but this is used only when a scalar attribute has been specified.          # but this is used only when a scalar attribute has been specified.
157          if scalar in self.__point_attribute['scalars']:          if self.__active_scalar in self.__point_attribute['scalars']:
158              self._getOutput().GetPointData().SetActiveScalars(scalar)              self._getDataCollectorOutput().GetPointData().SetActiveScalars(
159          elif scalar in self.__cell_attribute['scalars']:                      self.__active_scalar)
160              self._getOutput().GetCellData().SetActiveScalars(scalar)          elif self.__active_scalar in self.__cell_attribute['scalars']:
161                self._getDataCollectorOutput().GetCellData().SetActiveScalars(
162                        self.__active_scalar)
163          else:          else:
164              raise IOError("ERROR: No scalar called '%s' is available." % scalar)              raise IOError("ERROR: No scalar called '%s' is available." % \
165                        self.__active_scalar)
166    
167        # This method is used to delay the execution of setting the active vector
168        # until 'setFileName' or 'setData' have been executed.
169      def setActiveVector(self, vector):      def setActiveVector(self, vector):
170          """          """
171          Specify the vector field to load.          Specify the vector field to load.
# Line 155  class DataCollector: Line 173  class DataCollector:
173          @type vector: String          @type vector: String
174          @param vector: Vector field to load from the file.          @param vector: Vector field to load from the file.
175          """          """
176            
177            self.__set_vector = True
178            self.__active_vector = vector
179    
180        def _setActiveVector(self):
181            """
182            Load the specified vector field.
183            """
184    
185          # Check whether the specified vector is available in either point          # Check whether the specified vector is available in either point
186          # or cell data. If not available, program exits.          # or cell data. If not available, error is raised.
187    
188          # NOTE: This check is similar to the check used in _getVectorRange          # NOTE: This check is similar to the check used in _getVectorRange
189          # but this is used only when a vector attribute has been specified.          # but this is used only when a vector attribute has been specified.
190          if vector in self.__point_attribute['vectors']:          if self.__active_vector in self.__point_attribute['vectors']:
191              self._getOutput().GetPointData().SetActiveVectors(vector)              self._getDataCollectorOutput().GetPointData().SetActiveVectors(
192          elif vector in self.__cell_attribute['vectors']:                      self.__active_vector)
193              self._getOutput().GetCellData().SetActiveVectors(vector)          elif self.__active_vector in self.__cell_attribute['vectors']:
194                self._getDataCollectorOutput().GetCellData().SetActiveVectors(
195                        self.__active_vector)
196          else:          else:
197              raise IOError("ERROR: No vector called '%s' is available." % vector)              raise IOError("ERROR: No vector called '%s' is available." % \
198                                    self.__active_vector)
199    
200        # This method is used to delay the execution of setting the active tensor
201        # until 'setFileName' or 'setData' have been executed.
202      def setActiveTensor(self, tensor):      def setActiveTensor(self, tensor):
203          """          """
204          Specify the tensor field to load.          Specify the tensor field to load.
# Line 176  class DataCollector: Line 207  class DataCollector:
207          @param tensor: Tensor field to load from the file.          @param tensor: Tensor field to load from the file.
208          """          """
209    
210            self.__set_tensor = True
211            self.__active_tensor = tensor
212    
213        def _setActiveTensor(self):
214            """
215            Load the the specified tensor field.
216            """
217    
218          # Check whether the specified tensor is available in either point          # Check whether the specified tensor is available in either point
219          # or cell data. If not available, program exits.          # or cell data. If not available, error is raised.
220    
221          # NOTE: This check is similar to the check used in _getTensorRange          # NOTE: This check is similar to the check used in _getTensorRange
222          # but this is used only when a tensor attribute has been specified.          # but this is used only when a tensor attribute has been specified.
223          if tensor in self.__point_attribute['tensors']:          if self.__active_tensor in self.__point_attribute['tensors']:
224              self._getOutput().GetPointData().SetActiveTensors(tensor)              self._getDataCollectorOutput().GetPointData().SetActiveTensors(
225          elif tensor in self.__cell_attribute['tensors']:                      self.__active_tensor)
226              self._getOutput().GetCellData().SetActiveTensors(tensor)          elif self.__active_tensor in self.__cell_attribute['tensors']:
227                self._getDataCollectorOutput().GetCellData().SetActiveTensors(
228                        self.__active_tensor)
229          else:          else:
230              raise IOError("ERROR: No tensor called '%s' is available." % tensor)              raise IOError("ERROR: No tensor called '%s' is available." % \
231                        self.__active_tensor)
     # 'object' is set to 'None' because some types of visualization have  
     # two ranges that needs to be updated while others only have one.  
     def _paramForUpdatingMultipleSources(self, viz_type, color_mode, mapper,  
             object = None):  
         """  
         Parameters required to update the necessary data when two or more  
         files or escript objects are read.  
   
         @type viz_type: : L{VizType <constant.VizType>} constant  
         @param viz_type: Type if visualization  
         @type color_mode: L{ColorMode <constant.ColorMode>} constant  
         @param color_mode: Type of color mode  
         @type mapper: vtkDataSetMapper  
         @param mapper: Mapped data  
         @type object: vtkPolyDataAlgorithm (i.e. vtkContourFilter, vtkGlyph3D, \  
                 etc)  
         @param object: Polygonal data  
         """  
   
         self.__viz_type = viz_type  
         self.__color_mode = color_mode  
         self.__mapper = mapper  
         self.__object = object  
   
     def _updateRange(self):  
         """  
         Update the necessary range(s) when two or more files or escript objects  
         are read.  
         """  
   
         if self.__viz_type == VizType.MAP or \  
                 self.__viz_type == VizType.ELLIPSOID or \  
                 self.__viz_type == VizType.CARPET:  
             self.__mapper.SetScalarRange(self._getScalarRange())  
         elif self.__viz_type == VizType.VELOCITY:  
             if self.__color_mode == ColorMode.VECTOR:  
                 self.__object.SetRange(self._getVectorRange())  
                 self.__mapper.SetScalarRange(self._getVectorRange())  
             elif self.__color_mode == ColorMode.SCALAR:  
                 self.__object.SetRange(self._getScalarRange())  
                 self.__mapper.SetScalarRange(self._getScalarRange())  
         elif self.__viz_type == VizType.CONTOUR:  
             self.__object.GenerateValues(  
                     self.__object.GetNumberOfContours(),  
                     self._getScalarRange()[0],  
                     self._getScalarRange()[1])  
             self.__mapper.SetScalarRange(self._getScalarRange())  
         elif self.__viz_type == VizType.STREAMLINE:  
             if self.__color_mode == ColorMode.VECTOR:  
                 self.__mapper.SetScalarRange(self._getVectorRange())  
             elif self.__color_mode == ColorMode.SCALAR:  
                 self.__mapper.SetScalarRange(self._getScalarRange())  
232    
233      def __get_array_type(self, arr):      def __get_array_type(self, arr):
234          """          """
# Line 291  class DataCollector: Line 280  class DataCollector:
280    
281          # Get all the available point data attributes into a list.          # Get all the available point data attributes into a list.
282          self.__point_attribute = \          self.__point_attribute = \
283                  self.__get_attribute_list(self._getOutput().GetPointData())                  self.__get_attribute_list(
284                    self._getDataCollectorOutput().GetPointData())
285    
286          # Get all the available cell data attribute into another list.            # Get all the available cell data attribute into another list.  
287          self.__cell_attribute = \          self.__cell_attribute = \
288                  self.__get_attribute_list(self._getOutput().GetCellData())                  self.__get_attribute_list(
289                    self._getDataCollectorOutput().GetCellData())
290    
291      def _getScalarRange(self):      def _getScalarRange(self):
292          """          """
# Line 310  class DataCollector: Line 302  class DataCollector:
302          # NOTE: This check is similar to the check used in _setActiveScalar          # NOTE: This check is similar to the check used in _setActiveScalar
303          # but this is used only when no scalar attribute has been specified.          # but this is used only when no scalar attribute has been specified.
304          if(len(self.__point_attribute['scalars']) != 0):          if(len(self.__point_attribute['scalars']) != 0):
305              return self._getOutput().GetPointData().GetScalars().GetRange(-1)              return self._getDataCollectorOutput().GetPointData().\
306                        GetScalars().GetRange(-1)
307          elif(len(self.__cell_attribute['scalars']) != 0):          elif(len(self.__cell_attribute['scalars']) != 0):
308              return self._getOutput().GetCellData().GetScalars().GetRange(-1)              return self._getDataCollectorOutput().GetCellData().\
309                        GetScalars().GetRange(-1)
310          else:          else:
311              raise IOError("ERROR: No scalar is available.")              raise IOError("\nERROR: No scalar is available.\n")
312    
313      def _getVectorRange(self):      def _getVectorRange(self):
314          """          """
# Line 337  class DataCollector: Line 331  class DataCollector:
331          # to accommodate for the incorrect cases.          # to accommodate for the incorrect cases.
332          if(len(self.__point_attribute['vectors']) != 0):          if(len(self.__point_attribute['vectors']) != 0):
333              vector_range = \              vector_range = \
334                      self._getOutput().GetPointData().GetVectors().GetRange(-1)                      self._getDataCollectorOutput().GetPointData().\
335                        GetVectors().GetRange(-1)
336              return (0.0, vector_range[1])              return (0.0, vector_range[1])
337          elif(len(self.__cell_attribute['vectors']) != 0):          elif(len(self.__cell_attribute['vectors']) != 0):
338              vector_range = \              vector_range = \
339                      self._getOutput().GetCellData().GetVectors().GetRange(-1)                      self._getDataCollectorOutput().GetCellData().\
340                        GetVectors().GetRange(-1)
341              return (0.0, vector_range[1])              return (0.0, vector_range[1])
342          else:          else:
343              print "\nERROR: No vector is available.\n"                raise IOError("\nERROR: No vector is available.\n")
             sys.exit(0)  
344    
345      def _getTensorRange(self):      def _getTensorRange(self):
346          """          """
# Line 361  class DataCollector: Line 356  class DataCollector:
356          # NOTE: This check is similar to the check used in _setActiveTensor          # NOTE: This check is similar to the check used in _setActiveTensor
357          # but this is used only when no tensor attribute has been specified.          # but this is used only when no tensor attribute has been specified.
358          if(len(self.__point_attribute['tensors']) != 0):          if(len(self.__point_attribute['tensors']) != 0):
359              return self._getOutput().GetPointData().GetTensors().GetRange(-1)              return self._getDataCollectorOutput().GetPointData().\
360                        GetTensors().GetRange(-1)
361          elif(len(self.__cell_attribute['tensors']) != 0):          elif(len(self.__cell_attribute['tensors']) != 0):
362              return self._getOutput().GetCellData().GetTensors().GetRange(-1)              return self._getDataCollectorOutput().GetCellData().\
363                        GetTensors().GetRange(-1)
364          else:          else:
365              print "\nERROR: No tensor is available.\n"                raise IOError("\nERROR: No tensor is available.\n")
             sys.exit(1)  
366    
367      def _getOutput(self):      def _getDataCollectorOutput(self):
368          """          """
369          Return the output of the data collector.          Return the output of the data collector.
370    
371          @rtype: vtkUnstructuredGrid          @rtype: vtkUnstructuredGrid
372          @return: Unstructured grid          @return: Unstructured grid
373          """          """
374            return self.__vtk_xml_reader.GetOutput()
375    
376          return self.__output      def _isModified(self):
377            """
378            Return whether the DataCollector has been modified.
379    
380            @rtype: Boolean
381            @return: True or False
382            """
383    
384            if(self.__modified == True):
385                # 'self.__modified' is set to False only if the 'setFileName' or
386                # 'setData' method have been called once. This is to prevent
387                # the scalar range and active field (i.e. scalar, vector or tensor)
388                # from being updated as no changes has taken place (for performance
389                # reasons). However if the 'setFileName' or 'setData' method is
390                # called more than once, then 'self.__modified' remains True.
391                if(self.__count == 1):
392                    self.__modified = False
393                return True
394            else:
395                return False
396        
397        def _isScalarSet(self):
398            """
399            Return whether a specific scalar field has been specified.
400    
401            @rtype: Boolean
402            @return: True or False
403            """
404    
405            return self.__set_scalar
406    
407        def _isVectorSet(self):
408            """
409            Return whether a specific vector field has been specified.
410    
411            @rtype: Boolean
412            @return: True or False
413            """
414    
415            return self.__set_vector
416    
417        def _isTensorSet(self):
418            """
419            Return whether a specific tensor field has been specified.
420    
421            @rtype: Boolean
422            @return: True or False
423            """
424    
425            return self.__set_tensor
426    
427        def _getCenter(self):
428            """
429            Return the center of the rendered object.
430    
431            @rtype: Three column tuple containing numbers
432            @return: Center of the rendered object
433            """
434    
435            return self._getDataCollectorOutput().GetCenter()
436            

Legend:
Removed from v.1147  
changed lines
  Added in v.1197

  ViewVC Help
Powered by ViewVC 1.1.26