/[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 1809 - (show annotations)
Thu Sep 25 06:43:44 2008 UTC (10 years, 10 months ago) by ksteube
File MIME type: text/x-python
File size: 14173 byte(s)
Copyright updated in all python files

1
2 ########################################################
3 #
4 # Copyright (c) 2003-2008 by University of Queensland
5 # Earth Systems Science Computational Center (ESSCC)
6 # http://www.uq.edu.au/esscc
7 #
8 # Primary Business: Queensland, Australia
9 # Licensed under the Open Software License version 3.0
10 # http://www.opensource.org/licenses/osl-3.0.php
11 #
12 ########################################################
13
14 __copyright__="""Copyright (c) 2003-2008 by University of Queensland
15 Earth Systems Science Computational Center (ESSCC)
16 http://www.uq.edu.au/esscc
17 Primary Business: Queensland, Australia"""
18 __license__="""Licensed under the Open Software License version 3.0
19 http://www.opensource.org/licenses/osl-3.0.php"""
20 __url__="http://www.uq.edu.au/esscc/escript-finley"
21
22 """
23 @var __author__: name of author
24 @var __copyright__: copyrights
25 @var __license__: licence agreement
26 @var __url__: url entry point on documentation
27 @var __version__: version
28 @var __date__: date of the version
29 """
30
31 __author__="John Ngui, john.ngui@uq.edu.au"
32
33
34 import vtk
35 import tempfile, os, sys
36 from constant import Source, ColorMode
37 try:
38 import esys.escript
39 except ImportError:
40 print "Warning: importing esys.escript failed."
41
42 class DataCollector:
43 """
44 Class that defines a data collector. A data collector is used to read
45 data from a XML file or from an escript object directly. Writing XML
46 files are expensive, but this approach has the advantage given that the
47 results can be analyzed easily after the simulation has completed.
48
49 @attention: A DataCollector instance can only be used to specify one
50 scalar, vector and tensor attribute from a source at any one time. If a
51 second scalar, vector or tensor attribute needs to be specified from the
52 same source, a second DataCollector instance must be created.
53 """
54
55 def __init__(self, source = Source.XML):
56 """
57 Initialise the data collector.
58
59 @type source: L{Source <constant.Source>} constant
60 @param source: Source type
61 """
62
63 self.__source = source
64 # Keeps track on whether DataCollector have been modified.
65 self.__modified = True
66 # Keeps track of the number of times the 'setFileName' or 'setData'
67 # method have been executed.
68 self.__count = 0
69 # Keeps track on whether any specific scalar, vector or tensor
70 # field have been specified.
71 self.__set_scalar = False
72 self.__set_vector= False
73 self.__set_tensor= False
74
75 if(source == Source.XML): # Source is an XML file.
76 self.__vtk_xml_reader = vtk.vtkXMLUnstructuredGridReader()
77 # Source is a escript data object using a temp file in the background.
78 elif (self.__source == Source.ESCRIPT):
79 self.__vtk_xml_reader = vtk.vtkXMLUnstructuredGridReader()
80 # Create a temporary .xml file and retrieve its path.
81 self.__tmp_file = tempfile.mkstemp(suffix=".xml")[1]
82
83 def __del__(self):
84 """
85 Perform some clean up of the temporary file.
86 """
87
88 if (self.__source == Source.ESCRIPT):
89 if os.access(self.__tmp_file,os.F_OK): os.unlink(self.__tmp_file)
90
91 def setFileName(self, file_name):
92 """
93 Set the XML file name to read.
94
95 @type file_name: String
96 @param file_name: Name of the file to read
97 """
98
99 self.__modified = True
100 self.__count += 1
101
102 if(self.__source == Source.XML):
103 # Check whether the specified file exists, otherwise an error is
104 # raised.
105 if not(os.access(file_name, os.F_OK)):
106 raise IOError("\nERROR: '%s' file does NOT exists.\n" % \
107 file_name)
108
109 self.__vtk_xml_reader.SetFileName(file_name)
110 # Update must be called after SetFileName to make the reader
111 # up-to-date. Otherwise, some output values may be incorrect.
112 self.__vtk_xml_reader.Update()
113 self.__get_attribute_lists()
114 else:
115 raise ValueError("Source type %s does not support \
116 'setFileName'\n" % self.__source)
117
118 def setData(self,**args):
119 """
120 Create data using the <name>=<data> pairing. Assumption is made
121 that the data will be given in the appropriate format.
122 """
123
124 self.__modified = True
125 self.__count += 1
126
127 if self.__source == Source.ESCRIPT:
128 esys.escript.saveVTK(self.__tmp_file,**args)
129 self.__vtk_xml_reader.SetFileName(self.__tmp_file)
130
131 # Modified must be called for setData but NOT for
132 # setFileName. If Modified is not called, only the first file
133 # will always be displayed. The reason Modified is used is
134 # because the same temporary file name is always used
135 # (previous file is overwritten). Modified MUST NOT be used in
136 # setFileName, as it can cause incorrect output such as map.
137 self.__vtk_xml_reader.Modified()
138
139 # Update must be called after Modified. If Update is called before
140 # Modified, then the first/second image(s) may not be updated
141 # correctly.
142 self.__vtk_xml_reader.Update()
143 self.__get_attribute_lists()
144 else:
145 raise ValueError("Source type %s does not support 'setData'\n" \
146 % self.__source)
147
148 # This method is used to delay the execution of setting the active scalar
149 # until 'setFileName' or 'setData' have been executed.
150 def setActiveScalar(self, scalar):
151 """
152 Specify the scalar field to load.
153
154 @type scalar: String
155 @param scalar: Scalar field to load from the file.
156 """
157
158 self.__set_scalar = True
159 self.__active_scalar = scalar
160
161 def _setActiveScalar(self):
162 """
163 Load the specified scalar field.
164 """
165
166 # Check whether the specified scalar is available in either point
167 # or cell data. If not available, an error is raised.
168
169 # NOTE: This check is similar to the check used in _getScalarRange
170 # but this is used only when a scalar attribute has been specified.
171 if self.__active_scalar in self.__point_attribute['scalars']:
172 self._getDataCollectorOutput().GetPointData().SetActiveScalars(
173 self.__active_scalar)
174 elif self.__active_scalar in self.__cell_attribute['scalars']:
175 self._getDataCollectorOutput().GetCellData().SetActiveScalars(
176 self.__active_scalar)
177 else:
178 raise IOError("ERROR: No scalar called '%s' is available." % \
179 self.__active_scalar)
180
181 # This method is used to delay the execution of setting the active vector
182 # until 'setFileName' or 'setData' have been executed.
183 def setActiveVector(self, vector):
184 """
185 Specify the vector field to load.
186
187 @type vector: String
188 @param vector: Vector field to load from the file.
189 """
190
191 self.__set_vector = True
192 self.__active_vector = vector
193
194 def _setActiveVector(self):
195 """
196 Load the specified vector field.
197 """
198
199 # Check whether the specified vector is available in either point
200 # or cell data. If not available, error is raised.
201
202 # NOTE: This check is similar to the check used in _getVectorRange
203 # but this is used only when a vector attribute has been specified.
204 if self.__active_vector in self.__point_attribute['vectors']:
205 self._getDataCollectorOutput().GetPointData().SetActiveVectors(
206 self.__active_vector)
207 elif self.__active_vector in self.__cell_attribute['vectors']:
208 self._getDataCollectorOutput().GetCellData().SetActiveVectors(
209 self.__active_vector)
210 else:
211 raise IOError("ERROR: No vector called '%s' is available." % \
212 self.__active_vector)
213
214 # This method is used to delay the execution of setting the active tensor
215 # until 'setFileName' or 'setData' have been executed.
216 def setActiveTensor(self, tensor):
217 """
218 Specify the tensor field to load.
219
220 @type tensor: String
221 @param tensor: Tensor field to load from the file.
222 """
223
224 self.__set_tensor = True
225 self.__active_tensor = tensor
226
227 def _setActiveTensor(self):
228 """
229 Load the the specified tensor field.
230 """
231
232 # Check whether the specified tensor is available in either point
233 # or cell data. If not available, error is raised.
234
235 # NOTE: This check is similar to the check used in _getTensorRange
236 # but this is used only when a tensor attribute has been specified.
237 if self.__active_tensor in self.__point_attribute['tensors']:
238 self._getDataCollectorOutput().GetPointData().SetActiveTensors(
239 self.__active_tensor)
240 elif self.__active_tensor in self.__cell_attribute['tensors']:
241 self._getDataCollectorOutput().GetCellData().SetActiveTensors(
242 self.__active_tensor)
243 else:
244 raise IOError("ERROR: No tensor called '%s' is available." % \
245 self.__active_tensor)
246
247 def __get_array_type(self, arr):
248 """
249 Return whether an array type is scalar, vector or tensor by looking
250 at the number of components in the array.
251
252 @type arr: vtkDataArray
253 @param arr: An array from the source.
254 @rtype: String
255 @return: Array type ('scalar', vector' or 'tensor')
256 """
257
258 # Number of components in an array.
259 num_components = arr.GetNumberOfComponents()
260
261 if num_components == 1:
262 return 'scalars'
263 elif num_components == 3:
264 return 'vectors'
265 elif num_components == 9:
266 return 'tensors'
267
268 def __get_attribute_list(self, data):
269 """
270 Return the available scalar, vector and tensor attributes
271 (either point or cell data).
272
273 @type data: vtkPointData or vtkCellData
274 @param data: Available point data or cell data from the source
275 @rtype: Dictionary
276 @return: Dictionary containing the available scalar, vector and \
277 tensor attributes
278 """
279
280 attribute = {'scalars':[], 'vectors':[], 'tensors':[]}
281 if data:
282 num_arrays = data.GetNumberOfArrays() # Number of arrays.
283 for i in range(num_arrays):
284 name = data.GetArrayName(i) # Get an array name.
285 type = self.__get_array_type(data.GetArray(i)) # Get array type.
286 attribute[type].extend([name]) # Add array name to dictionary.
287
288 return attribute
289
290 def __get_attribute_lists(self):
291 """
292 Get all the available point and cell data attributes from the source.
293 """
294
295 # Get all the available point data attributes into a list.
296 self.__point_attribute = \
297 self.__get_attribute_list(
298 self._getDataCollectorOutput().GetPointData())
299
300 # Get all the available cell data attributes into another list.
301 self.__cell_attribute = \
302 self.__get_attribute_list(
303 self._getDataCollectorOutput().GetCellData())
304
305 def _getScalarRange(self):
306 """
307 Return the scalar range.
308
309 @rtype: Two column tuple containing numbers
310 @return: Scalar range
311 """
312
313 # Check whether any scalar is available in either point or cell data.
314 # If not available, an error is raised.
315
316 # NOTE: This check is similar to the check used in _setActiveScalar
317 # but this is used only when no scalar attribute has been specified.
318 if(len(self.__point_attribute['scalars']) != 0):
319 return self._getDataCollectorOutput().GetPointData().\
320 GetScalars().GetRange(-1)
321 elif(len(self.__cell_attribute['scalars']) != 0):
322 return self._getDataCollectorOutput().GetCellData().\
323 GetScalars().GetRange(-1)
324 else:
325 raise IOError("\nERROR: No scalar is available.\n")
326
327 def _getVectorRange(self):
328 """
329 Return the vector range.
330
331 @rtype: Two column tuple containing numbers
332 @return: Vector range
333 """
334
335 # Check whether any vector is available in either point or cell data.
336 # If not available, an error is raised.
337
338 # NOTE: This check is similar to the check used in _setActiveVector
339 # but this is used only when no vector attribute has been specified.
340
341 # NOTE: Generally GetRange(-1) returns the correct vector range.
342 # However, there are certain data sets where GetRange(-1) seems
343 # to return incorrect mimimum vector although the maximum vector is
344 # correct. As a result, the mimimum vector has been hard coded to 0.0
345 # to accommodate for the incorrect cases.
346 if(len(self.__point_attribute['vectors']) != 0):
347 vector_range = \
348 self._getDataCollectorOutput().GetPointData().\
349 GetVectors().GetRange(-1)
350 return (0.0, vector_range[1])
351 elif(len(self.__cell_attribute['vectors']) != 0):
352 vector_range = \
353 self._getDataCollectorOutput().GetCellData().\
354 GetVectors().GetRange(-1)
355 return (0.0, vector_range[1])
356 else:
357 raise IOError("\nERROR: No vector is available.\n")
358
359 def _getTensorRange(self):
360 """
361 Return the tensor range.
362
363 @rtype: Two column tuple containing numbers
364 @return: Tensor range
365 """
366
367 # Check whether any tensor is available in either point or cell data.
368 # If not available, an error is raised.
369
370 # NOTE: This check is similar to the check used in _setActiveTensor
371 # but this is used only when no tensor attribute has been specified.
372 if(len(self.__point_attribute['tensors']) != 0):
373 return self._getDataCollectorOutput().GetPointData().\
374 GetTensors().GetRange(-1)
375 elif(len(self.__cell_attribute['tensors']) != 0):
376 return self._getDataCollectorOutput().GetCellData().\
377 GetTensors().GetRange(-1)
378 else:
379 raise IOError("\nERROR: No tensor is available.\n")
380
381 def _getDataCollectorOutput(self):
382 """
383 Return the output of the data collector.
384
385 @rtype: vtkUnstructuredGrid
386 @return: Unstructured grid
387 """
388 return self.__vtk_xml_reader.GetOutput()
389
390 def _isModified(self):
391 """
392 Return whether the DataCollector has been modified.
393
394 @rtype: Boolean
395 @return: True or False
396 """
397
398 if(self.__modified == True):
399 # 'self.__modified' is set to False only if the 'setFileName' or
400 # 'setData' method have been called once. This is to prevent
401 # the scalar range and active field (i.e. scalar, vector or tensor)
402 # from being updated as no changes has taken place (for performance
403 # reasons). However if the 'setFileName' or 'setData' method is
404 # called more than once, then 'self.__modified' remains True.
405 if(self.__count == 1):
406 self.__modified = False
407 return True
408 else:
409 return False
410
411 def _isScalarSet(self):
412 """
413 Return whether a specific scalar field has been specified.
414
415 @rtype: Boolean
416 @return: True or False
417 """
418
419 return self.__set_scalar
420
421 def _isVectorSet(self):
422 """
423 Return whether a specific vector field has been specified.
424
425 @rtype: Boolean
426 @return: True or False
427 """
428
429 return self.__set_vector
430
431 def _isTensorSet(self):
432 """
433 Return whether a specific tensor field has been specified.
434
435 @rtype: Boolean
436 @return: True or False
437 """
438
439 return self.__set_tensor
440
441 def _getCenter(self):
442 """
443 Return the center of the rendered object.
444
445 @rtype: Three column tuple containing numbers
446 @return: Center of the rendered object
447 """
448
449 return self._getDataCollectorOutput().GetCenter()
450

  ViewVC Help
Powered by ViewVC 1.1.26