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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1387 - (hide annotations)
Fri Jan 11 07:45:26 2008 UTC (11 years, 7 months ago) by trankine
Original Path: temp/pyvisi/py_src/datacollector.py
File MIME type: text/x-python
File size: 13779 byte(s)
Restore the trunk that existed before the windows changes were committed to the (now moved to branches) old trunk.
1 ksteube 1147 """
2 jongui 1197 @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 ksteube 1147 """
9    
10 jongui 1197 __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 ksteube 1147 import vtk
22     import tempfile, os, sys
23 jongui 1148 from constant import Source, ColorMode
24 ksteube 1147 try:
25     import esys.escript
26     except ImportError:
27     print "Warning: importing esys.escript failed."
28    
29     class DataCollector:
30     """
31     Class that defines a data collector. A data collector is used to read
32 jongui 1154 data from a XML file or from an escript object directly. Writing XML
33 jongui 1148 files are expensive, but this approach has the advantage given that the
34     results can be analyzed easily after the simulation has completed.
35 ksteube 1147
36     @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
38     second scalar, vector or tensor attribute needs to be specified from the
39     same source, a second DataCollector instance must be created.
40     """
41    
42     def __init__(self, source = Source.XML):
43     """
44     Initialise the data collector.
45    
46     @type source: L{Source <constant.Source>} constant
47     @param source: Source type
48     """
49    
50     self.__source = source
51 jongui 1148 # Keeps track on whether DataCollector have been modified.
52     self.__modified = True
53 jongui 1197 # Keeps track of the number of times the 'setFileName' or 'setData'
54     # method have been executed.
55     self.__count = 0
56 jongui 1148 # 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 ksteube 1147
62     if(source == Source.XML): # Source is an XML file.
63     self.__vtk_xml_reader = vtk.vtkXMLUnstructuredGridReader()
64     # Source is a escript data object using a temp file in the background.
65     elif (self.__source == Source.ESCRIPT):
66     self.__vtk_xml_reader = vtk.vtkXMLUnstructuredGridReader()
67     # Create a temporary .xml file and retrieve its path.
68     self.__tmp_file = tempfile.mkstemp(suffix=".xml")[1]
69    
70     def __del__(self):
71     """
72     Perform some clean up of the temporary file.
73     """
74    
75     if (self.__source == Source.ESCRIPT):
76     if os.access(self.__tmp_file,os.F_OK): os.unlink(self.__tmp_file)
77    
78     def setFileName(self, file_name):
79     """
80     Set the XML file name to read.
81    
82     @type file_name: String
83     @param file_name: Name of the file to read
84     """
85    
86 jongui 1148 self.__modified = True
87 jongui 1197 self.__count += 1
88 jongui 1148
89 ksteube 1147 if(self.__source == Source.XML):
90 jongui 1199 # Check whether the specified file exists, otherwise an error is
91     # raised.
92 ksteube 1147 if not(os.access(file_name, os.F_OK)):
93 jongui 1148 raise IOError("\nERROR: '%s' file does NOT exists.\n" % \
94     file_name)
95 ksteube 1147
96     self.__vtk_xml_reader.SetFileName(file_name)
97     # Update must be called after SetFileName to make the reader
98     # up-to-date. Otherwise, some output values may be incorrect.
99     self.__vtk_xml_reader.Update()
100     self.__get_attribute_lists()
101     else:
102     raise ValueError("Source type %s does not support \
103     'setFileName'\n" % self.__source)
104    
105     def setData(self,**args):
106     """
107     Create data using the <name>=<data> pairing. Assumption is made
108     that the data will be given in the appropriate format.
109     """
110    
111 jongui 1148 self.__modified = True
112 jongui 1197 self.__count += 1
113 jongui 1148
114 ksteube 1147 if self.__source == Source.ESCRIPT:
115     esys.escript.saveVTK(self.__tmp_file,**args)
116     self.__vtk_xml_reader.SetFileName(self.__tmp_file)
117 jongui 1148
118 ksteube 1147 # Modified must be called for setData but NOT for
119     # setFileName. If Modified is not called, only the first file
120     # will always be displayed. The reason Modified is used is
121     # because the same temporary file name is always used
122     # (previous file is overwritten). Modified MUST NOT be used in
123 jongui 1199 # setFileName, as it can cause incorrect output such as map.
124 ksteube 1147 self.__vtk_xml_reader.Modified()
125 jongui 1148
126 ksteube 1147 # Update must be called after Modified. If Update is called before
127     # Modified, then the first/second image(s) may not be updated
128     # correctly.
129     self.__vtk_xml_reader.Update()
130     self.__get_attribute_lists()
131     else:
132     raise ValueError("Source type %s does not support 'setData'\n" \
133     % self.__source)
134    
135 jongui 1148 # This method is used to delay the execution of setting the active scalar
136     # until 'setFileName' or 'setData' have been executed.
137 ksteube 1147 def setActiveScalar(self, scalar):
138     """
139     Specify the scalar field to load.
140    
141     @type scalar: String
142     @param scalar: Scalar field to load from the file.
143     """
144 jongui 1148
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 ksteube 1147 # Check whether the specified scalar is available in either point
154 jongui 1199 # or cell data. If not available, an error is raised.
155 ksteube 1147
156     # NOTE: This check is similar to the check used in _getScalarRange
157     # but this is used only when a scalar attribute has been specified.
158 jongui 1148 if self.__active_scalar in self.__point_attribute['scalars']:
159     self._getDataCollectorOutput().GetPointData().SetActiveScalars(
160     self.__active_scalar)
161     elif self.__active_scalar in self.__cell_attribute['scalars']:
162     self._getDataCollectorOutput().GetCellData().SetActiveScalars(
163     self.__active_scalar)
164 ksteube 1147 else:
165 jongui 1148 raise IOError("ERROR: No scalar called '%s' is available." % \
166     self.__active_scalar)
167 ksteube 1147
168 jongui 1148 # This method is used to delay the execution of setting the active vector
169     # until 'setFileName' or 'setData' have been executed.
170 ksteube 1147 def setActiveVector(self, vector):
171     """
172     Specify the vector field to load.
173    
174     @type vector: String
175     @param vector: Vector field to load from the file.
176     """
177 jongui 1148
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 ksteube 1147 # Check whether the specified vector is available in either point
187 jongui 1153 # or cell data. If not available, error is raised.
188 ksteube 1147
189     # NOTE: This check is similar to the check used in _getVectorRange
190     # but this is used only when a vector attribute has been specified.
191 jongui 1148 if self.__active_vector in self.__point_attribute['vectors']:
192     self._getDataCollectorOutput().GetPointData().SetActiveVectors(
193     self.__active_vector)
194     elif self.__active_vector in self.__cell_attribute['vectors']:
195     self._getDataCollectorOutput().GetCellData().SetActiveVectors(
196     self.__active_vector)
197 ksteube 1147 else:
198 jongui 1148 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 ksteube 1147 def setActiveTensor(self, tensor):
204     """
205     Specify the tensor field to load.
206    
207     @type tensor: String
208     @param tensor: Tensor field to load from the file.
209     """
210    
211 jongui 1148 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 ksteube 1147 # Check whether the specified tensor is available in either point
220 jongui 1153 # or cell data. If not available, error is raised.
221 ksteube 1147
222     # NOTE: This check is similar to the check used in _getTensorRange
223     # but this is used only when a tensor attribute has been specified.
224 jongui 1148 if self.__active_tensor in self.__point_attribute['tensors']:
225     self._getDataCollectorOutput().GetPointData().SetActiveTensors(
226     self.__active_tensor)
227     elif self.__active_tensor in self.__cell_attribute['tensors']:
228     self._getDataCollectorOutput().GetCellData().SetActiveTensors(
229     self.__active_tensor)
230 ksteube 1147 else:
231 jongui 1148 raise IOError("ERROR: No tensor called '%s' is available." % \
232     self.__active_tensor)
233 ksteube 1147
234     def __get_array_type(self, arr):
235     """
236     Return whether an array type is scalar, vector or tensor by looking
237     at the number of components in the array.
238    
239     @type arr: vtkDataArray
240     @param arr: An array from the source.
241     @rtype: String
242     @return: Array type ('scalar', vector' or 'tensor')
243     """
244    
245     # Number of components in an array.
246     num_components = arr.GetNumberOfComponents()
247    
248     if num_components == 1:
249     return 'scalars'
250     elif num_components == 3:
251     return 'vectors'
252     elif num_components == 9:
253     return 'tensors'
254    
255     def __get_attribute_list(self, data):
256     """
257     Return the available scalar, vector and tensor attributes
258     (either point or cell data).
259    
260     @type data: vtkPointData or vtkCellData
261     @param data: Available point data or cell data from the source
262     @rtype: Dictionary
263     @return: Dictionary containing the available scalar, vector and \
264     tensor attributes
265     """
266    
267     attribute = {'scalars':[], 'vectors':[], 'tensors':[]}
268     if data:
269     num_arrays = data.GetNumberOfArrays() # Number of arrays.
270     for i in range(num_arrays):
271     name = data.GetArrayName(i) # Get an array name.
272     type = self.__get_array_type(data.GetArray(i)) # Get array type.
273     attribute[type].extend([name]) # Add array name to dictionary.
274    
275     return attribute
276    
277     def __get_attribute_lists(self):
278     """
279     Get all the available point and cell data attributes from the source.
280     """
281    
282     # Get all the available point data attributes into a list.
283     self.__point_attribute = \
284 jongui 1148 self.__get_attribute_list(
285     self._getDataCollectorOutput().GetPointData())
286    
287 jongui 1199 # Get all the available cell data attributes into another list.
288 ksteube 1147 self.__cell_attribute = \
289 jongui 1148 self.__get_attribute_list(
290     self._getDataCollectorOutput().GetCellData())
291 ksteube 1147
292     def _getScalarRange(self):
293     """
294     Return the scalar range.
295    
296     @rtype: Two column tuple containing numbers
297     @return: Scalar range
298     """
299    
300     # Check whether any scalar is available in either point or cell data.
301 jongui 1199 # If not available, an error is raised.
302 ksteube 1147
303     # NOTE: This check is similar to the check used in _setActiveScalar
304     # but this is used only when no scalar attribute has been specified.
305     if(len(self.__point_attribute['scalars']) != 0):
306 jongui 1148 return self._getDataCollectorOutput().GetPointData().\
307     GetScalars().GetRange(-1)
308 ksteube 1147 elif(len(self.__cell_attribute['scalars']) != 0):
309 jongui 1148 return self._getDataCollectorOutput().GetCellData().\
310     GetScalars().GetRange(-1)
311 ksteube 1147 else:
312 jongui 1148 raise IOError("\nERROR: No scalar is available.\n")
313 ksteube 1147
314     def _getVectorRange(self):
315     """
316     Return the vector range.
317    
318     @rtype: Two column tuple containing numbers
319     @return: Vector range
320     """
321    
322     # Check whether any vector is available in either point or cell data.
323 jongui 1199 # If not available, an error is raised.
324 ksteube 1147
325     # NOTE: This check is similar to the check used in _setActiveVector
326     # but this is used only when no vector attribute has been specified.
327    
328     # NOTE: Generally GetRange(-1) returns the correct vector range.
329     # However, there are certain data sets where GetRange(-1) seems
330     # to return incorrect mimimum vector although the maximum vector is
331     # correct. As a result, the mimimum vector has been hard coded to 0.0
332     # to accommodate for the incorrect cases.
333     if(len(self.__point_attribute['vectors']) != 0):
334     vector_range = \
335 jongui 1148 self._getDataCollectorOutput().GetPointData().\
336     GetVectors().GetRange(-1)
337 ksteube 1147 return (0.0, vector_range[1])
338     elif(len(self.__cell_attribute['vectors']) != 0):
339     vector_range = \
340 jongui 1148 self._getDataCollectorOutput().GetCellData().\
341     GetVectors().GetRange(-1)
342 ksteube 1147 return (0.0, vector_range[1])
343     else:
344 jongui 1148 raise IOError("\nERROR: No vector is available.\n")
345 ksteube 1147
346     def _getTensorRange(self):
347     """
348     Return the tensor range.
349    
350     @rtype: Two column tuple containing numbers
351     @return: Tensor range
352     """
353    
354     # Check whether any tensor is available in either point or cell data.
355 jongui 1199 # If not available, an error is raised.
356 ksteube 1147
357     # NOTE: This check is similar to the check used in _setActiveTensor
358     # but this is used only when no tensor attribute has been specified.
359     if(len(self.__point_attribute['tensors']) != 0):
360 jongui 1148 return self._getDataCollectorOutput().GetPointData().\
361     GetTensors().GetRange(-1)
362 ksteube 1147 elif(len(self.__cell_attribute['tensors']) != 0):
363 jongui 1148 return self._getDataCollectorOutput().GetCellData().\
364     GetTensors().GetRange(-1)
365 ksteube 1147 else:
366 jongui 1148 raise IOError("\nERROR: No tensor is available.\n")
367 ksteube 1147
368 jongui 1148 def _getDataCollectorOutput(self):
369 ksteube 1147 """
370     Return the output of the data collector.
371    
372     @rtype: vtkUnstructuredGrid
373     @return: Unstructured grid
374     """
375 jongui 1148 return self.__vtk_xml_reader.GetOutput()
376 ksteube 1147
377 jongui 1148 def _isModified(self):
378     """
379     Return whether the DataCollector has been modified.
380 ksteube 1147
381 jongui 1148 @rtype: Boolean
382     @return: True or False
383     """
384    
385     if(self.__modified == True):
386 jongui 1197 # '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 jongui 1148 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    

  ViewVC Help
Powered by ViewVC 1.1.26