/[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 1197 - (show annotations)
Mon Jun 18 02:08:34 2007 UTC (12 years, 2 months ago) by jongui
File MIME type: text/x-python
File size: 13737 byte(s)
Update the way movies are generated. Please refer to the examples. 

The user can now either specify the image range(first and last images inclusive):
mov.imageRange(input_directory = PYVISI_EXAMPLE_IMAGES_PATH,
        first_image = IMAGE_NAME + "000938.jpg",
		last_image = IMAGE_NAME + "000948.jpg")
mov.makeMovie(os.path.join(PYVISI_EXAMPLE_IMAGES_PATH, "movie.mpg"))

or the user can specify a list of images:

lst = ['image1.jpg', 'image5.jpg', 'image7.jpg]
mov.imageList(input_directory = PYVISI_EXAMPLE_IMAGES_PATH, image_list = lst)
mov.makeMovie(os.path.join(PYVISI_EXAMPLE_IMAGES_PATH, "movie.mpg"))


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 exit.
91 if not(os.access(file_name, os.F_OK)):
92 raise IOError("\nERROR: '%s' file does NOT exists.\n" % \
93 file_name)
94
95 self.__vtk_xml_reader.SetFileName(file_name)
96 # Update must be called after SetFileName to make the reader
97 # up-to-date. Otherwise, some output values may be incorrect.
98 self.__vtk_xml_reader.Update()
99 self.__get_attribute_lists()
100 else:
101 raise ValueError("Source type %s does not support \
102 'setFileName'\n" % self.__source)
103
104 def setData(self,**args):
105 """
106 Create data using the <name>=<data> pairing. Assumption is made
107 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:
114 esys.escript.saveVTK(self.__tmp_file,**args)
115 self.__vtk_xml_reader.SetFileName(self.__tmp_file)
116
117 # Modified must be called for setData but NOT for
118 # setFileName. If Modified is not called, only the first file
119 # will always be displayed. The reason Modified is used is
120 # because the same temporary file name is always used
121 # (previous file is overwritten). Modified MUST NOT be used in
122 # setFileName, it can cause incorrect output such as map.
123 self.__vtk_xml_reader.Modified()
124
125 # Update must be called after Modified. If Update is called before
126 # Modified, then the first/second image(s) may not be updated
127 # correctly.
128 self.__vtk_xml_reader.Update()
129 self.__get_attribute_lists()
130 else:
131 raise ValueError("Source type %s does not support 'setData'\n" \
132 % 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):
137 """
138 Specify the scalar field to load.
139
140 @type scalar: String
141 @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
153 # or cell data. If not available, error is raised.
154
155 # NOTE: This check is similar to the check used in _getScalarRange
156 # but this is used only when a scalar attribute has been specified.
157 if self.__active_scalar in self.__point_attribute['scalars']:
158 self._getDataCollectorOutput().GetPointData().SetActiveScalars(
159 self.__active_scalar)
160 elif self.__active_scalar in self.__cell_attribute['scalars']:
161 self._getDataCollectorOutput().GetCellData().SetActiveScalars(
162 self.__active_scalar)
163 else:
164 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):
170 """
171 Specify the vector field to load.
172
173 @type vector: String
174 @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
186 # or cell data. If not available, error is raised.
187
188 # NOTE: This check is similar to the check used in _getVectorRange
189 # but this is used only when a vector attribute has been specified.
190 if self.__active_vector in self.__point_attribute['vectors']:
191 self._getDataCollectorOutput().GetPointData().SetActiveVectors(
192 self.__active_vector)
193 elif self.__active_vector in self.__cell_attribute['vectors']:
194 self._getDataCollectorOutput().GetCellData().SetActiveVectors(
195 self.__active_vector)
196 else:
197 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):
203 """
204 Specify the tensor field to load.
205
206 @type tensor: String
207 @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
219 # or cell data. If not available, error is raised.
220
221 # NOTE: This check is similar to the check used in _getTensorRange
222 # but this is used only when a tensor attribute has been specified.
223 if self.__active_tensor in self.__point_attribute['tensors']:
224 self._getDataCollectorOutput().GetPointData().SetActiveTensors(
225 self.__active_tensor)
226 elif self.__active_tensor in self.__cell_attribute['tensors']:
227 self._getDataCollectorOutput().GetCellData().SetActiveTensors(
228 self.__active_tensor)
229 else:
230 raise IOError("ERROR: No tensor called '%s' is available." % \
231 self.__active_tensor)
232
233 def __get_array_type(self, arr):
234 """
235 Return whether an array type is scalar, vector or tensor by looking
236 at the number of components in the array.
237
238 @type arr: vtkDataArray
239 @param arr: An array from the source.
240 @rtype: String
241 @return: Array type ('scalar', vector' or 'tensor')
242 """
243
244 # Number of components in an array.
245 num_components = arr.GetNumberOfComponents()
246
247 if num_components == 1:
248 return 'scalars'
249 elif num_components == 3:
250 return 'vectors'
251 elif num_components == 9:
252 return 'tensors'
253
254 def __get_attribute_list(self, data):
255 """
256 Return the available scalar, vector and tensor attributes
257 (either point or cell data).
258
259 @type data: vtkPointData or vtkCellData
260 @param data: Available point data or cell data from the source
261 @rtype: Dictionary
262 @return: Dictionary containing the available scalar, vector and \
263 tensor attributes
264 """
265
266 attribute = {'scalars':[], 'vectors':[], 'tensors':[]}
267 if data:
268 num_arrays = data.GetNumberOfArrays() # Number of arrays.
269 for i in range(num_arrays):
270 name = data.GetArrayName(i) # Get an array name.
271 type = self.__get_array_type(data.GetArray(i)) # Get array type.
272 attribute[type].extend([name]) # Add array name to dictionary.
273
274 return attribute
275
276 def __get_attribute_lists(self):
277 """
278 Get all the available point and cell data attributes from the source.
279 """
280
281 # Get all the available point data attributes into a list.
282 self.__point_attribute = \
283 self.__get_attribute_list(
284 self._getDataCollectorOutput().GetPointData())
285
286 # Get all the available cell data attribute into another list.
287 self.__cell_attribute = \
288 self.__get_attribute_list(
289 self._getDataCollectorOutput().GetCellData())
290
291 def _getScalarRange(self):
292 """
293 Return the scalar range.
294
295 @rtype: Two column tuple containing numbers
296 @return: Scalar range
297 """
298
299 # Check whether any scalar is available in either point or cell data.
300 # If not available, program exits.
301
302 # NOTE: This check is similar to the check used in _setActiveScalar
303 # but this is used only when no scalar attribute has been specified.
304 if(len(self.__point_attribute['scalars']) != 0):
305 return self._getDataCollectorOutput().GetPointData().\
306 GetScalars().GetRange(-1)
307 elif(len(self.__cell_attribute['scalars']) != 0):
308 return self._getDataCollectorOutput().GetCellData().\
309 GetScalars().GetRange(-1)
310 else:
311 raise IOError("\nERROR: No scalar is available.\n")
312
313 def _getVectorRange(self):
314 """
315 Return the vector range.
316
317 @rtype: Two column tuple containing numbers
318 @return: Vector range
319 """
320
321 # Check whether any vector is available in either point or cell data.
322 # If not available, program exits.
323
324 # NOTE: This check is similar to the check used in _setActiveVector
325 # but this is used only when no vector attribute has been specified.
326
327 # NOTE: Generally GetRange(-1) returns the correct vector range.
328 # However, there are certain data sets where GetRange(-1) seems
329 # to return incorrect mimimum vector although the maximum vector is
330 # correct. As a result, the mimimum vector has been hard coded to 0.0
331 # to accommodate for the incorrect cases.
332 if(len(self.__point_attribute['vectors']) != 0):
333 vector_range = \
334 self._getDataCollectorOutput().GetPointData().\
335 GetVectors().GetRange(-1)
336 return (0.0, vector_range[1])
337 elif(len(self.__cell_attribute['vectors']) != 0):
338 vector_range = \
339 self._getDataCollectorOutput().GetCellData().\
340 GetVectors().GetRange(-1)
341 return (0.0, vector_range[1])
342 else:
343 raise IOError("\nERROR: No vector is available.\n")
344
345 def _getTensorRange(self):
346 """
347 Return the tensor range.
348
349 @rtype: Two column tuple containing numbers
350 @return: Tensor range
351 """
352
353 # Check whether any tensor is available in either point or cell data.
354 # If not available, program exits.
355
356 # NOTE: This check is similar to the check used in _setActiveTensor
357 # but this is used only when no tensor attribute has been specified.
358 if(len(self.__point_attribute['tensors']) != 0):
359 return self._getDataCollectorOutput().GetPointData().\
360 GetTensors().GetRange(-1)
361 elif(len(self.__cell_attribute['tensors']) != 0):
362 return self._getDataCollectorOutput().GetCellData().\
363 GetTensors().GetRange(-1)
364 else:
365 raise IOError("\nERROR: No tensor is available.\n")
366
367 def _getDataCollectorOutput(self):
368 """
369 Return the output of the data collector.
370
371 @rtype: vtkUnstructuredGrid
372 @return: Unstructured grid
373 """
374 return self.__vtk_xml_reader.GetOutput()
375
376 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

  ViewVC Help
Powered by ViewVC 1.1.26