source: trunk/gui/scripts/resultviewer.tcl @ 1189

Last change on this file since 1189 was 1189, checked in by gah, 16 years ago

Makefile.in:

Changed "make package" to include the build directory name

(e.g. 20081010).

gui/scripts/field.tcl

Added method "isunirect2d" to field.tcl.


gui/scripts/sequenceviewer.tcl

Added "isunirect2d" test to display surface plots in sequence.

gui/scripts/resultviewer.tcl

Changed test for contours to use new "isunirect2d" method.

packages/vizservers/nanoscale/server.c

Added experimental rotating DISPLAY variable setting for multi GPU
servers.

File size: 16.7 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: ResultViewer - plots a collection of related results
3#
4#  This widget plots a collection of results that all represent
5#  the same quantity, but for various ranges of input values.  It
6#  is normally used as part of an Analyzer, to plot the various
7#  results selected by a ResultSet.
8# ======================================================================
9#  AUTHOR:  Michael McLennan, Purdue University
10#  Copyright (c) 2004-2005  Purdue Research Foundation
11#
12#  See the file "license.terms" for information on usage and
13#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14# ======================================================================
15package require Itk
16package require Img
17
18itcl::class Rappture::ResultViewer {
19    inherit itk::Widget
20
21    itk_option define -width width Width 4i
22    itk_option define -height height Height 4i
23    itk_option define -colors colors Colors ""
24    itk_option define -clearcommand clearCommand ClearCommand ""
25    itk_option define -simulatecommand simulateCommand SimulateCommand ""
26
27    constructor {args} { # defined below }
28    destructor { # defined below }
29
30    public method add {index xmlobj path}
31    public method clear {{index ""}}
32    public method value {xmlobj}
33
34    public method plot {option args}
35    public method download {option args}
36
37    protected method _plotAdd {xmlobj {settings ""}}
38    protected method _fixScale {args}
39    protected proc _xml2data {xmlobj path}
40
41    private variable _dispatcher ""  ;# dispatchers for !events
42    private variable _mode ""        ;# current plotting mode (xy, etc.)
43    private variable _mode2widget    ;# maps plotting mode => widget
44    private variable _dataslots ""   ;# list of all data objects in this widget
45}
46
47itk::usual ResultViewer {
48    keep -background -foreground -cursor -font
49}
50
51# ----------------------------------------------------------------------
52# CONSTRUCTOR
53# ----------------------------------------------------------------------
54itcl::body Rappture::ResultViewer::constructor {args} {
55    # create a dispatcher for events
56    Rappture::dispatcher _dispatcher
57    $_dispatcher register !scale
58    $_dispatcher dispatch $this !scale \
59        [itcl::code $this _fixScale]
60
61    eval itk_initialize $args
62}
63
64# ----------------------------------------------------------------------
65# DESTRUCTOR
66# ----------------------------------------------------------------------
67itcl::body Rappture::ResultViewer::destructor {} {
68    foreach slot $_dataslots {
69        foreach obj $slot {
70            itcl::delete object $obj
71        }
72    }
73}
74
75# ----------------------------------------------------------------------
76# USAGE: add <index> <xmlobj> <path>
77#
78# Adds a new result to this result viewer at the specified <index>.
79# Data is taken from the <xmlobj> object at the <path>.
80# ----------------------------------------------------------------------
81itcl::body Rappture::ResultViewer::add {index xmlobj path} {
82    set dobj [_xml2data $xmlobj $path]
83
84    #
85    # If the index doesn't exist, then fill in empty slots and
86    # make it exist.
87    #
88    for {set i [llength $_dataslots]} {$i <= $index} {incr i} {
89        lappend _dataslots ""
90    }
91    set slot [lindex $_dataslots $index]
92    lappend slot $dobj
93    set _dataslots [lreplace $_dataslots $index $index $slot]
94
95    $_dispatcher event -idle !scale
96}
97
98# ----------------------------------------------------------------------
99# USAGE: clear ?<index>?
100#
101# Clears one or all results in this result viewer.
102# ----------------------------------------------------------------------
103itcl::body Rappture::ResultViewer::clear {{index ""}} {
104    if {"" != $index} {
105        # clear one result
106        if {$index >= 0 && $index < [llength $_dataslots]} {
107            set slot [lindex $_dataslots $index]
108            foreach dobj $slot {
109                itcl::delete object $dobj
110            }
111            set _dataslots [lreplace $_dataslots $index $index ""]
112        }
113    } else {
114        # clear all results
115        plot clear
116        foreach slot $_dataslots {
117            foreach dobj $slot {
118                itcl::delete object $dobj
119            }
120        }
121        set _dataslots ""
122    }
123}
124
125# ----------------------------------------------------------------------
126# USAGE: value <xmlobj>
127#
128# Convenience method for showing a single value.  Loads the value
129# into the widget via add/clear, then immediately plots the value.
130# This makes the widget consistent with other widgets, such as
131# the DeviceEditor, etc.
132# ----------------------------------------------------------------------
133itcl::body Rappture::ResultViewer::value {xmlobj} {
134    clear
135    if {"" != $xmlobj} {
136        add 0 $xmlobj ""
137        plot add 0 ""
138    }
139}
140
141# ----------------------------------------------------------------------
142# USAGE: plot add ?<index> <settings> <index> <settings> ...?
143# USAGE: plot clear
144#
145# Used to manipulate the contents of this viewer.  The "plot clear"
146# command clears the current viewer.  Data is still stored in the
147# widget, but the results are not shown on screen.  The "plot add"
148# command adds the data at the specified <index> to the plot.  If
149# the optional <settings> are specified, then they are applied
150# to the plot; otherwise, default settings are used.
151# ----------------------------------------------------------------------
152itcl::body Rappture::ResultViewer::plot {option args} {
153    switch -- $option {
154        add {
155            set params ""
156            foreach {index opts} $args {
157                if {$index == "params"} {
158                    set params $opts
159                    continue
160                }
161                set reset "-color autoreset"
162                set slot [lindex $_dataslots $index]
163                foreach dobj $slot {
164                    set settings ""
165                    # start with color reset, only for first object in series
166                    if {"" != $reset} {
167                        set settings $reset
168                        set reset ""
169                    }
170                    # add default settings from data object
171                    if {[catch {$dobj hints style} style] == 0} {
172                        eval lappend settings $style
173                    }
174                    if {[catch {$dobj hints type} type] == 0} {
175                        if {"" != $type} {
176                            eval lappend settings "-type $type"
177                        }
178                    }
179                    # add override settings passed in here
180                    eval lappend settings $opts
181
182                    _plotAdd $dobj $settings
183                }
184            }
185            if {"" != $params && "" != $_mode} {
186                eval $_mode2widget($_mode) parameters $params
187            }
188        }
189        clear {
190            # clear the contents of the current mode
191            if {"" != $_mode} {
192                $_mode2widget($_mode) delete
193            }
194        }
195        default {
196            error "bad option \"$option\": should be add or clear"
197        }
198    }
199}
200
201# ----------------------------------------------------------------------
202# USAGE: _plotAdd <dataobj> <settings>
203#
204# Used internally to add a <dataobj> representing some data to
205# the plot at the top of this widget.  The data is added to the
206# current plot.  Use the "clear" function to clear before adding
207# new data.
208# ----------------------------------------------------------------------
209itcl::body Rappture::ResultViewer::_plotAdd {dataobj {settings ""}} {
210    switch -- [$dataobj info class] {
211        ::Rappture::Histogram {
212            set mode "histogram"
213            if {![info exists _mode2widget($mode)]} {
214                set w $itk_interior.xy
215                Rappture::HistogramResult $w
216                set _mode2widget($mode) $w
217            }
218        }
219        ::Rappture::Curve {
220            set mode "xy"
221            if {![info exists _mode2widget($mode)]} {
222                set w $itk_interior.xy
223                Rappture::XyResult $w
224                set _mode2widget($mode) $w
225            }
226        }
227        ::Rappture::Field {
228            set dims [lindex [lsort [$dataobj components -dimensions]] end]
229            switch -- $dims {
230                1D {
231                    set mode "xy"
232                    if {![info exists _mode2widget($mode)]} {
233                        set w $itk_interior.xy
234                        Rappture::XyResult $w
235                        set _mode2widget($mode) $w
236                    }
237                }
238                2D {
239                    set mode "contour"
240                    if {![info exists _mode2widget($mode)]} {
241                        if { [$dataobj isunirect2d] } {
242                            set resultMode "heightmap"
243                        } else {
244                            set resultMode "vtk"
245                        }
246                        set w $itk_interior.contour
247                        Rappture::Field2DResult $w -mode $resultMode
248                        set _mode2widget($mode) $w
249                    }
250                }
251                3D {
252                    set mode "field3D"
253                    if {![info exists _mode2widget($mode)]} {
254                        set mesh [$dataobj mesh]
255                        set fmt [expr {("" != $mesh) ? "vtk" : "nanovis"}]
256                        set w $itk_interior.field3D
257                        Rappture::Field3DResult $w -mode $fmt
258                        set _mode2widget($mode) $w
259                    }
260                }
261                default {
262                    error "can't handle [$dataobj components -dimensions] field"
263                }
264            }
265        }
266        ::Rappture::Mesh {
267            switch -- [$dataobj dimensions] {
268                2 {
269                    set mode "mesh"
270                    if {![info exists _mode2widget($mode)]} {
271                        set w $itk_interior.mesh
272                        Rappture::MeshResult $w
273                        set _mode2widget($mode) $w
274                    }
275                }
276                default {
277                    error "can't handle [$dataobj dimensions]D field"
278                }
279            }
280        }
281        ::Rappture::Table {
282            set cols [Rappture::EnergyLevels::columns $dataobj]
283            if {"" != $cols} {
284                set mode "energies"
285                if {![info exists _mode2widget($mode)]} {
286                    set w $itk_interior.energies
287                    Rappture::EnergyLevels $w
288                    set _mode2widget($mode) $w
289                }
290            }
291        }
292        ::Rappture::LibraryObj {
293            switch -- [$dataobj element -as type] {
294                string - log {
295                    set mode "log"
296                    if {![info exists _mode2widget($mode)]} {
297                        set w $itk_interior.log
298                        Rappture::TextResult $w
299                        set _mode2widget($mode) $w
300                    }
301                }
302                structure {
303                    set mode "structure"
304                    if {![info exists _mode2widget($mode)]} {
305                        set w $itk_interior.struct
306                        Rappture::DeviceResult $w
307                        set _mode2widget($mode) $w
308                    }
309                }
310                number - integer {
311                    set mode "number"
312                    if {![info exists _mode2widget($mode)]} {
313                        set w $itk_interior.number
314                        Rappture::NumberResult $w
315                        set _mode2widget($mode) $w
316                    }
317                }
318                boolean - choice {
319                    set mode "value"
320                    if {![info exists _mode2widget($mode)]} {
321                        set w $itk_interior.value
322                        Rappture::ValueResult $w
323                        set _mode2widget($mode) $w
324                    }
325                }
326            }
327        }
328        ::Rappture::Image {
329            set mode "image"
330            if {![info exists _mode2widget($mode)]} {
331                set w $itk_interior.image
332                Rappture::ImageResult $w
333                set _mode2widget($mode) $w
334            }
335        }
336        ::Rappture::Sequence {
337            set mode "sequence"
338            if {![info exists _mode2widget($mode)]} {
339                set w $itk_interior.image
340                Rappture::SequenceResult $w
341                set _mode2widget($mode) $w
342            }
343        }
344        default {
345            error "don't know how to plot <$type> data"
346        }
347    }
348
349    if {$mode != $_mode && $_mode != ""} {
350        set nactive [llength [$_mode2widget($_mode) get]]
351        if {$nactive > 0} {
352            return  ;# mixing data that doesn't mix -- ignore it!
353        }
354    }
355
356    # are we plotting in a new mode? then change widgets
357    if {$_mode2widget($mode) != [pack slaves $itk_interior]} {
358        # remove any current window
359        foreach w [pack slaves $itk_interior] {
360            pack forget $w
361        }
362        pack $_mode2widget($mode) -expand yes -fill both
363
364        set _mode $mode
365        $_dispatcher event -idle !scale
366    }
367    $_mode2widget($mode) add $dataobj $settings
368}
369
370# ----------------------------------------------------------------------
371# USAGE: _fixScale ?<eventArgs>...?
372#
373# Invoked automatically whenever a new dataset is added to fix the
374# overall scales of the viewer.  This makes the visualizer consistent
375# across all <dataobj> in this widget, so that it can plot all
376# available data.
377# ----------------------------------------------------------------------
378itcl::body Rappture::ResultViewer::_fixScale {args} {
379    if {"" != $_mode} {
380        set dlist ""
381        foreach slot $_dataslots {
382            foreach dobj $slot {
383                lappend dlist $dobj
384            }
385        }
386        eval $_mode2widget($_mode) scale $dlist
387    }
388}
389
390# ----------------------------------------------------------------------
391# USAGE: download coming
392# USAGE: download controls <downloadCommand>
393# USAGE: download now
394#
395# Clients use this method to create a downloadable representation
396# of the plot.  Returns a list of the form {ext string}, where
397# "ext" is the file extension (indicating the type of data) and
398# "string" is the data itself.
399# ----------------------------------------------------------------------
400itcl::body Rappture::ResultViewer::download {option args} {
401    if {"" == $_mode} {
402        return ""
403    }
404    return [eval $_mode2widget($_mode) download $option $args]
405}
406
407# ----------------------------------------------------------------------
408# USAGE: _xml2data <xmlobj> <path>
409#
410# Used internally to create a data object for the data at the
411# specified <path> in the <xmlobj>.
412# ----------------------------------------------------------------------
413itcl::body Rappture::ResultViewer::_xml2data {xmlobj path} {
414    set type [$xmlobj element -as type $path]
415    switch -- $type {
416        curve {
417            return [Rappture::Curve ::#auto $xmlobj $path]
418        }
419        histogram {
420            return [Rappture::Histogram ::#auto $xmlobj $path]
421        }
422        field {
423            return [Rappture::Field ::#auto $xmlobj $path]
424        }
425        mesh {
426            return [Rappture::Mesh ::#auto $xmlobj $path]
427        }
428        table {
429            return [Rappture::Table ::#auto $xmlobj $path]
430        }
431        image {
432            return [Rappture::Image ::#auto $xmlobj $path]
433        }
434        sequence {
435            return [Rappture::Sequence ::#auto $xmlobj $path]
436        }
437        string - log {
438            return [$xmlobj element -as object $path]
439        }
440        structure {
441            return [$xmlobj element -as object $path]
442        }
443        number - integer - boolean - choice {
444            return [$xmlobj element -as object $path]
445        }
446        time - status {
447            return ""
448        }
449    }
450    error "don't know how to plot <$type> data"
451}
452
453# ----------------------------------------------------------------------
454# CONFIGURATION OPTION: -width
455# ----------------------------------------------------------------------
456itcl::configbody Rappture::ResultViewer::width {
457    set w [winfo pixels $itk_component(hull) $itk_option(-width)]
458    set h [winfo pixels $itk_component(hull) $itk_option(-height)]
459    if {$w == 0 || $h == 0} {
460        pack propagate $itk_component(hull) yes
461    } else {
462        component hull configure -width $w -height $h
463        pack propagate $itk_component(hull) no
464    }
465}
466
467# ----------------------------------------------------------------------
468# CONFIGURATION OPTION: -height
469# ----------------------------------------------------------------------
470itcl::configbody Rappture::ResultViewer::height {
471    set h [winfo pixels $itk_component(hull) $itk_option(-height)]
472    set w [winfo pixels $itk_component(hull) $itk_option(-width)]
473    if {$w == 0 || $h == 0} {
474        pack propagate $itk_component(hull) yes
475    } else {
476        component hull configure -width $w -height $h
477        pack propagate $itk_component(hull) no
478    }
479}
Note: See TracBrowser for help on using the repository browser.