/[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

trunk/pyvisi/py_src/datacollector.py revision 1147 by ksteube, Wed May 16 06:39:11 2007 UTC temp/pyvisi/py_src/datacollector.py revision 1387 by trankine, Fri Jan 11 07:45:26 2008 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 an error is
91                # raised.
92              if not(os.access(file_name, os.F_OK)):              if not(os.access(file_name, os.F_OK)):
93                  raise IOError("ERROR: '%s' file does NOT exists." % file_name)                        raise IOError("\nERROR: '%s' file does NOT exists.\n" % \
94                            file_name)
95    
96              self.__vtk_xml_reader.SetFileName(file_name)              self.__vtk_xml_reader.SetFileName(file_name)
97              # Update must be called after SetFileName to make the reader              # Update must be called after SetFileName to make the reader
98              # up-to-date. Otherwise, some output values may be incorrect.              # up-to-date. Otherwise, some output values may be incorrect.
99              self.__vtk_xml_reader.Update()              self.__vtk_xml_reader.Update()
             self.__output = self.__vtk_xml_reader.GetOutput()  
100              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  
   
101          else:          else:
102              raise ValueError("Source type %s does not support \              raise ValueError("Source type %s does not support \
103              'setFileName'\n" % self.__source)              'setFileName'\n" % self.__source)
# Line 103  class DataCollector: Line 108  class DataCollector:
108          that the data will be given in the appropriate format.          that the data will be given in the appropriate format.
109          """          """
110    
111            self.__modified = True
112            self.__count += 1
113    
114          if self.__source == Source.ESCRIPT:          if self.__source == Source.ESCRIPT:
115              esys.escript.saveVTK(self.__tmp_file,**args)              esys.escript.saveVTK(self.__tmp_file,**args)
116              self.__vtk_xml_reader.SetFileName(self.__tmp_file)              self.__vtk_xml_reader.SetFileName(self.__tmp_file)
117    
118              # Modified must be called for setData but NOT for              # Modified must be called for setData but NOT for
119              # setFileName. If Modified is not called, only the first file              # setFileName. If Modified is not called, only the first file
120              # will always be displayed. The reason Modified is used is              # will always be displayed. The reason Modified is used is
121              # because the same temporary file name is always used              # because the same temporary file name is always used
122              # (previous file is overwritten). Modified MUST NOT be used in              # (previous file is overwritten). Modified MUST NOT be used in
123              # setFileName, it can cause incorrect output such as map.              # setFileName, as it can cause incorrect output such as map.
124              self.__vtk_xml_reader.Modified()              self.__vtk_xml_reader.Modified()
125    
126              # Update must be called after Modified. If Update is called before              # Update must be called after Modified. If Update is called before
127              # Modified, then the first/second image(s) may not be updated              # Modified, then the first/second image(s) may not be updated
128              # correctly.              # correctly.
129              self.__vtk_xml_reader.Update()              self.__vtk_xml_reader.Update()
             self.__output = self.__vtk_xml_reader.GetOutput()  
130              self.__get_attribute_lists()              self.__get_attribute_lists()
   
             if(self.__count > 0):  
                 self._updateRange()  
   
             self.__count+=1  
131          else:          else:
132              raise ValueError("Source type %s does not support 'setData'\n" \              raise ValueError("Source type %s does not support 'setData'\n" \
133                      % self.__source)                      % self.__source)
134    
135        # This method is used to delay the execution of setting the active scalar
136        # until 'setFileName' or 'setData' have been executed.
137      def setActiveScalar(self, scalar):      def setActiveScalar(self, scalar):
138          """          """
139          Specify the scalar field to load.          Specify the scalar field to load.
# Line 135  class DataCollector: Line 141  class DataCollector:
141          @type scalar: String          @type scalar: String
142          @param scalar: Scalar field to load from the file.          @param scalar: Scalar field to load from the file.
143          """          """
144            
145            self.__set_scalar = True
146            self.__active_scalar = scalar
147    
148        def _setActiveScalar(self):
149            """
150            Load the specified scalar field.
151            """
152    
153          # Check whether the specified scalar is available in either point          # Check whether the specified scalar is available in either point
154          # or cell data. If not available, program exits.          # or cell data. If not available, an error is raised.
155    
156          # NOTE: This check is similar to the check used in _getScalarRange          # NOTE: This check is similar to the check used in _getScalarRange
157          # but this is used only when a scalar attribute has been specified.          # but this is used only when a scalar attribute has been specified.
158          if scalar in self.__point_attribute['scalars']:          if self.__active_scalar in self.__point_attribute['scalars']:
159              self._getOutput().GetPointData().SetActiveScalars(scalar)              self._getDataCollectorOutput().GetPointData().SetActiveScalars(
160          elif scalar in self.__cell_attribute['scalars']:                      self.__active_scalar)
161              self._getOutput().GetCellData().SetActiveScalars(scalar)          elif self.__active_scalar in self.__cell_attribute['scalars']:
162                self._getDataCollectorOutput().GetCellData().SetActiveScalars(
163                        self.__active_scalar)
164          else:          else:
165              raise IOError("ERROR: No scalar called '%s' is available." % scalar)              raise IOError("ERROR: No scalar called '%s' is available." % \
166                        self.__active_scalar)
167    
168        # This method is used to delay the execution of setting the active vector
169        # until 'setFileName' or 'setData' have been executed.
170      def setActiveVector(self, vector):      def setActiveVector(self, vector):
171          """          """
172          Specify the vector field to load.          Specify the vector field to load.
# Line 155  class DataCollector: Line 174  class DataCollector:
174          @type vector: String          @type vector: String
175          @param vector: Vector field to load from the file.          @param vector: Vector field to load from the file.
176          """          """
177            
178            self.__set_vector = True
179            self.__active_vector = vector
180    
181        def _setActiveVector(self):
182            """
183            Load the specified vector field.
184            """
185    
186          # Check whether the specified vector is available in either point          # Check whether the specified vector is available in either point
187          # or cell data. If not available, program exits.          # or cell data. If not available, error is raised.
188    
189          # NOTE: This check is similar to the check used in _getVectorRange          # NOTE: This check is similar to the check used in _getVectorRange
190          # but this is used only when a vector attribute has been specified.          # but this is used only when a vector attribute has been specified.
191          if vector in self.__point_attribute['vectors']:          if self.__active_vector in self.__point_attribute['vectors']:
192              self._getOutput().GetPointData().SetActiveVectors(vector)              self._getDataCollectorOutput().GetPointData().SetActiveVectors(
193          elif vector in self.__cell_attribute['vectors']:                      self.__active_vector)
194              self._getOutput().GetCellData().SetActiveVectors(vector)          elif self.__active_vector in self.__cell_attribute['vectors']:
195                self._getDataCollectorOutput().GetCellData().SetActiveVectors(
196                        self.__active_vector)
197          else:          else:
198              raise IOError("ERROR: No vector called '%s' is available." % vector)              raise IOError("ERROR: No vector called '%s' is available." % \
199                                    self.__active_vector)
200    
201        # This method is used to delay the execution of setting the active tensor
202        # until 'setFileName' or 'setData' have been executed.
203      def setActiveTensor(self, tensor):      def setActiveTensor(self, tensor):
204          """          """
205          Specify the tensor field to load.          Specify the tensor field to load.
# Line 176  class DataCollector: Line 208  class DataCollector:
208          @param tensor: Tensor field to load from the file.          @param tensor: Tensor field to load from the file.
209          """          """
210    
211            self.__set_tensor = True
212            self.__active_tensor = tensor
213    
214        def _setActiveTensor(self):
215            """
216            Load the the specified tensor field.
217            """
218    
219          # Check whether the specified tensor is available in either point          # Check whether the specified tensor is available in either point
220          # or cell data. If not available, program exits.          # or cell data. If not available, error is raised.
221    
222          # NOTE: This check is similar to the check used in _getTensorRange          # NOTE: This check is similar to the check used in _getTensorRange
223          # but this is used only when a tensor attribute has been specified.          # but this is used only when a tensor attribute has been specified.
224          if tensor in self.__point_attribute['tensors']:          if self.__active_tensor in self.__point_attribute['tensors']:
225              self._getOutput().GetPointData().SetActiveTensors(tensor)              self._getDataCollectorOutput().GetPointData().SetActiveTensors(
226          elif tensor in self.__cell_attribute['tensors']:                      self.__active_tensor)
227              self._getOutput().GetCellData().SetActiveTensors(tensor)          elif self.__active_tensor in self.__cell_attribute['tensors']:
228                self._getDataCollectorOutput().GetCellData().SetActiveTensors(
229                        self.__active_tensor)
230          else:          else:
231              raise IOError("ERROR: No tensor called '%s' is available." % tensor)              raise IOError("ERROR: No tensor called '%s' is available." % \
232                        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())  
233    
234      def __get_array_type(self, arr):      def __get_array_type(self, arr):
235          """          """
# Line 291  class DataCollector: Line 281  class DataCollector:
281    
282          # Get all the available point data attributes into a list.          # Get all the available point data attributes into a list.
283          self.__point_attribute = \          self.__point_attribute = \
284                  self.__get_attribute_list(self._getOutput().GetPointData())                  self.__get_attribute_list(
285          # Get all the available cell data attribute into another list.                    self._getDataCollectorOutput().GetPointData())
286    
287            # Get all the available cell data attributes into another list.
288          self.__cell_attribute = \          self.__cell_attribute = \
289                  self.__get_attribute_list(self._getOutput().GetCellData())                  self.__get_attribute_list(
290                    self._getDataCollectorOutput().GetCellData())
291    
292      def _getScalarRange(self):      def _getScalarRange(self):
293          """          """
# Line 305  class DataCollector: Line 298  class DataCollector:
298          """          """
299    
300          # Check whether any scalar is available in either point or cell data.          # Check whether any scalar is available in either point or cell data.
301          # If not available, program exits.          # If not available, an error is raised.
302    
303          # NOTE: This check is similar to the check used in _setActiveScalar          # NOTE: This check is similar to the check used in _setActiveScalar
304          # but this is used only when no scalar attribute has been specified.          # but this is used only when no scalar attribute has been specified.
305          if(len(self.__point_attribute['scalars']) != 0):          if(len(self.__point_attribute['scalars']) != 0):
306              return self._getOutput().GetPointData().GetScalars().GetRange(-1)              return self._getDataCollectorOutput().GetPointData().\
307                        GetScalars().GetRange(-1)
308          elif(len(self.__cell_attribute['scalars']) != 0):          elif(len(self.__cell_attribute['scalars']) != 0):
309              return self._getOutput().GetCellData().GetScalars().GetRange(-1)              return self._getDataCollectorOutput().GetCellData().\
310                        GetScalars().GetRange(-1)
311          else:          else:
312              raise IOError("ERROR: No scalar is available.")              raise IOError("\nERROR: No scalar is available.\n")
313    
314      def _getVectorRange(self):      def _getVectorRange(self):
315          """          """
# Line 325  class DataCollector: Line 320  class DataCollector:
320          """          """
321                    
322          # Check whether any vector is available in either point or cell data.          # Check whether any vector is available in either point or cell data.
323          # If not available, program exits.          # If not available, an error is raised.
324    
325          # NOTE: This check is similar to the check used in _setActiveVector          # NOTE: This check is similar to the check used in _setActiveVector
326          # but this is used only when no vector attribute has been specified.          # but this is used only when no vector attribute has been specified.
# Line 337  class DataCollector: Line 332  class DataCollector:
332          # to accommodate for the incorrect cases.          # to accommodate for the incorrect cases.
333          if(len(self.__point_attribute['vectors']) != 0):          if(len(self.__point_attribute['vectors']) != 0):
334              vector_range = \              vector_range = \
335                      self._getOutput().GetPointData().GetVectors().GetRange(-1)                      self._getDataCollectorOutput().GetPointData().\
336                        GetVectors().GetRange(-1)
337              return (0.0, vector_range[1])              return (0.0, vector_range[1])
338          elif(len(self.__cell_attribute['vectors']) != 0):          elif(len(self.__cell_attribute['vectors']) != 0):
339              vector_range = \              vector_range = \
340                      self._getOutput().GetCellData().GetVectors().GetRange(-1)                      self._getDataCollectorOutput().GetCellData().\
341                        GetVectors().GetRange(-1)
342              return (0.0, vector_range[1])              return (0.0, vector_range[1])
343          else:          else:
344              print "\nERROR: No vector is available.\n"                raise IOError("\nERROR: No vector is available.\n")
             sys.exit(0)  
345    
346      def _getTensorRange(self):      def _getTensorRange(self):
347          """          """
# Line 356  class DataCollector: Line 352  class DataCollector:
352          """          """
353    
354          # Check whether any tensor is available in either point or cell data.          # Check whether any tensor is available in either point or cell data.
355          # If not available, program exits.          # If not available, an error is raised.
356    
357          # NOTE: This check is similar to the check used in _setActiveTensor          # NOTE: This check is similar to the check used in _setActiveTensor
358          # but this is used only when no tensor attribute has been specified.          # but this is used only when no tensor attribute has been specified.
359          if(len(self.__point_attribute['tensors']) != 0):          if(len(self.__point_attribute['tensors']) != 0):
360              return self._getOutput().GetPointData().GetTensors().GetRange(-1)              return self._getDataCollectorOutput().GetPointData().\
361                        GetTensors().GetRange(-1)
362          elif(len(self.__cell_attribute['tensors']) != 0):          elif(len(self.__cell_attribute['tensors']) != 0):
363              return self._getOutput().GetCellData().GetTensors().GetRange(-1)              return self._getDataCollectorOutput().GetCellData().\
364                        GetTensors().GetRange(-1)
365          else:          else:
366              print "\nERROR: No tensor is available.\n"                raise IOError("\nERROR: No tensor is available.\n")
             sys.exit(1)  
367    
368      def _getOutput(self):      def _getDataCollectorOutput(self):
369          """          """
370          Return the output of the data collector.          Return the output of the data collector.
371    
372          @rtype: vtkUnstructuredGrid          @rtype: vtkUnstructuredGrid
373          @return: Unstructured grid          @return: Unstructured grid
374          """          """
375            return self.__vtk_xml_reader.GetOutput()
376    
377          return self.__output      def _isModified(self):
378            """
379            Return whether the DataCollector has been modified.
380    
381            @rtype: Boolean
382            @return: True or False
383            """
384    
385            if(self.__modified == True):
386                # 'self.__modified' is set to False only if the 'setFileName' or
387                # 'setData' method have been called once. This is to prevent
388                # the scalar range and active field (i.e. scalar, vector or tensor)
389                # from being updated as no changes has taken place (for performance
390                # reasons). However if the 'setFileName' or 'setData' method is
391                # called more than once, then 'self.__modified' remains True.
392                if(self.__count == 1):
393                    self.__modified = False
394                return True
395            else:
396                return False
397        
398        def _isScalarSet(self):
399            """
400            Return whether a specific scalar field has been specified.
401    
402            @rtype: Boolean
403            @return: True or False
404            """
405    
406            return self.__set_scalar
407    
408        def _isVectorSet(self):
409            """
410            Return whether a specific vector field has been specified.
411    
412            @rtype: Boolean
413            @return: True or False
414            """
415    
416            return self.__set_vector
417    
418        def _isTensorSet(self):
419            """
420            Return whether a specific tensor field has been specified.
421    
422            @rtype: Boolean
423            @return: True or False
424            """
425    
426            return self.__set_tensor
427    
428        def _getCenter(self):
429            """
430            Return the center of the rendered object.
431    
432            @rtype: Three column tuple containing numbers
433            @return: Center of the rendered object
434            """
435    
436            return self._getDataCollectorOutput().GetCenter()
437            

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

  ViewVC Help
Powered by ViewVC 1.1.26