1 | /***************************************
2 | $Header: /cvsroot/petscgraphics/tsview-ng.c,v 1.35 2004/11/30 14:35:54 hazelsct Exp $
3 |
4 | This program views the output of a time series saved using
5 | +latex+{\tt IlluMultiSave()}.
6 | +html+ <tt>IlluMultiSave()</tt>.
7 | It basically just switches between timesteps; future versions may be more
8 | interesting. The neat part of it is that it loads multiprocessor data and
9 | displays it on a single CPU.
10 | ***************************************/
11 |
12 | static char help[] = "Displays the output of of a timestep series saved using IlluMultiSave().\n\
13 | Usage:\n\
14 | \n\
15 | tsview <basename> [-no_transparency]\n\
16 | \n\
17 | Then interactively flip through the timesteps (h or ? lists commands).\n";
18 |
19 | #include "illuminator.h"
20 | #include <glade/glade.h>
21 | #include <gnome.h>
22 | #include <libgnomeui/libgnomeui.h>
23 | #include <sys/dir.h> /* For scandir(), alphasort, struct dirent */
24 | #include <libgen.h> /* For dirname(), basename() */
25 | #include <string.h> /* For strdup() */
26 |
27 | /* Build with -DDEBUG for debugging output */
28 | #undef DPRINTF
29 | #ifdef DEBUG
30 | #define DPRINTF(fmt, args...) PetscPrintf (PETSC_COMM_WORLD, "%s: " fmt, __FUNCT__, args)
31 | #else
32 | #define DPRINTF(fmt, args...)
33 | #endif
34 |
35 | /*+ Declared in illuminator.c, these give the current number of triangles on
36 | this node and corner coordinates and color information for each triangle. +*/
37 | extern int num_triangles;
38 | extern PetscScalar vertices[];
39 |
40 | GladeXML *xml;
41 | /* Filename list */
42 | int entrynum=0, total_entries=0, current_timestep;
43 | char *the_basename, *basedirname, **stepnames=NULL;
44 | double current_time;
45 |
46 | /* Window parameters and drawables */
47 | int width=0, height=0, bpp=3, nx, ny, dataview_count=1;
48 | GtkWidget *dataviews [1];
49 | guchar *rgbbuf [1] = { NULL }, scalar_rgb[120000], ternary_rgb[120000],
50 | vector_rgb[120000], shear_rgb[120000];
51 | gboolean scalar_auto_set=TRUE, ternary_auto_set=TRUE, vector_auto_set=TRUE,
52 | shear_auto_set=TRUE;
53 | double sizemag;
54 | PetscTruth transp;
55 |
56 | /* PETSc structures etc. */
57 | DA theda;
58 | Vec global;
59 | PetscScalar minmax[6] = { 0.,1., 0.,1., 0.,1. };
60 | PetscScalar scales[11]; /* 2 scalar, 2 vector, 6 ternary, 1 tensor */
61 | field_plot_type *fieldtypes;
62 | int dimensions, num_fields, current_field, *field_index, num_variables[1],
63 | **variable_indices;
64 |
65 | /* First some primary functions which do stuff, then callbacks, then main(). */
66 |
67 | #undef __FUNCT__
68 | #define __FUNCT__ "render_dataviews"
69 |
70 | void render_dataviews ()
71 | {
72 | int viewnum, nx,ny,nz, ierr;
73 |
74 | DPRINTF ("Rendering dataviews\n",0);
75 | if (dataview_count != 1)
76 | {
77 | printf ("dataview_count != 1 is not yet supported\n");
78 | exit(0);
79 | }
80 | for (viewnum=0; viewnum<dataview_count; viewnum++)
81 | {
82 | int nx,ny, xs,ys, xm,ym, i;
83 | PetscScalar minval, maxval, refmag, *global_array;
84 | GtkType type;
85 | char thestatus [100];
86 |
87 | /* (Re)allocate buffer */
88 | DPRINTF ("(Re)allocating RGB buffer\n",0);
89 | if (!(rgbbuf [viewnum] =
90 | (guchar *) realloc (rgbbuf [viewnum],
91 | bpp*width*height*sizeof(guchar)))) {
92 | printf ("ERROR: can't reallocate RGB buffer\n");
93 | exit (1); }
94 |
95 | /* Render into rgbbuf [viewnum] */
96 | ierr = DAGetInfo (theda, PETSC_NULL, &nx,&ny,PETSC_NULL,
97 | PETSC_NULL,PETSC_NULL,PETSC_NULL, PETSC_NULL,
98 | PETSC_NULL,PETSC_NULL,PETSC_NULL); CHKERRQ (ierr);
99 | ierr = DAGetCorners (theda, &xs,&ys,PETSC_NULL, &xm,&ym,PETSC_NULL);
100 | CHKERRQ (ierr);
101 | if (dimensions == 2)
102 | {
103 | char maxes [6][20];
104 |
105 | ierr = VecGetArray (global, &global_array); CHKERRQ (ierr);
106 |
107 | /* Plot with automatic or manual scaling, as appropriate */
108 | switch (fieldtypes [current_field])
109 | {
110 | case FIELD_SCALAR:
111 | if (scalar_auto_set)
112 | {
113 | auto_scale (global_array, xm*ym, num_fields, current_field,
114 | fieldtypes [current_field], 2, scales);
115 | snprintf (maxes[0], 19, "%g", scales[0]);
116 | snprintf (maxes[1], 19, "%g", scales[1]);
117 | gtk_entry_set_text (GTK_ENTRY (glade_xml_get_widget
118 | (xml, "scalar_min_entry")),
119 | maxes[0]);
120 | gtk_entry_set_text (GTK_ENTRY (glade_xml_get_widget
121 | (xml, "scalar_max_entry")),
122 | maxes[1]);
123 | }
124 | ierr = render_rgb_local_2d
125 | (rgbbuf [viewnum], width,height,width, bpp, global_array,
126 | num_fields, current_field, fieldtypes [current_field],
127 | scales, nx,ny, xs,ys, xm,ym);
128 | CHKERRQ (ierr);
129 | break;
130 |
131 | case FIELD_TERNARY:
132 | if (ternary_auto_set)
133 | {
134 | auto_scale (global_array, xm*ym, num_fields, current_field,
135 | fieldtypes [current_field], 2, scales+2);
136 | snprintf (maxes[0], 19, "%g", scales[2]);
137 | snprintf (maxes[1], 19, "%g", scales[3]);
138 | snprintf (maxes[2], 19, "%g", scales[4]);
139 | snprintf (maxes[3], 19, "%g", scales[5]);
140 | snprintf (maxes[4], 19, "%g", scales[6]);
141 | snprintf (maxes[5], 19, "%g", scales[7]);
142 | gtk_entry_set_text (GTK_ENTRY (glade_xml_get_widget
143 | (xml, "ternary_1A_entry")),
144 | maxes[0]);
145 | gtk_entry_set_text (GTK_ENTRY (glade_xml_get_widget
146 | (xml, "ternary_1B_entry")),
147 | maxes[1]);
148 | gtk_entry_set_text (GTK_ENTRY (glade_xml_get_widget
149 | (xml, "ternary_2A_entry")),
150 | maxes[2]);
151 | gtk_entry_set_text (GTK_ENTRY (glade_xml_get_widget
152 | (xml, "ternary_2B_entry")),
153 | maxes[3]);
154 | gtk_entry_set_text (GTK_ENTRY (glade_xml_get_widget
155 | (xml, "ternary_3A_entry")),
156 | maxes[4]);
157 | gtk_entry_set_text (GTK_ENTRY (glade_xml_get_widget
158 | (xml, "ternary_3B_entry")),
159 | maxes[5]);
160 | }
161 | ierr = render_rgb_local_2d
162 | (rgbbuf [viewnum], width,height,width, bpp, global_array,
163 | num_fields, current_field, fieldtypes [current_field],
164 | scales+2, nx,ny, xs,ys, xm,ym);
165 | CHKERRQ (ierr);
166 | break;
167 |
168 | case FIELD_VECTOR:
169 | if (vector_auto_set)
170 | {
171 | auto_scale (global_array, xm*ym, num_fields, current_field,
172 | fieldtypes [current_field], 2, scales+8);
173 | snprintf (maxes[0], 19, "%g", scales[9]);
174 | gtk_entry_set_text (GTK_ENTRY (glade_xml_get_widget
175 | (xml, "vector_max_entry")),
176 | maxes[0]);
177 | }
178 | ierr = render_rgb_local_2d
179 | (rgbbuf [viewnum], width,height,width, bpp, global_array,
180 | num_fields, current_field, fieldtypes [current_field],
181 | scales+8, nx,ny, xs,ys, xm,ym);
182 | CHKERRQ (ierr);
183 | break;
184 |
185 | case FIELD_TENSOR_SHEAR:
186 | if (shear_auto_set)
187 | {
188 | auto_scale (global_array, xm*ym, num_fields, current_field,
189 | fieldtypes [current_field], 2, scales+10);
190 | snprintf (maxes[0], 19, "%g", scales[10]);
191 | gtk_entry_set_text (GTK_ENTRY (glade_xml_get_widget
192 | (xml, "shear_max_entry")),
193 | maxes[0]);
194 | }
195 | ierr = render_rgb_local_2d
196 | (rgbbuf [viewnum], width,height,width, bpp, global_array,
197 | num_fields, current_field, fieldtypes [current_field],
198 | scales+10, nx,ny, xs,ys, xm,ym);
199 | CHKERRQ (ierr);
200 | break;
201 | }
202 |
203 | ierr = VecRestoreArray (global, &global_array); CHKERRQ (ierr);
204 | }
205 | else
206 | {
207 | /* Fixed negative z-direction for now */
208 | PetscScalar eye[3], dir[3] = {0, 0, -1.}, right[3] = {.5, 0., 0.};
209 | eye[0] = 0.5*(minmax[0]+minmax[1]);
210 | eye[1] = 0.5*(minmax[2]+minmax[3]);
211 | eye[2] = minmax[5] + minmax[1]-minmax[0];
212 |
213 | ierr = DATriangulate
214 | (theda, global, current_field, minmax, PETSC_DECIDE, PETSC_NULL,
215 | PETSC_NULL, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE); CHKERRQ(ierr);
216 |
217 | for (i=0; i<width*height; i++)
218 | {
219 | rgbbuf[viewnum][4*i] = 0x50;
220 | rgbbuf[viewnum][4*i+1] = 0x50;
221 | rgbbuf[viewnum][4*i+2] = 0x50;
222 | rgbbuf[viewnum][4*i+3] = 0xFF;
223 | }
224 | ierr = render_rgb_local_3d
225 | (rgbbuf [viewnum], width,height, bpp, num_triangles, vertices,
226 | eye, dir, right);
227 | for (i=0; i<width*height; i++)
228 | {
229 | guchar tmp = rgbbuf[viewnum][4*i];
230 | rgbbuf[viewnum][4*i] = rgbbuf[viewnum][4*i+2];
231 | rgbbuf[viewnum][4*i+2] = tmp;
232 | }
233 | num_triangles = 0;
234 | }
235 |
236 | /* Draw buffer onto window */
237 | DPRINTF ("Painting rgb%s buffer onto window\n", (bpp==4) ? "_32" : "");
238 | if (!dataviews [viewnum])
239 | dataviews [viewnum] = glade_xml_get_widget (xml, "plot_area");
240 | gtk_drawing_area_size (GTK_DRAWING_AREA (dataviews [viewnum]),
241 | width, height);
242 | if (bpp == 3)
243 | gdk_draw_rgb_image (dataviews [viewnum]->window,
244 | dataviews[viewnum]->style->fg_gc[GTK_STATE_NORMAL],
245 | 0, 0, width, height, GDK_RGB_DITHER_MAX,
246 | rgbbuf [viewnum], width * bpp);
247 | else if (bpp == 4)
248 | gdk_draw_rgb_32_image (dataviews [viewnum]->window,
249 | dataviews[viewnum]->style->fg_gc[GTK_STATE_NORMAL],
250 | 0, 0, width, height, GDK_RGB_DITHER_MAX,
251 | rgbbuf [viewnum], width * bpp);
252 | }
253 | }
254 |
255 |
256 | #undef __FUNCT__
257 | #define __FUNCT__ "myfilter"
258 |
259 | /*+ Little variable for myfilter() and refresh_stepnames(). +*/
260 | static char *basefilename;
261 |
262 | /*++++++++++++++++++++++++++++++++++++++
263 | This function returns non-zero for "qualifying" file names which start with
264 | the stored files' basename.time and end with
265 | +latex+{\tt .cpu0000.meta}.
266 | +html+ <tt>.cpu0000.meta</tt>.
267 | It is used as the
268 | +latex+{\tt select()} function for {\tt scandir()} in {\tt main()}.
269 | +html+ <tt>select()</tt> function for <tt>scandir()</tt> in <tt>main()</tt>.
270 |
271 | int myfilter Returns non-zero for qualifying filenames.
272 |
273 | const struct dirent *direntry Directory entry with filename to test.
274 | ++++++++++++++++++++++++++++++++++++++*/
275 |
276 | int myfilter (const struct dirent *direntry)
277 | {
278 | if ((!strncmp (direntry->d_name, basefilename, strlen(basefilename))) &&
279 | (!strncmp (direntry->d_name + strlen(basefilename), ".time", 5)))
280 | return (!strncmp (direntry->d_name + strlen(direntry->d_name) - 13,
281 | ".cpu0000.meta", 13));
282 | return 0;
283 | }
284 |
285 |
286 | void on_plot_area_expose_event (GtkWidget *widget, GdkEventExpose *event,
287 | gpointer user_data)
288 | {
289 | if (bpp == 3)
290 | gdk_draw_rgb_image (widget->window, widget->style->fg_gc[GTK_STATE_NORMAL],
291 | 0, 0, width, height, GDK_RGB_DITHER_MAX, rgbbuf [0],
292 | width * bpp);
293 | else if (bpp == 4)
294 | gdk_draw_rgb_32_image (widget->window,
295 | widget->style->fg_gc[GTK_STATE_NORMAL],
296 | 0, 0, width, height, GDK_RGB_DITHER_MAX, rgbbuf [0],
297 | width * bpp);
298 | }
299 |
300 | void on_scalar_scale_area_expose_event
301 | (GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
302 | { gdk_draw_rgb_image (widget->window, widget->style->fg_gc[GTK_STATE_NORMAL],
303 | 0, 0, 200, 200, GDK_RGB_DITHER_MAX, scalar_rgb, 600); }
304 |
305 | void on_ternary_scale_area_expose_event
306 | (GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
307 | { gdk_draw_rgb_image (widget->window, widget->style->fg_gc[GTK_STATE_NORMAL],
308 | 0, 0, 200, 200, GDK_RGB_DITHER_MAX, ternary_rgb, 600); }
309 |
310 | void on_vector_scale_area_expose_event
311 | (GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
312 | { gdk_draw_rgb_image (widget->window, widget->style->fg_gc[GTK_STATE_NORMAL],
313 | 0, 0, 200, 200, GDK_RGB_DITHER_MAX, vector_rgb, 600); }
314 |
315 | void on_shear_scale_area_expose_event
316 | (GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
317 | { gdk_draw_rgb_image (widget->window, widget->style->fg_gc[GTK_STATE_NORMAL],
318 | 0, 0, 200, 200, GDK_RGB_DITHER_MAX, shear_rgb, 600); }
319 |
320 | void on_scalar_auto_checkbutton_toggled
321 | (GtkWidget *thebutton, gpointer user_data)
322 | {
323 | scalar_auto_set = gtk_toggle_button_get_active
324 | (GTK_TOGGLE_BUTTON (thebutton));
325 | if (scalar_auto_set)
326 | {
327 | gtk_widget_set_sensitive
328 | (glade_xml_get_widget (xml, "scalar_min_label"), FALSE);
329 | gtk_widget_set_sensitive
330 | (glade_xml_get_widget (xml, "scalar_max_label"), FALSE);
331 | gtk_widget_set_sensitive
332 | (glade_xml_get_widget (xml, "scalar_min_entry"), FALSE);
333 | gtk_widget_set_sensitive
334 | (glade_xml_get_widget (xml, "scalar_max_entry"), FALSE);
335 | }
336 | else
337 | {
338 | gtk_widget_set_sensitive
339 | (glade_xml_get_widget (xml, "scalar_min_label"), TRUE);
340 | gtk_widget_set_sensitive
341 | (glade_xml_get_widget (xml, "scalar_max_label"), TRUE);
342 | gtk_widget_set_sensitive
343 | (glade_xml_get_widget (xml, "scalar_min_entry"), TRUE);
344 | gtk_widget_set_sensitive
345 | (glade_xml_get_widget (xml, "scalar_max_entry"), TRUE);
346 | }
347 | }
348 |
349 | void on_ternary_auto_checkbutton_toggled
350 | (GtkWidget *thebutton, gpointer user_data)
351 | {
352 | ternary_auto_set = gtk_toggle_button_get_active
353 | (GTK_TOGGLE_BUTTON (thebutton));
354 | if (ternary_auto_set)
355 | {
356 | gtk_widget_set_sensitive
357 | (glade_xml_get_widget (xml, "ternary_1A_label"), FALSE);
358 | gtk_widget_set_sensitive
359 | (glade_xml_get_widget (xml, "ternary_1B_label"), FALSE);
360 | gtk_widget_set_sensitive
361 | (glade_xml_get_widget (xml, "ternary_2A_label"), FALSE);
362 | gtk_widget_set_sensitive
363 | (glade_xml_get_widget (xml, "ternary_2B_label"), FALSE);
364 | gtk_widget_set_sensitive
365 | (glade_xml_get_widget (xml, "ternary_3A_label"), FALSE);
366 | gtk_widget_set_sensitive
367 | (glade_xml_get_widget (xml, "ternary_3B_label"), FALSE);
368 | gtk_widget_set_sensitive
369 | (glade_xml_get_widget (xml, "ternary_1A_entry"), FALSE);
370 | gtk_widget_set_sensitive
371 | (glade_xml_get_widget (xml, "ternary_1B_entry"), FALSE);
372 | gtk_widget_set_sensitive
373 | (glade_xml_get_widget (xml, "ternary_2A_entry"), FALSE);
374 | gtk_widget_set_sensitive
375 | (glade_xml_get_widget (xml, "ternary_2B_entry"), FALSE);
376 | gtk_widget_set_sensitive
377 | (glade_xml_get_widget (xml, "ternary_3A_entry"), FALSE);
378 | gtk_widget_set_sensitive
379 | (glade_xml_get_widget (xml, "ternary_3B_entry"), FALSE);
380 | }
381 | else
382 | {
383 | gtk_widget_set_sensitive
384 | (glade_xml_get_widget (xml, "ternary_1A_label"), TRUE);
385 | gtk_widget_set_sensitive
386 | (glade_xml_get_widget (xml, "ternary_1B_label"), TRUE);
387 | gtk_widget_set_sensitive
388 | (glade_xml_get_widget (xml, "ternary_2A_label"), TRUE);
389 | gtk_widget_set_sensitive
390 | (glade_xml_get_widget (xml, "ternary_2B_label"), TRUE);
391 | gtk_widget_set_sensitive
392 | (glade_xml_get_widget (xml, "ternary_3A_label"), TRUE);
393 | gtk_widget_set_sensitive
394 | (glade_xml_get_widget (xml, "ternary_3B_label"), TRUE);
395 | gtk_widget_set_sensitive
396 | (glade_xml_get_widget (xml, "ternary_1A_entry"), TRUE);
397 | gtk_widget_set_sensitive
398 | (glade_xml_get_widget (xml, "ternary_1B_entry"), TRUE);
399 | gtk_widget_set_sensitive
400 | (glade_xml_get_widget (xml, "ternary_2A_entry"), TRUE);
401 | gtk_widget_set_sensitive
402 | (glade_xml_get_widget (xml, "ternary_2B_entry"), TRUE);
403 | gtk_widget_set_sensitive
404 | (glade_xml_get_widget (xml, "ternary_3A_entry"), TRUE);
405 | gtk_widget_set_sensitive
406 | (glade_xml_get_widget (xml, "ternary_3B_entry"), TRUE);
407 | }
408 | }
409 |
410 | void on_vector_auto_checkbutton_toggled
411 | (GtkWidget *thebutton, gpointer user_data)
412 | {
413 | vector_auto_set = gtk_toggle_button_get_active
414 | (GTK_TOGGLE_BUTTON (thebutton));
415 | if (vector_auto_set)
416 | {
417 | gtk_widget_set_sensitive
418 | (glade_xml_get_widget (xml, "vector_max_label"), FALSE);
419 | gtk_widget_set_sensitive
420 | (glade_xml_get_widget (xml, "vector_symm_label"), FALSE);
421 | gtk_widget_set_sensitive
422 | (glade_xml_get_widget (xml, "vector_max_entry"), FALSE);
423 | gtk_widget_set_sensitive
424 | (glade_xml_get_widget (xml, "vector_symm_spinbutton"), FALSE);
425 | }
426 | else
427 | {
428 | gtk_widget_set_sensitive
429 | (glade_xml_get_widget (xml, "vector_max_label"), TRUE);
430 | gtk_widget_set_sensitive
431 | (glade_xml_get_widget (xml, "vector_symm_label"), TRUE);
432 | gtk_widget_set_sensitive
433 | (glade_xml_get_widget (xml, "vector_max_entry"), TRUE);
434 | gtk_widget_set_sensitive
435 | (glade_xml_get_widget (xml, "vector_symm_spinbutton"), TRUE);
436 | }
437 | }
438 |
439 | void on_shear_auto_checkbutton_toggled
440 | (GtkWidget *thebutton, gpointer user_data)
441 | {
442 | shear_auto_set = gtk_toggle_button_get_active
443 | (GTK_TOGGLE_BUTTON (thebutton));
444 | if (shear_auto_set)
445 | {
446 | gtk_widget_set_sensitive
447 | (glade_xml_get_widget (xml, "shear_max_label"), FALSE);
448 | gtk_widget_set_sensitive
449 | (glade_xml_get_widget (xml, "shear_max_entry"), FALSE);
450 | }
451 | else
452 | {
453 | gtk_widget_set_sensitive
454 | (glade_xml_get_widget (xml, "shear_max_label"), TRUE);
455 | gtk_widget_set_sensitive
456 | (glade_xml_get_widget (xml, "shear_max_entry"), TRUE);
457 | }
458 | }
459 |
460 | void on_scalar_min_entry_changed (GtkWidget *theentry, gpointer user_data)
461 | { G_CONST_RETURN gchar *entrytext = gtk_entry_get_text (GTK_ENTRY (theentry));
462 | sscanf (entrytext, "%lf", scales); }
463 |
464 | void on_scalar_max_entry_changed (GtkWidget *theentry, gpointer user_data)
465 | { G_CONST_RETURN gchar *entrytext = gtk_entry_get_text (GTK_ENTRY (theentry));
466 | sscanf (entrytext, "%lf", scales+1); }
467 |
468 | void on_ternary_1A_entry_changed (GtkWidget *theentry, gpointer user_data)
469 | { G_CONST_RETURN gchar *entrytext = gtk_entry_get_text (GTK_ENTRY (theentry));
470 | sscanf (entrytext, "%lf", scales+2); }
471 |
472 | void on_ternary_1B_entry_changed (GtkWidget *theentry, gpointer user_data)
473 | { G_CONST_RETURN gchar *entrytext = gtk_entry_get_text (GTK_ENTRY (theentry));
474 | sscanf (entrytext, "%lf", scales+3); }
475 |
476 | void on_ternary_2A_entry_changed (GtkWidget *theentry, gpointer user_data)
477 | { G_CONST_RETURN gchar *entrytext = gtk_entry_get_text (GTK_ENTRY (theentry));
478 | sscanf (entrytext, "%lf", scales+4); }
479 |
480 | void on_ternary_2B_entry_changed (GtkWidget *theentry, gpointer user_data)
481 | { G_CONST_RETURN gchar *entrytext = gtk_entry_get_text (GTK_ENTRY (theentry));
482 | sscanf (entrytext, "%lf", scales+5); }
483 |
484 | void on_ternary_3A_entry_changed (GtkWidget *theentry, gpointer user_data)
485 | { G_CONST_RETURN gchar *entrytext = gtk_entry_get_text (GTK_ENTRY (theentry));
486 | sscanf (entrytext, "%lf", scales+6); }
487 |
488 | void on_ternary_3B_entry_changed (GtkWidget *theentry, gpointer user_data)
489 | { G_CONST_RETURN gchar *entrytext = gtk_entry_get_text (GTK_ENTRY (theentry));
490 | sscanf (entrytext, "%lf", scales+7); }
491 |
492 | void on_vector_max_entry_changed (GtkWidget *theentry, gpointer user_data)
493 | { G_CONST_RETURN gchar *entrytext = gtk_entry_get_text (GTK_ENTRY (theentry));
494 | sscanf (entrytext, "%lf", scales+9); }
495 |
496 | void on_vector_symm_spinbutton_changed (GtkWidget *theentry,gpointer user_data)
497 | { int symmetry;
498 | G_CONST_RETURN gchar *entrytext = gtk_entry_get_text (GTK_ENTRY (theentry));
499 | sscanf (entrytext, "%d", &symmetry);
500 | /* Because this sometimes sends events with outrageous symmetry numbers */
501 | if (symmetry <= 10) {
502 | render_scale_2d (vector_rgb, 200, 200, 3, FIELD_VECTOR, symmetry);
503 | on_vector_scale_area_expose_event
504 | (glade_xml_get_widget (xml, "vector_scale_area"), NULL, user_data); }}
505 |
506 | void on_shear_max_entry_changed (GtkWidget *theentry, gpointer user_data)
507 | { G_CONST_RETURN gchar *entrytext = gtk_entry_get_text (GTK_ENTRY (theentry));
508 | sscanf (entrytext, "%lf", scales+10); }
509 |
510 | /*++++++++++++++++++++++++++++++++++++++
511 | This loads the names of the files into a long list.
512 | ++++++++++++++++++++++++++++++++++++++*/
513 |
514 | int refresh_stepnames ()
515 | {
516 | struct dirent **namelist;
517 | char *filec, *dirc;
518 | int i, ierr;
519 |
520 | filec = strdup (the_basename);
521 | dirc = strdup (the_basename);
522 | basefilename = basename (filec);
523 | basedirname = dirname (dirc);
524 |
525 | total_entries = scandir (basedirname, &namelist, myfilter, alphasort);
526 | if (!total_entries)
527 | {
528 | ierr = PetscPrintf (PETSC_COMM_WORLD, "No such files\n");
529 | CHKERRQ (ierr);
530 | return 1;
531 | }
532 | if (total_entries < 0)
533 | {
534 | ierr = PetscPrintf (PETSC_COMM_WORLD, "Error scanning directory %s\n",
535 | basedirname); CHKERRQ (ierr);
536 | ierr = PetscFinalize (); CHKERRQ(ierr);
537 | return 1;
538 | }
539 | DPRINTF ("%d eligible files:\n", total_entries);
540 |
541 | if (!(stepnames = (char **) realloc
542 | (stepnames, total_entries*sizeof (char *))))
543 | {
544 | ierr = PetscPrintf (PETSC_COMM_WORLD, "Error allocating memory\n");
545 | CHKERRQ (ierr);
546 | return 1;
547 | }
548 | for (i=0; i<total_entries; i++)
549 | {
550 | int filength = strlen(namelist[i]->d_name);
551 |
552 | stepnames [i] = (char *) malloc ((filength-12)*sizeof(char));
553 | strncpy (stepnames [i], namelist[i]->d_name, filength-13);
554 | stepnames [i] [filength-13] = '\0';
555 | free (namelist[i]);
556 | DPRINTF ("[%d] %s\n", i, stepnames [i]);
557 | CHKERRQ (ierr);
558 | }
559 |
560 | free (namelist);
561 | return 0;
562 | }
563 |
564 | void change_variable (GtkWidget *widget, gpointer user_data)
565 | {
566 | current_field = GPOINTER_TO_INT (widget);
567 | DPRINTF ("Switching to variable %d\n", current_field);
568 | render_dataviews();
569 | gtk_notebook_set_current_page
570 | (GTK_NOTEBOOK (glade_xml_get_widget (xml, "scale_notebook")),
571 | fieldtypes [current_field] >> 4);
572 | }
573 |
574 | void on_mag_spin_value_changed (GtkWidget *mag_spin, gpointer user_data) {
575 | G_CONST_RETURN gchar *entrytext;
576 | entrytext = gtk_entry_get_text (GTK_ENTRY (mag_spin));
577 | sscanf (entrytext, "%lf", &sizemag);
578 | width = (int) (minmax [1] * sizemag);
579 | height = (int) (minmax [3] * sizemag);
580 |
581 | render_dataviews();
582 | }
583 |
584 |
585 | void display_timestep (int usermetacount, char **usermetanames,
586 | char **usermetadata)
587 | {
588 | int i;
589 | static char step_buffer [20], time_buffer [20];
590 |
591 | for (i=0; i<usermetacount; i++)
592 | {
593 | if (!strncmp (usermetanames [i], "timestep", 8))
594 | sscanf (usermetadata [i], "%d", ¤t_timestep);
595 | else if (!strncmp (usermetanames [i], "time", 4))
596 | sscanf (usermetadata [i], "%lf", ¤t_time);
597 | }
598 | snprintf (step_buffer, 19, "Timestep: %d", current_timestep);
599 | gtk_label_set_text (GTK_LABEL (glade_xml_get_widget (xml, "timestep_label")),
600 | step_buffer);
601 | snprintf (time_buffer, 19, "Time: %g", current_time);
602 | gtk_label_set_text (GTK_LABEL (glade_xml_get_widget (xml, "time_label")),
603 | time_buffer);
604 |
605 | on_mag_spin_value_changed (glade_xml_get_widget (xml, "mag_spin"), NULL);
606 | }
607 |
608 |
609 | void on_save_activate (GtkWidget *widget, gpointer user_data)
610 | {
611 | int i, ierr;
612 | char **usermetanames, **usermetadata, filename [200], number[10];
613 | FILE *outppm;
614 |
615 | strncpy (filename, basedirname, 198);
616 | strcat (filename, "/");
617 | strncat (filename, stepnames [entrynum], 198 - strlen (filename));
618 | snprintf (number, 9, "-f%d", current_field);
619 | strncat (filename, number, 198 - strlen (filename));
620 | strncat (filename, ".ppm", 198 - strlen (filename));
621 |
622 | DPRINTF ("Saving image with filename %s\n", filename);
623 | if (!(outppm = fopen (filename, "w")))
624 | {
625 | PetscPrintf (PETSC_COMM_WORLD, "Error opening file %s\n", filename);
626 | return;
627 | }
628 | fprintf (outppm, "P6\n%d %d\n255\n", width, height);
629 | /* If more than 3 bytes per pixel, write just the first three (RGB) */
630 | if (bpp == 3)
631 | fwrite (rgbbuf [0], sizeof (guchar), 3*width*height, outppm);
632 | else
633 | for (i=0; i<width*height; i++)
634 | fwrite (rgbbuf [0] + i*bpp, sizeof (guchar), 3, outppm);
635 | fclose (outppm);
636 | }
637 |
638 |
639 | void on_timestep_spin_value_changed (GtkWidget *timestep_spin, gpointer user_data) {
640 | int usermetacount, ierr;
641 | G_CONST_RETURN gchar *entrytext;
642 | char **usermetanames, **usermetadata, filename [200], **field_name;
643 | GtkWidget *variable_options, *variable_menu, **variable_item;
644 |
645 | entrytext = gtk_entry_get_text (GTK_ENTRY (timestep_spin));
646 | sscanf (entrytext, "%d", &entrynum);
647 |
648 | /* Bound the entrynum between 0 and total_entries-1; -11 is the minimum of
649 | the widget (from jump), 1000001 is the maximum. */
650 | if ((entrynum < 0 && entrynum != -11) || entrynum == 1000001)
651 | entrynum = total_entries-1;
652 | if ((entrynum >= total_entries && entrynum != 1000001) || entrynum == -11)
653 | entrynum = 0;
654 | gtk_spin_button_set_value (GTK_SPIN_BUTTON (timestep_spin),
655 | (gfloat) entrynum);
656 |
657 | strncpy (filename, basedirname, 198);
658 | strcat (filename, "/");
659 | strncat (filename, stepnames [entrynum], 198 - strlen (filename));
660 |
661 | ierr = IlluMultiRead (theda, global, filename, &usermetacount,&usermetanames,
662 | &usermetadata); CHKERRQ (ierr);
663 |
664 | display_timestep (usermetacount, usermetanames, usermetadata);
665 | }
666 |
667 |
668 | void on_refresh_activate (GtkWidget *none, gpointer user_data) {
669 | if (refresh_stepnames ()) exit (1); }
670 |
671 |
672 | void on_about_activate (GtkWidget *none, gpointer user_data) {
673 | gtk_widget_show (glade_xml_get_widget (xml, "about")); }
674 |
675 |
676 | #undef __FUNCT__
677 | #define __FUNCT__ "main"
678 |
679 | /*++++++++++++++++++++++++++++++++++++++
680 | This is
681 | +latex+{\tt main()}.
682 | +html+ <tt>main()</tt>.
683 |
684 | int main It returns an int to the OS.
685 |
686 | int argc Argument count.
687 |
688 | char *argv[] Arguments.
689 | ++++++++++++++++++++++++++++++++++++++*/
690 |
691 | int main (int argc, char *argv[])
692 | {
693 | int usermetacount=0, i, ierr;
694 | char **usermetanames, **usermetadata, filename [200], **field_name;
695 | GtkWidget *variable_options, *variable_menu, **variable_item;
696 |
697 | /*+ After
698 | +latex+{\tt PETSc}
699 | +html+ <tt>PETSc</tt>
700 | and glade/GNOME initialization, it gets the list of files matching the
701 | basename. +*/
702 | ierr = PetscInitialize (&argc, &argv, (char *)0, help); CHKERRQ (ierr);
703 |
704 | if (argc<2)
705 | {
706 | ierr = PetscPrintf (PETSC_COMM_WORLD, "Usage: tsview basename\n");
707 | CHKERRQ (ierr);
708 | return 1;
709 | }
710 |
711 | #ifdef DEBUG
712 | ierr = PetscPrintf (PETSC_COMM_WORLD, "Command line:"); CHKERRQ (ierr);
713 | for (i=0; i<argc; i++)
714 | {
715 | ierr = PetscPrintf (PETSC_COMM_WORLD, " %s", argv[i]); CHKERRQ (ierr);
716 | }
717 | ierr = PetscPrintf (PETSC_COMM_WORLD, "\n"); CHKERRQ (ierr);
718 | #endif
719 |
720 | ierr = PetscOptionsHasName (PETSC_NULL, "-no_transparency", &transp);
721 | CHKERRQ (ierr);
722 | transp = !transp;
723 |
724 | /* Kludge alert! Setting argc to avoid gnome_program_init errors;
725 | fix: use GNOME arguments instead of PETSc. */
726 | argc=2;
727 |
728 | DPRINTF ("Running gnome_program_init with argc=%d\n", argc);
729 | gnome_program_init ("TSView", VERSION, LIBGNOMEUI_MODULE, argc, argv, NULL);
730 |
731 | strncpy (filename, GLADE_DIRECTORY, 187);
732 | strcat (filename, "/tsview.glade");
733 | DPRINTF ("Loading Glade file %s\n", filename);
734 | xml = glade_xml_new (filename, NULL, NULL);
735 | glade_xml_signal_autoconnect (xml);
736 |
737 | if (argc>1)
738 | the_basename = argv[1];
739 | else
740 | {
741 | /* Put in filter for .time0000000.cpu0000.meta */
742 | gtk_widget_show (glade_xml_get_widget (xml, "open_fileselect"));
743 | }
744 |
745 | DPRINTF ("Loading list of timestep names\n",0);
746 | if (refresh_stepnames ())
747 | exit (1);
748 |
749 | DPRINTF ("Loading first timestep, creating distributed array\n",0);
750 | strncpy (filename, basedirname, 198);
751 | strcat (filename, "/");
752 | strncat (filename, stepnames [0], 198 - strlen (stepnames [0]));
753 | ierr = IlluMultiLoad (filename, &theda, minmax+1,minmax+3,minmax+5,
754 | &fieldtypes, &usermetacount, &usermetanames,
755 | &usermetadata);
756 | CHKERRQ (ierr);
757 |
758 | /* Usermetadata xwidth, ywidth, zwidth override minmax in case IlluMulti
759 | version of saved data is 0.1. */
760 | DPRINTF ("Checking usermetadata for width information\n",0);
761 | for (i=0; i<usermetacount; i++)
762 | {
763 | if (!strncmp (usermetanames [i], "xwidth", 6))
764 | sscanf (usermetadata [i], "%lf", minmax+1);
765 | else if (!strncmp (usermetanames [i], "ywidth", 6))
766 | sscanf (usermetadata [i], "%lf", minmax+3);
767 | else if (!strncmp (usermetanames [i], "zwidth", 6))
768 | sscanf (usermetadata [i], "%lf", minmax+5);
769 | }
770 |
771 | DPRINTF ("Getting distributed array global vector and info\n",0);
772 | ierr = DAGetGlobalVector (theda, &global); CHKERRQ (ierr);
773 | ierr = DAGetInfo (theda, &dimensions, PETSC_NULL,PETSC_NULL,PETSC_NULL,
774 | PETSC_NULL,PETSC_NULL,PETSC_NULL, &num_fields,
775 | PETSC_NULL,PETSC_NULL,PETSC_NULL); CHKERRQ (ierr);
776 | if (dimensions == 1)
777 | SETERRQ (PETSC_ERR_ARG_OUTOFRANGE, "tsview-ng only supports 2-D or 3-D distributed arrays.")
778 | else if (dimensions == 2)
779 | bpp = 3;
780 | else
781 | bpp = 4;
782 |
783 | /* Build menu of field variables */
784 | variable_options = glade_xml_get_widget (xml, "variable_menu");
785 | gtk_option_menu_remove_menu (GTK_OPTION_MENU (variable_options));
786 | variable_menu = gtk_menu_new ();
787 | variable_item = (GtkWidget **) malloc (num_fields * sizeof (GtkWidget *));
788 | field_name = (char **) malloc (num_fields * sizeof (char *));
789 | field_index = (int *) malloc (num_fields * sizeof (int));
790 | /* For now, use scalar plots for all types in 3-D */
791 | if (dimensions == 2)
792 | field_indices (num_fields, dimensions, fieldtypes, field_index);
793 | else
794 | for (i=0; i<num_fields; i++)
795 | field_index[i] = i;
796 | DPRINTF ("Field indices:\n",0);
797 | for (i=0; i<num_fields && field_index [i] != -1; i++)
798 | {
799 | ierr = DAGetFieldName (theda, field_index [i], field_name+i);
800 | CHKERRQ (ierr);
801 | DPRINTF ("%d index %d name %s\n", i, field_index [i], field_name [i]);
802 | variable_item [i] = gtk_menu_item_new_with_label (field_name [i]);
803 | gtk_menu_append (GTK_MENU (variable_menu), variable_item [i]);
804 | gtk_signal_connect_object (GTK_OBJECT (variable_item [i]), "activate",
805 | GTK_SIGNAL_FUNC (change_variable),
806 | GINT_TO_POINTER (field_index [i]));
807 | gtk_widget_show (variable_item [i]);
808 | }
809 | gtk_option_menu_set_menu (GTK_OPTION_MENU (variable_options), variable_menu);
810 | gtk_widget_show (variable_menu);
811 | gtk_widget_show (variable_options);
812 |
813 | /* Scale images */
814 | render_scale_2d (scalar_rgb, 200, 200, 3, FIELD_SCALAR, 1);
815 | render_scale_2d (ternary_rgb, 200, 200, 3, FIELD_TERNARY, 1);
816 | render_scale_2d (vector_rgb, 200, 200, 3, FIELD_VECTOR, 1);
817 | render_scale_2d (shear_rgb, 200, 200, 3, FIELD_TENSOR_SHEAR, 1);
818 |
819 | gtk_notebook_set_current_page
820 | (GTK_NOTEBOOK (glade_xml_get_widget (xml, "scale_notebook")),
821 | fieldtypes [0] >> 4);
822 |
823 | /* Main window title */
824 | {
825 | char main_window_title[100] = "TSView: ";
826 | GtkWidget *main_window = glade_xml_get_widget (xml, "main_window");
827 |
828 | strncat (main_window_title, basename (the_basename), 90);
829 | gtk_window_set_title (GTK_WINDOW (main_window), main_window_title);
830 | gtk_widget_show (main_window);
831 | }
832 |
833 | DPRINTF ("Displaying first timestep\n",0);
834 | display_timestep (usermetacount, usermetanames, usermetadata);
835 |
836 | DPRINTF ("Running main loop\n",0);
837 | gtk_main();
838 |
839 | DPRINTF ("Finalizing and exitting.\n",0);
840 | ierr = PetscFinalize (); CHKERRQ(ierr);
841 | return 0;
842 | }