/[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 1077 - (show annotations)
Wed Apr 4 13:31:39 2007 UTC (13 years, 5 months ago) by jongui
File MIME type: text/x-python
File size: 12568 byte(s)
There seems to be some problems with regards to reading data directly from an ESCRIPT object using the 'setData' method in the DataCollector. Please avoid using this method at this stage.
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 which deals with the source
16 of data for the visualisation.
17
18 @attention: One 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 / ESCRIPT objects are read
24 (using 'setFileName' in a for-loop), the 'setActiveScalar' /
25 'setActiveVector' / 'setActiveTensor' have to be called after loading each
26 new file (if a specific field needs to be loaded) as all active fields
27 specified for 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 retrieves its path.
48 self.__tmp_file = tempfile.mkstemp(suffix=".xml")[1]
49 #self.__vtk_xml_reader.SetFileName(self.__tmp_file)
50
51 def __del__(self):
52 """
53 Perform some clean up of the temporary file.
54 """
55
56 if (self.__source == Source.ESCRIPT):
57 if os.access(self.__tmp_file,os.F_OK): os.unlink(self.__tmp_file)
58
59 def setFileName(self, file_name):
60 """
61 Set the source file name to read.
62
63 @type file_name: String
64 @param file_name: Name of the file to read
65 """
66
67 if(self.__source == Source.XML):
68 self.__vtk_xml_reader.SetFileName(file_name)
69
70 # Update must be called after SetFileName to make the reader
71 # up to date. Otherwise, some output values may be incorrect.
72 self.__vtk_xml_reader.Update()
73 self.__output = self.__vtk_xml_reader.GetOutput()
74 self.__get_attribute_lists()
75
76 # Count has to be larger than zero because when setFileName is
77 # called for the first time, the data set mapper has not yet been
78 # instantiated. Therefore, the range of the mapper can only be
79 # updated after the first file/source has been read.
80 if(self.__count > 0):
81 self._updateRange(None)
82
83 self.__count+=1
84
85 else:
86 raise ValueError("Source type %s does not support \
87 'setFileName'\n" % self.__source)
88
89 def setData(self,**args):
90 """
91 Create data using the <name>=<data> pairing. Assumption is made
92 that the data will be given in the appropriate format.
93
94 @bug: Reading source data directly from an ESCRIPT object is NOT
95 work properly and should NOT be used.
96 """
97
98 if self.__source == Source.ESCRIPT:
99 esys.escript.saveVTK(self.__tmp_file,**args)
100 self.__vtk_xml_reader.SetFileName(self.__tmp_file)
101 # Modified must be called for setData but NOT for
102 # setFileName. If Modified is not called, only the first file
103 # will always be displayed. The reason Modified is used is
104 # because the same temporary file name is always used
105 # (old file is overwritten). Modified MUST NOT be used in
106 # setFileName, it can cause incorrect output such as map.
107 self.__vtk_xml_reader.Modified()
108 # Update must be called after Modified. If Update is called before
109 # Modified, then the first/second image(s) may not be updated
110 # correctly.
111 self.__vtk_xml_reader.Update()
112 self.__output = self.__vtk_xml_reader.GetOutput()
113 self.__get_attribute_lists()
114 else:
115 raise ValueError("Source type %s does not support 'setData'\n" \
116 % self.__source)
117
118 def setActiveScalar(self, scalar):
119 """
120 Specify the scalar field to load.
121
122 @type scalar: String
123 @param scalar: Scalar field to load from the file.
124 """
125
126 # Check whether the specified scalar is available in either point
127 # or cell data. If not available, program exits.
128
129 # NOTE: This check is similar to the check used in _getScalarRange
130 # but is used only when a scalar attribute has been specified.
131 if scalar in self.__point_attribute['scalars']:
132 self._getOutput().GetPointData().SetActiveScalars(scalar)
133 elif scalar in self.__cell_attribute['scalars']:
134 self._getOutput().GetCellData().SetActiveScalars(scalar)
135 else:
136 print "\nERROR: No scalar called '%s' is available.\n" % scalar
137 sys.exit(1)
138
139 def setActiveVector(self, vector):
140 """
141 Specify the vector field to load.
142
143 @type vector: String
144 @param vector: Vector field to load from the file.
145 """
146
147 # Check whether the specified vector is available in either point
148 # or cell data. If not available, program exits.
149
150 # NOTE: This check is similar to the check used in _getVectorRange
151 # but is used only when a vector attribute has been specified.
152 if vector in self.__point_attribute['vectors']:
153 self._getOutput().GetPointData().SetActiveVectors(vector)
154 elif vector in self.__cell_attribute['vectors']:
155 self._getOutput().GetCellData().SetActiveVectors(vector)
156 else:
157 print "\nERROR: No vector called '%s' is available.\n" % vector
158 sys.exit(1)
159
160 def setActiveTensor(self, tensor):
161 """
162 Specify the tensor field to load.
163
164 @type tensor: String
165 @param tensor: Tensor field to load from the file.
166 """
167
168 # Check whether the specified tensor is available in either point
169 # or cell data. If not available, program exits.
170
171 # NOTE: This check is similar to the check used in _getTensorRange
172 # but is used only when a tensor attribute has been specified.
173 if tensor in self.__point_attribute['tensors']:
174 self._getOutput().GetPointData().SetActiveTensors(tensor)
175 elif tensor in self.__cell_attribute['tensors']:
176 self._getOutput().GetCellData().SetActiveTensors(tensor)
177 else:
178 print "\nERROR: No tensor called '%s' is available.\n" % tensor
179 sys.exit(0)
180
181 # 'object' is set to 'None' because some types of visualization have
182 # two different ranges that need to be updated while others only have one.
183 def _paramForUpdatingMultipleSources(self, viz_type, color_mode, mapper,
184 object = None):
185 """
186 Parameters required to update the necessary range when two or more
187 files are read.
188
189 @type viz_type: : L{VizType <constant.VizType>} constant
190 @param viz_type: Type if visualization (i.e. Map, Velocity, etc)
191 @type color_mode: L{ColorMode <constant.ColorMode>} constant
192 @param color_mode: Type of color mode
193 @type mapper: vtkDataSetMapper
194 @param mapper: Mapped data
195 @type object: vtkPolyDataAlgorith (i.e. vtkContourFilter, vtkGlyph3D, \
196 etc)
197 @param object: Poly data
198 """
199
200 self.__viz_type = viz_type
201 self.__color_mode = color_mode
202 self.__mapper = mapper
203 self.__object = object
204
205 def _updateRange(self, range):
206 """
207 Update the necessary range when two or more sources are read in.
208 """
209
210 if self.__viz_type == VizType.MAP or \
211 self.__viz_type == VizType.ELLIPSOID or \
212 self.__viz_type == VizType.CARPET:
213 self.__mapper.SetScalarRange(self._getScalarRange())
214 elif self.__viz_type == VizType.VELOCITY:
215 if self.__color_mode == ColorMode.VECTOR:
216 self.__object.SetRange(self._getVectorRange())
217 self.__mapper.SetScalarRange(self._getVectorRange())
218 elif self.__color_mode == ColorMode.SCALAR:
219 self.__object.SetRange(self._getScalarRange())
220 self.__mapper.SetScalarRange(self._getScalarRange())
221 elif self.__viz_type == VizType.CONTOUR:
222 self.__object.GenerateValues(
223 self.__object.GetNumberOfContours(),
224 self._getScalarRange()[0],
225 self._getScalarRange()[1])
226 self.__mapper.SetScalarRange(self._getScalarRange())
227 elif self.__viz_type == VizType.STREAMLINE:
228 if self.__color_mode == ColorMode.VECTOR:
229 self.__mapper.SetScalarRange(self._getVectorRange())
230 elif self.__color_mode == ColorMode.SCALAR:
231 self.__mapper.SetScalarRange(self._getScalarRange())
232
233 def __get_array_type(self, arr):
234 """
235 Return if the array type is a 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', '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(self._getOutput().GetPointData())
284 # Get all the available cell data attribute into another list.
285 self.__cell_attribute = \
286 self.__get_attribute_list(self._getOutput().GetCellData())
287
288 def _getScalarRange(self):
289 """
290 Return the scalar range.
291
292 @rtype: Two column tuple containing numbers
293 @return: Scalar range
294 """
295
296 # Check whether any scalar is available in either point or cell data.
297 # If not available, program exits.
298
299 # NOTE: This check is similar to the check used in _setActiveScalar
300 # but is used only when no scalar attribute has been specified.
301 if(len(self.__point_attribute['scalars']) != 0):
302 return self._getOutput().GetPointData().GetScalars().GetRange(-1)
303 elif(len(self.__cell_attribute['scalars']) != 0):
304 return self._getOutput().GetCellData().GetScalars().GetRange(-1)
305 else:
306 print "\nERROR: No scalar is available.\n"
307 sys.exit(1)
308
309 def _getVectorRange(self):
310 """
311 Return the vector range.
312
313 @rtype: Two column tuple containing numbers
314 @return: Vector range
315 """
316
317 # Check whether any vector is available in either point or cell data.
318 # If not available, program exits.
319
320 # NOTE: This check is similar to the check used in _setActiveVector
321 # but is used only when no vector attribute has been specified.
322
323 # NOTE: Generally GetRange(-1) returns the correct vector range.
324 # However, there are certain data sets where GetRange(-1) seems
325 # to return incorrect mimimum vector although the maximum vector is
326 # correct. As a result, the mimimum vector has been hard coded to 0.0
327 # to accommodate the incorrect cases.
328 if(len(self.__point_attribute['vectors']) != 0):
329 vector_range = \
330 self._getOutput().GetPointData().GetVectors().GetRange(-1)
331 return (0.0, vector_range[1])
332 elif(len(self.__cell_attribute['vectors']) != 0):
333 vector_range = \
334 self._getOutput().GetCellData().GetVectors().GetRange(-1)
335 return (0.0, vector_range[1])
336 else:
337 print "\nERROR: No vector is available.\n"
338 sys.exit(0)
339
340 def _getTensorRange(self):
341 """
342 Return the tensor range.
343
344 @rtype: Two column table
345 @return: Tensor range
346 """
347
348 # Check whether any tensor is available in either point or cell data.
349 # If not available, program exits.
350
351 # NOTE: This check is similar to the check used in _setActiveTensor
352 # but is used only when no tensor attribute has been specified.
353 if(len(self.__point_attribute['tensors']) != 0):
354 return self._getOutput().GetPointData().GetTensors().GetRange(-1)
355 elif(len(self.__cell_attribute['tensors']) != 0):
356 return self._getOutput().GetCellData().GetTensors().GetRange(-1)
357 else:
358 print "\nERROR: No tensor is available.\n"
359 sys.exit(1)
360
361 def _getOutput(self):
362 """
363 Return the output of the data collector.
364
365 @rtype: vtkUnstructuredGrid
366 @return: Unstructured grid
367 """
368
369 return self.__output
370

  ViewVC Help
Powered by ViewVC 1.1.26