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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1199 - (show annotations)
Wed Jun 20 05:01:30 2007 UTC (12 years, 2 months ago) by jongui
File MIME type: text/x-python
File size: 13779 byte(s)
- Updated the epydocs and guide.
Deleted redundant files and methods.
Tidied up the codes.
1 """
2 @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
22 import tempfile, os, sys
23 from constant import Source, ColorMode
24 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 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
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 # 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.
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 self.__modified = True
87 self.__count += 1
88
89 if(self.__source == Source.XML):
90 # Check whether the specified file exists, otherwise an error is
91 # raised.
92 if not(os.access(file_name, os.F_OK)):
93 raise IOError("\nERROR: '%s' file does NOT exists.\n" % \
94 file_name)
95
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 self.__modified = True
112 self.__count += 1
113
114 if self.__source == Source.ESCRIPT:
115 esys.escript.saveVTK(self.__tmp_file,**args)
116 self.__vtk_xml_reader.SetFileName(self.__tmp_file)
117
118 # 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 # setFileName, as it can cause incorrect output such as map.
124 self.__vtk_xml_reader.Modified()
125
126 # 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 # 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):
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
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
154 # or cell data. If not available, an error is raised.
155
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 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 else:
165 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):
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
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
187 # or cell data. If not available, error is raised.
188
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 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 else:
198 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):
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 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
220 # or cell data. If not available, error is raised.
221
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 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 else:
231 raise IOError("ERROR: No tensor called '%s' is available." % \
232 self.__active_tensor)
233
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 self.__get_attribute_list(
285 self._getDataCollectorOutput().GetPointData())
286
287 # Get all the available cell data attributes into another list.
288 self.__cell_attribute = \
289 self.__get_attribute_list(
290 self._getDataCollectorOutput().GetCellData())
291
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 # If not available, an error is raised.
302
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 return self._getDataCollectorOutput().GetPointData().\
307 GetScalars().GetRange(-1)
308 elif(len(self.__cell_attribute['scalars']) != 0):
309 return self._getDataCollectorOutput().GetCellData().\
310 GetScalars().GetRange(-1)
311 else:
312 raise IOError("\nERROR: No scalar is available.\n")
313
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 # If not available, an error is raised.
324
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 self._getDataCollectorOutput().GetPointData().\
336 GetVectors().GetRange(-1)
337 return (0.0, vector_range[1])
338 elif(len(self.__cell_attribute['vectors']) != 0):
339 vector_range = \
340 self._getDataCollectorOutput().GetCellData().\
341 GetVectors().GetRange(-1)
342 return (0.0, vector_range[1])
343 else:
344 raise IOError("\nERROR: No vector is available.\n")
345
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 # If not available, an error is raised.
356
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 return self._getDataCollectorOutput().GetPointData().\
361 GetTensors().GetRange(-1)
362 elif(len(self.__cell_attribute['tensors']) != 0):
363 return self._getDataCollectorOutput().GetCellData().\
364 GetTensors().GetRange(-1)
365 else:
366 raise IOError("\nERROR: No tensor is available.\n")
367
368 def _getDataCollectorOutput(self):
369 """
370 Return the output of the data collector.
371
372 @rtype: vtkUnstructuredGrid
373 @return: Unstructured grid
374 """
375 return self.__vtk_xml_reader.GetOutput()
376
377 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

  ViewVC Help
Powered by ViewVC 1.1.26