/[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 1138 - (show annotations)
Mon May 14 04:15:04 2007 UTC (13 years, 6 months ago) by gross
File MIME type: text/x-python
File size: 12700 byte(s)
 * some of the sys.exit calls removed.
 * some modifications on the test (and more work needs to be done, use test/python/run_carpet.py as an example) to get them going with scons 

-> things seems to run on windows XP.
1 """
2 @author: John NGUI
3 """
4
5 import vtk
6 import tempfile, os, sys
7 from constant import Source, VizType, ColorMode
8 try:
9 import esys.escript
10 except ImportError:
11 print "Warning: importing esys.escript failed."
12
13 class DataCollector:
14 """
15 Class that defines a data collector. A data collector is used to read
16 data from an XML file or from an escript object directly.
17
18 @attention: A DataCollector instance can only be used to specify one
19 scalar, vector and tensor attribute from a source at any one time. If a
20 second scalar, vector or tensor attribute needs to be specified from the
21 same source, a second DataCollector instance must be created.
22
23 @attention: When a series of XML files or escript objects are read
24 (using 'setFileName' or 'setData' in a for-loop), the 'setActiveScalar' /
25 'setActiveVector' / 'setActiveTensor' have to be called for each new file
26 (provided a specific field needs to be loaded) as all active fields
27 specified from the previous file goes back to the default once a new file
28 is read.
29 """
30
31 def __init__(self, source = Source.XML):
32 """
33 Initialise the data collector.
34
35 @type source: L{Source <constant.Source>} constant
36 @param source: Source type
37 """
38
39 self.__source = source
40 self.__count = 0 # Keeps track of the number of files/sources read.
41
42 if(source == Source.XML): # Source is an XML file.
43 self.__vtk_xml_reader = vtk.vtkXMLUnstructuredGridReader()
44 # Source is a escript data object using a temp file in the background.
45 elif (self.__source == Source.ESCRIPT):
46 self.__vtk_xml_reader = vtk.vtkXMLUnstructuredGridReader()
47 # Create a temporary .xml file and retrieve its path.
48 self.__tmp_file = tempfile.mkstemp(suffix=".xml")[1]
49
50 def __del__(self):
51 """
52 Perform some clean up of the temporary file.
53 """
54
55 if (self.__source == Source.ESCRIPT):
56 if os.access(self.__tmp_file,os.F_OK): os.unlink(self.__tmp_file)
57
58 def setFileName(self, file_name):
59 """
60 Set the XML file name to read.
61
62 @type file_name: String
63 @param file_name: Name of the file to read
64 """
65
66 if(self.__source == Source.XML):
67 # Check whether the specified file exists, otherwise exit.
68 if not(os.access(file_name, os.F_OK)):
69 raise IOError("ERROR: '%s' file does NOT exists." % file_name)
70
71 self.__vtk_xml_reader.SetFileName(file_name)
72 # Update must be called after SetFileName to make the reader
73 # up-to-date. Otherwise, some output values may be incorrect.
74 self.__vtk_xml_reader.Update()
75 self.__output = self.__vtk_xml_reader.GetOutput()
76 self.__get_attribute_lists()
77
78 # Count has to be larger than zero because when setFileName is
79 # called for the first time, the data set mapper has not yet been
80 # instantiated. Therefore, the range of the mapper can only be
81 # updated after the first file/source has been read.
82 if(self.__count > 0):
83 self._updateRange()
84
85 self.__count+=1
86
87 else:
88 raise ValueError("Source type %s does not support \
89 'setFileName'\n" % self.__source)
90
91 def setData(self,**args):
92 """
93 Create data using the <name>=<data> pairing. Assumption is made
94 that the data will be given in the appropriate format.
95 """
96
97 if self.__source == Source.ESCRIPT:
98 esys.escript.saveVTK(self.__tmp_file,**args)
99 self.__vtk_xml_reader.SetFileName(self.__tmp_file)
100 # Modified must be called for setData but NOT for
101 # setFileName. If Modified is not called, only the first file
102 # will always be displayed. The reason Modified is used is
103 # because the same temporary file name is always used
104 # (previous file is overwritten). Modified MUST NOT be used in
105 # setFileName, it can cause incorrect output such as map.
106 self.__vtk_xml_reader.Modified()
107 # Update must be called after Modified. If Update is called before
108 # Modified, then the first/second image(s) may not be updated
109 # correctly.
110 self.__vtk_xml_reader.Update()
111 self.__output = self.__vtk_xml_reader.GetOutput()
112 self.__get_attribute_lists()
113
114 if(self.__count > 0):
115 self._updateRange()
116
117 self.__count+=1
118 else:
119 raise ValueError("Source type %s does not support 'setData'\n" \
120 % self.__source)
121
122 def setActiveScalar(self, scalar):
123 """
124 Specify the scalar field to load.
125
126 @type scalar: String
127 @param scalar: Scalar field to load from the file.
128 """
129
130 # Check whether the specified scalar is available in either point
131 # or cell data. If not available, program exits.
132
133 # NOTE: This check is similar to the check used in _getScalarRange
134 # but this is used only when a scalar attribute has been specified.
135 if scalar in self.__point_attribute['scalars']:
136 self._getOutput().GetPointData().SetActiveScalars(scalar)
137 elif scalar in self.__cell_attribute['scalars']:
138 self._getOutput().GetCellData().SetActiveScalars(scalar)
139 else:
140 raise IOError("ERROR: No scalar called '%s' is available." % scalar)
141
142 def setActiveVector(self, vector):
143 """
144 Specify the vector field to load.
145
146 @type vector: String
147 @param vector: Vector field to load from the file.
148 """
149
150 # Check whether the specified vector is available in either point
151 # or cell data. If not available, program exits.
152
153 # NOTE: This check is similar to the check used in _getVectorRange
154 # but this is used only when a vector attribute has been specified.
155 if vector in self.__point_attribute['vectors']:
156 self._getOutput().GetPointData().SetActiveVectors(vector)
157 elif vector in self.__cell_attribute['vectors']:
158 self._getOutput().GetCellData().SetActiveVectors(vector)
159 else:
160 raise IOError("ERROR: No vector called '%s' is available." % vector)
161
162 def setActiveTensor(self, tensor):
163 """
164 Specify the tensor field to load.
165
166 @type tensor: String
167 @param tensor: Tensor field to load from the file.
168 """
169
170 # Check whether the specified tensor is available in either point
171 # or cell data. If not available, program exits.
172
173 # NOTE: This check is similar to the check used in _getTensorRange
174 # but this is used only when a tensor attribute has been specified.
175 if tensor in self.__point_attribute['tensors']:
176 self._getOutput().GetPointData().SetActiveTensors(tensor)
177 elif tensor in self.__cell_attribute['tensors']:
178 self._getOutput().GetCellData().SetActiveTensors(tensor)
179 else:
180 raise IOError("ERROR: No tensor called '%s' is available." % tensor)
181
182 # 'object' is set to 'None' because some types of visualization have
183 # two ranges that needs to be updated while others only have one.
184 def _paramForUpdatingMultipleSources(self, viz_type, color_mode, mapper,
185 object = None):
186 """
187 Parameters required to update the necessary data when two or more
188 files or escript objects are read.
189
190 @type viz_type: : L{VizType <constant.VizType>} constant
191 @param viz_type: Type if visualization
192 @type color_mode: L{ColorMode <constant.ColorMode>} constant
193 @param color_mode: Type of color mode
194 @type mapper: vtkDataSetMapper
195 @param mapper: Mapped data
196 @type object: vtkPolyDataAlgorithm (i.e. vtkContourFilter, vtkGlyph3D, \
197 etc)
198 @param object: Polygonal data
199 """
200
201 self.__viz_type = viz_type
202 self.__color_mode = color_mode
203 self.__mapper = mapper
204 self.__object = object
205
206 def _updateRange(self):
207 """
208 Update the necessary range(s) when two or more files or escript objects
209 are read.
210 """
211
212 if self.__viz_type == VizType.MAP or \
213 self.__viz_type == VizType.ELLIPSOID or \
214 self.__viz_type == VizType.CARPET:
215 self.__mapper.SetScalarRange(self._getScalarRange())
216 elif self.__viz_type == VizType.VELOCITY:
217 if self.__color_mode == ColorMode.VECTOR:
218 self.__object.SetRange(self._getVectorRange())
219 self.__mapper.SetScalarRange(self._getVectorRange())
220 elif self.__color_mode == ColorMode.SCALAR:
221 self.__object.SetRange(self._getScalarRange())
222 self.__mapper.SetScalarRange(self._getScalarRange())
223 elif self.__viz_type == VizType.CONTOUR:
224 self.__object.GenerateValues(
225 self.__object.GetNumberOfContours(),
226 self._getScalarRange()[0],
227 self._getScalarRange()[1])
228 self.__mapper.SetScalarRange(self._getScalarRange())
229 elif self.__viz_type == VizType.STREAMLINE:
230 if self.__color_mode == ColorMode.VECTOR:
231 self.__mapper.SetScalarRange(self._getVectorRange())
232 elif self.__color_mode == ColorMode.SCALAR:
233 self.__mapper.SetScalarRange(self._getScalarRange())
234
235 def __get_array_type(self, arr):
236 """
237 Return whether an array type is scalar, vector or tensor by looking
238 at the number of components in the array.
239
240 @type arr: vtkDataArray
241 @param arr: An array from the source.
242 @rtype: String
243 @return: Array type ('scalar', vector' or 'tensor')
244 """
245
246 # Number of components in an array.
247 num_components = arr.GetNumberOfComponents()
248
249 if num_components == 1:
250 return 'scalars'
251 elif num_components == 3:
252 return 'vectors'
253 elif num_components == 9:
254 return 'tensors'
255
256 def __get_attribute_list(self, data):
257 """
258 Return the available scalar, vector and tensor attributes
259 (either point or cell data).
260
261 @type data: vtkPointData or vtkCellData
262 @param data: Available point data or cell data from the source
263 @rtype: Dictionary
264 @return: Dictionary containing the available scalar, vector and \
265 tensor attributes
266 """
267
268 attribute = {'scalars':[], 'vectors':[], 'tensors':[]}
269 if data:
270 num_arrays = data.GetNumberOfArrays() # Number of arrays.
271 for i in range(num_arrays):
272 name = data.GetArrayName(i) # Get an array name.
273 type = self.__get_array_type(data.GetArray(i)) # Get array type.
274 attribute[type].extend([name]) # Add array name to dictionary.
275
276 return attribute
277
278 def __get_attribute_lists(self):
279 """
280 Get all the available point and cell data attributes from the source.
281 """
282
283 # Get all the available point data attributes into a list.
284 self.__point_attribute = \
285 self.__get_attribute_list(self._getOutput().GetPointData())
286 # Get all the available cell data attribute into another list.
287 self.__cell_attribute = \
288 self.__get_attribute_list(self._getOutput().GetCellData())
289
290 def _getScalarRange(self):
291 """
292 Return the scalar range.
293
294 @rtype: Two column tuple containing numbers
295 @return: Scalar range
296 """
297
298 # Check whether any scalar is available in either point or cell data.
299 # If not available, program exits.
300
301 # NOTE: This check is similar to the check used in _setActiveScalar
302 # but this is used only when no scalar attribute has been specified.
303 if(len(self.__point_attribute['scalars']) != 0):
304 return self._getOutput().GetPointData().GetScalars().GetRange(-1)
305 elif(len(self.__cell_attribute['scalars']) != 0):
306 return self._getOutput().GetCellData().GetScalars().GetRange(-1)
307 else:
308 raise IOError("ERROR: No scalar is available.")
309
310 def _getVectorRange(self):
311 """
312 Return the vector range.
313
314 @rtype: Two column tuple containing numbers
315 @return: Vector range
316 """
317
318 # Check whether any vector is available in either point or cell data.
319 # If not available, program exits.
320
321 # NOTE: This check is similar to the check used in _setActiveVector
322 # but this is used only when no vector attribute has been specified.
323
324 # NOTE: Generally GetRange(-1) returns the correct vector range.
325 # However, there are certain data sets where GetRange(-1) seems
326 # to return incorrect mimimum vector although the maximum vector is
327 # correct. As a result, the mimimum vector has been hard coded to 0.0
328 # to accommodate for the incorrect cases.
329 if(len(self.__point_attribute['vectors']) != 0):
330 vector_range = \
331 self._getOutput().GetPointData().GetVectors().GetRange(-1)
332 return (0.0, vector_range[1])
333 elif(len(self.__cell_attribute['vectors']) != 0):
334 vector_range = \
335 self._getOutput().GetCellData().GetVectors().GetRange(-1)
336 return (0.0, vector_range[1])
337 else:
338 print "\nERROR: No vector is available.\n"
339 sys.exit(0)
340
341 def _getTensorRange(self):
342 """
343 Return the tensor range.
344
345 @rtype: Two column tuple containing numbers
346 @return: Tensor range
347 """
348
349 # Check whether any tensor is available in either point or cell data.
350 # If not available, program exits.
351
352 # NOTE: This check is similar to the check used in _setActiveTensor
353 # but this is used only when no tensor attribute has been specified.
354 if(len(self.__point_attribute['tensors']) != 0):
355 return self._getOutput().GetPointData().GetTensors().GetRange(-1)
356 elif(len(self.__cell_attribute['tensors']) != 0):
357 return self._getOutput().GetCellData().GetTensors().GetRange(-1)
358 else:
359 print "\nERROR: No tensor is available.\n"
360 sys.exit(1)
361
362 def _getOutput(self):
363 """
364 Return the output of the data collector.
365
366 @rtype: vtkUnstructuredGrid
367 @return: Unstructured grid
368 """
369
370 return self.__output
371

  ViewVC Help
Powered by ViewVC 1.1.26