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 | }