1 |
#!/usr/bin/env python |
2 |
# $Id$ |
3 |
|
4 |
import vtk |
5 |
import sys, os, re |
6 |
import getopt |
7 |
|
8 |
(opts, args) = getopt.getopt(sys.argv[1:], |
9 |
"d:f:ph", |
10 |
["dirname=", "fnamestem=", "preproc", "help"], |
11 |
) |
12 |
|
13 |
def usage(): |
14 |
print "Usage:" |
15 |
print " velVis.py -d <dirname> -f <fnamestem> -p -i\n" |
16 |
print " Arguments:" |
17 |
print " -d/--dirname: directory of vtk files to process (req)" |
18 |
print " -f/--fnamestem: filename stem of vtk files to process (req)" |
19 |
print " -p/--preproc: preprocess vtk files to find global vector max? (opt)" |
20 |
print " -i/--interactive: interactive use of first frame? (opt)" |
21 |
|
22 |
#dirName = '/data/raid2/matt/results/050516/m3dpData/vis' |
23 |
dirName = None |
24 |
fnameStem = None |
25 |
interactive = False |
26 |
preproc = False # preprocess to find the global max of the data |
27 |
|
28 |
for option, arg in opts: |
29 |
if option in ('-d', '--dirname'): |
30 |
dirName = arg |
31 |
elif option in ('-f', '--fnamestem'): |
32 |
fnameStem = arg |
33 |
elif option in ('-p', '--preproc'): |
34 |
preproc = True |
35 |
elif option in ('-i', '--interactive'): |
36 |
interactive = True |
37 |
elif option in ('-h', '--help'): |
38 |
usage() |
39 |
sys.exit(0) |
40 |
|
41 |
if dirName is None: |
42 |
print "You must supply a directory of vtk files to process\n" |
43 |
usage() |
44 |
sys.exit(1) |
45 |
|
46 |
if fnameStem is None: |
47 |
print "You must supply the filename stem of the files to process" |
48 |
print "The filename stem is the part of the filename without the" |
49 |
print "frame number or extension\n" |
50 |
usage() |
51 |
sys.exit(1) |
52 |
|
53 |
# now need to determine the number of files to process |
54 |
dirList = os.listdir(dirName) |
55 |
r = re.compile( "%s\\d+\\.\\w+" % fnameStem ) |
56 |
count = 0 # counter for the number of files found |
57 |
fnames = [] |
58 |
for fname in dirList: |
59 |
if r.match(fname): |
60 |
fnames.append(fname) |
61 |
count += 1 |
62 |
|
63 |
# determine the first frame number and number of frames |
64 |
fnames.sort() |
65 |
firstFile = fnames[0] |
66 |
|
67 |
r = re.compile("([a-zA-Z-])(\\d+)(\\.)(\\w+)") |
68 |
firstNum = r.findall(firstFile) |
69 |
firstNum = int(firstNum[0][1]) |
70 |
|
71 |
# grab the filename extension as well, just in case |
72 |
extn = r.findall(firstFile) |
73 |
extn = extn[0][3] |
74 |
|
75 |
# the number of frames should be equal to the count |
76 |
if interactive: |
77 |
numFrames = 1 |
78 |
mesa = False |
79 |
else: |
80 |
numFrames = count |
81 |
mesa = True |
82 |
|
83 |
# try and work out the format of the zero-padded frame number |
84 |
if count < 10: |
85 |
formatString = '"%01d"' |
86 |
elif count < 100: |
87 |
formatString = '"%02d"' |
88 |
elif count < 1000: |
89 |
formatString = '"%03d"' |
90 |
elif count < 10000: |
91 |
formatString = '"%04d"' |
92 |
elif count < 100000: |
93 |
formatString = '"%05d"' |
94 |
else: |
95 |
print "Sorry, can't handle greater than 100000 input frames" |
96 |
sys.exit(1) |
97 |
|
98 |
# use mesa if required |
99 |
if mesa: |
100 |
factGraphics = vtk.vtkGraphicsFactory() |
101 |
factGraphics.SetUseMesaClasses(1) |
102 |
|
103 |
factImage = vtk.vtkImagingFactory() |
104 |
factImage.SetUseMesaClasses(1) |
105 |
|
106 |
# perform some preprocessing to find the global max of the vector data norm |
107 |
maxNorm = 0 |
108 |
if not interactive and preproc: |
109 |
print "Preprocessing vector data" |
110 |
sys.stdout.write("Completed: ") |
111 |
for i in range(numFrames): |
112 |
frameNum = eval(formatString) % i |
113 |
reader = vtk.vtkXMLUnstructuredGridReader() |
114 |
reader.SetFileName("%s/%s%s.%s" % (dirName,fnameStem,frameNum,extn)) |
115 |
reader.Update() |
116 |
|
117 |
grid = reader.GetOutput() |
118 |
norm = grid.GetPointData().GetVectors().GetMaxNorm() |
119 |
if norm > maxNorm: |
120 |
maxNorm = norm |
121 |
|
122 |
sys.stdout.write("%3.0f%%\b\b\b\b" % (float(i)/float(numFrames), )) |
123 |
print "" |
124 |
|
125 |
for i in range(firstNum, numFrames+firstNum): |
126 |
|
127 |
frameNum = eval(formatString) % i |
128 |
reader = vtk.vtkXMLUnstructuredGridReader() |
129 |
reader.SetFileName("%s/%s%s.%s" % (dirName,fnameStem,frameNum,extn)) |
130 |
reader.Update() |
131 |
|
132 |
print "Processing %s" % fnames[i] |
133 |
|
134 |
grid = reader.GetOutput() |
135 |
|
136 |
# grab the model centre and bounds |
137 |
centre = grid.GetCenter() |
138 |
bounds = grid.GetBounds() |
139 |
|
140 |
# grab the norm of the vectors |
141 |
norm = vtk.vtkVectorNorm() |
142 |
norm.SetInput(grid) |
143 |
|
144 |
if not preproc: |
145 |
maxNorm = grid.GetPointData().GetVectors().GetMaxNorm() |
146 |
|
147 |
# to make arrow glyphs need an arrow source |
148 |
arrow = vtk.vtkArrowSource() |
149 |
|
150 |
# the arrows are 3D glyphs so set that up now |
151 |
glyph = vtk.vtkGlyph3D() |
152 |
glyph.ScalingOn() |
153 |
glyph.SetScaleModeToScaleByScalar() |
154 |
glyph.SetColorModeToColorByScalar() |
155 |
glyph.SetVectorModeToUseVector() |
156 |
glyph.SetScaleFactor(0.1/maxNorm) |
157 |
glyph.SetInput(norm.GetOutput()) |
158 |
glyph.SetSource(arrow.GetOutput()) |
159 |
glyph.ClampingOff() |
160 |
|
161 |
# set up a stripper to speed up rendening |
162 |
stripper = vtk.vtkStripper() |
163 |
stripper.SetInput(glyph.GetOutput()) |
164 |
|
165 |
# make a lookup table for the colour map and invert it (colours look |
166 |
# better when it's inverted) |
167 |
lut = vtk.vtkLookupTable() |
168 |
refLut = vtk.vtkLookupTable() |
169 |
lut.Build() |
170 |
refLut.Build() |
171 |
for j in range(256): |
172 |
lut.SetTableValue(j, refLut.GetTableValue(255-j)) |
173 |
|
174 |
# set up the mapper |
175 |
mapper = vtk.vtkPolyDataMapper() |
176 |
mapper.SetInput(stripper.GetOutput()) |
177 |
mapper.SetScalarRange(0,maxNorm) |
178 |
mapper.SetLookupTable(lut) |
179 |
|
180 |
# set up the actor |
181 |
actor = vtk.vtkActor() |
182 |
actor.SetMapper(mapper) |
183 |
|
184 |
# set up the text properties for nice text |
185 |
font_size = 20 |
186 |
textProp = vtk.vtkTextProperty() |
187 |
textProp.SetFontSize(font_size) |
188 |
textProp.SetFontFamilyToArial() |
189 |
textProp.BoldOff() |
190 |
textProp.ItalicOff() |
191 |
textProp.ShadowOff() |
192 |
textProp.SetColor(0.0, 0.0, 0.0) |
193 |
|
194 |
# make a title |
195 |
title = vtk.vtkTextMapper() |
196 |
title.SetInput("Velocity flow vectors in mantle convection") |
197 |
|
198 |
# make the title text use the text properties |
199 |
titleProp = title.GetTextProperty() |
200 |
titleProp.ShallowCopy(textProp) |
201 |
titleProp.SetJustificationToCentered() |
202 |
titleProp.SetVerticalJustificationToTop() |
203 |
titleProp.BoldOn() |
204 |
|
205 |
# make the actor for the title |
206 |
titleActor = vtk.vtkTextActor() |
207 |
titleActor.SetMapper(title) |
208 |
titleActor.GetPositionCoordinate().SetCoordinateSystemToNormalizedDisplay() |
209 |
titleActor.GetPositionCoordinate().SetValue(0.5, 0.95) |
210 |
|
211 |
# make a frame counter |
212 |
counter = vtk.vtkTextMapper() |
213 |
counter.SetInput("frame: %d" % i) |
214 |
|
215 |
# make the counter use the text properties |
216 |
counterProp = counter.GetTextProperty() |
217 |
counterProp.ShallowCopy(textProp) |
218 |
counterProp.SetJustificationToLeft() |
219 |
counterProp.SetVerticalJustificationToTop() |
220 |
counterProp.SetFontSize(14) |
221 |
|
222 |
# make the actor for the frame counter |
223 |
counterActor = vtk.vtkTextActor() |
224 |
counterActor.SetMapper(counter) |
225 |
counterActor.GetPositionCoordinate().SetCoordinateSystemToNormalizedDisplay() |
226 |
counterActor.GetPositionCoordinate().SetValue(0.05, 0.8) |
227 |
|
228 |
# use a scalar bar |
229 |
scalarBar = vtk.vtkScalarBarActor() |
230 |
scalarBar.SetLookupTable(lut) |
231 |
scalarBar.SetWidth(0.1) |
232 |
scalarBar.SetHeight(0.7) |
233 |
scalarBar.SetPosition(0.9, 0.2) |
234 |
scalarBar.SetTitle("|v|") |
235 |
|
236 |
# set up its title text properties |
237 |
scalarBarProp = scalarBar.GetTitleTextProperty() |
238 |
scalarBarProp.ShallowCopy(textProp) |
239 |
scalarBarProp.SetFontSize(10) |
240 |
|
241 |
# set up the label text properties |
242 |
scalarBarTextProp = scalarBar.GetLabelTextProperty() |
243 |
scalarBarTextProp.ShallowCopy(textProp) |
244 |
scalarBarTextProp.SetFontSize(10) |
245 |
|
246 |
# put an outline around the data |
247 |
outline = vtk.vtkOutlineSource() |
248 |
outline.SetBounds(bounds) |
249 |
|
250 |
# make its mapper |
251 |
outlineMapper = vtk.vtkPolyDataMapper() |
252 |
outlineMapper.SetInput(outline.GetOutput()) |
253 |
|
254 |
# make its actor |
255 |
outlineActor = vtk.vtkActor() |
256 |
outlineActor.SetMapper(outlineMapper) |
257 |
outlineActor.GetProperty().SetColor(0,0,0) |
258 |
|
259 |
# set up the renderer and render window |
260 |
ren = vtk.vtkRenderer() |
261 |
renWin = vtk.vtkRenderWindow() |
262 |
|
263 |
renWin.SetSize(800,600) |
264 |
renWin.AddRenderer(ren) |
265 |
ren.SetBackground(1,1,1) |
266 |
|
267 |
# add the relevant actors |
268 |
ren.AddActor(actor) |
269 |
ren.AddActor(titleActor) |
270 |
ren.AddActor(counterActor) |
271 |
ren.AddActor(scalarBar) |
272 |
ren.AddActor(outlineActor) |
273 |
|
274 |
cam = ren.GetActiveCamera() |
275 |
cam.Azimuth(0) |
276 |
cam.Elevation(-90) |
277 |
cam.Zoom(1.2) |
278 |
ren.SetActiveCamera(cam) |
279 |
ren.ResetCameraClippingRange() |
280 |
|
281 |
# add some axes |
282 |
axes = vtk.vtkCubeAxesActor2D() |
283 |
axes.SetInput(grid) |
284 |
axes.SetCamera(ren.GetActiveCamera()) |
285 |
axes.SetLabelFormat("%6.4g") |
286 |
axes.SetFlyModeToOuterEdges() |
287 |
axes.SetFontFactor(0.8) |
288 |
axes.SetAxisTitleTextProperty(textProp) |
289 |
axes.SetAxisLabelTextProperty(textProp) |
290 |
axes.SetXLabel("x") |
291 |
axes.SetYLabel("y") |
292 |
axes.SetZLabel("z") |
293 |
axes.SetNumberOfLabels(5) |
294 |
axes.GetProperty().SetColor(0,0,0) |
295 |
ren.AddProp(axes) |
296 |
|
297 |
if interactive: |
298 |
# set up stuff for interactive viewing |
299 |
iren = vtk.vtkRenderWindowInteractor() |
300 |
iren.SetRenderWindow(renWin) |
301 |
|
302 |
iren.Initialize() |
303 |
renWin.Render() |
304 |
iren.Start() |
305 |
else: |
306 |
renWin.OffScreenRenderingOn() |
307 |
renWin.Render() |
308 |
|
309 |
# the WindowToImageFilter is what one uses to save the window to an |
310 |
# image file |
311 |
win2img = vtk.vtkWindowToImageFilter() |
312 |
win2img.SetInput(renWin) |
313 |
|
314 |
# set up the PNMWriter as we're saving to pnm |
315 |
writer = vtk.vtkPNMWriter() |
316 |
writer.SetFileName("%s%04d.pnm" % (fnameStem,i)) |
317 |
writer.SetInput(win2img.GetOutput()) |
318 |
writer.Write() |
319 |
|
320 |
print "Wrote %s%04d.pnm" % (fnameStem,i) |
321 |
|
322 |
# vim: expandtab shiftwidth=4: |