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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1077 - (hide annotations)
Wed Apr 4 13:31:39 2007 UTC (13 years, 6 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 jongui 1037 """
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 jongui 1075
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 jongui 1037 """
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 jongui 1043 #self.__vtk_xml_reader.SetFileName(self.__tmp_file)
50 jongui 1037
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 jongui 1043 # Update must be called after SetFileName to make the reader
71 jongui 1037 # 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 jongui 1076 raise ValueError("Source type %s does not support \
87     'setFileName'\n" % self.__source)
88 jongui 1037
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 jongui 1077
94     @bug: Reading source data directly from an ESCRIPT object is NOT
95     work properly and should NOT be used.
96 jongui 1037 """
97    
98     if self.__source == Source.ESCRIPT:
99     esys.escript.saveVTK(self.__tmp_file,**args)
100 jongui 1043 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 jongui 1037 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 jongui 1043 # '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 jongui 1037 def _paramForUpdatingMultipleSources(self, viz_type, color_mode, mapper,
184     object = None):
185 jongui 1038 """
186     Parameters required to update the necessary range when two or more
187     files are read.
188    
189 jongui 1043 @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 jongui 1038 """
199    
200 jongui 1037 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 jongui 1043 """
207     Update the necessary range when two or more sources are read in.
208     """
209    
210 jongui 1037 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 jongui 1076 # Check whether any scalar is available in either point or cell data.
297 jongui 1037 # 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