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

Last change on this file since 1373 was 1373, checked in by gah, 12 years ago

First pass at changes to visualization widgets.

nanovisview.tcl use png icons.
visviewer.tcl change to sidebar layout
molvisviewer.tcl use png icons, fixed for sidebar layout.
heightmapviewer.tcl use png icons, fixed for sidebar layout.
flowvisviewer.tcl use png icons, fixed for sidebar layout.

resultviewer.tcl recognize flow data
field.tcl recognize unirect3d mesh.
field3dresult.tcl load FlowvisViewer? component description.
panes.tcl added horizontal panes. Need cursor fix. Must specify

correct cursor from options.

unirect2d.tcl added "axisorder" tag to specify order of field data.

Changed name to Unirect2d from UniRect2d.

unirect3d.tcl added "axisorder" tag to specify order of field data.

Right now, this is a test platform for me for flow
visualizations.

File size: 13.9 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 extents [$dataobj extents]
257                        if { $extents == 3 } {
258                            set fmt "flowvis"
259                        }
260                        set w $itk_interior.field3D
261                        Rappture::Field3DResult $w -mode $fmt
262                        set _mode2widget($mode) $w
263                    }
264                }
265                default {
266                    error "can't handle [$dataobj components -dimensions] field"
267                }
268            }
269        }
270        ::Rappture::Mesh {
271            switch -- [$dataobj dimensions] {
272                2 {
273                    set mode "mesh"
274                    if {![info exists _mode2widget($mode)]} {
275                        set w $itk_interior.mesh
276                        Rappture::MeshResult $w
277                        set _mode2widget($mode) $w
278                    }
279                }
280                default {
281                    error "can't handle [$dataobj dimensions]D field"
282                }
283            }
284        }
285        ::Rappture::Table {
286            set cols [Rappture::EnergyLevels::columns $dataobj]
287            if {"" != $cols} {
288                set mode "energies"
289                if {![info exists _mode2widget($mode)]} {
290                    set w $itk_interior.energies
291                    Rappture::EnergyLevels $w
292                    set _mode2widget($mode) $w
293                }
294            }
295        }
296        ::Rappture::LibraryObj {
297            switch -- [$dataobj element -as type] {
298                string - log {
299                    set mode "log"
300                    if {![info exists _mode2widget($mode)]} {
301                        set w $itk_interior.log
302                        Rappture::TextResult $w
303                        set _mode2widget($mode) $w
304                    }
305                }
306                structure {
307                    set mode "structure"
308                    if {![info exists _mode2widget($mode)]} {
309                        set w $itk_interior.struct
310                        Rappture::DeviceResult $w
311                        set _mode2widget($mode) $w
312                    }
313                }
314                number - integer {
315                    set mode "number"
316                    if {![info exists _mode2widget($mode)]} {
317                        set w $itk_interior.number
318                        Rappture::NumberResult $w
319                        set _mode2widget($mode) $w
320                    }
321                }
322                boolean - choice {
323                    set mode "value"
324                    if {![info exists _mode2widget($mode)]} {
325                        set w $itk_interior.value
326                        Rappture::ValueResult $w
327                        set _mode2widget($mode) $w
328                    }
329                }
330            }
331        }
332        ::Rappture::Image {
333            set mode "image"
334            if {![info exists _mode2widget($mode)]} {
335                set w $itk_interior.image
336                Rappture::ImageResult $w
337                set _mode2widget($mode) $w
338            }
339        }
340        ::Rappture::Sequence {
341            set mode "sequence"
342            if {![info exists _mode2widget($mode)]} {
343                set w $itk_interior.image
344                Rappture::SequenceResult $w
345                set _mode2widget($mode) $w
346            }
347        }
348        default {
349            error "don't know how to plot <$type> data"
350        }
351    }
352
353    if {$mode != $_mode && $_mode != ""} {
354        set nactive [llength [$_mode2widget($_mode) get]]
355        if {$nactive > 0} {
356            return  ;# mixing data that doesn't mix -- ignore it!
357        }
358    }
359
360    # are we plotting in a new mode? then change widgets
361    if {$_mode2widget($mode) != [pack slaves $itk_interior]} {
362        # remove any current window
363        foreach w [pack slaves $itk_interior] {
364            pack forget $w
365        }
366        pack $_mode2widget($mode) -expand yes -fill both
367
368        set _mode $mode
369        $_dispatcher event -idle !scale
370    }
371    $_mode2widget($mode) add $dataobj $settings
372}
373
374# ----------------------------------------------------------------------
375# USAGE: _fixScale ?<eventArgs>...?
376#
377# Invoked automatically whenever a new dataset is added to fix the
378# overall scales of the viewer.  This makes the visualizer consistent
379# across all <dataobj> in this widget, so that it can plot all
380# available data.
381# ----------------------------------------------------------------------
382itcl::body Rappture::ResultViewer::_fixScale {args} {
383    if {"" != $_mode} {
384        set dlist ""
385        foreach slot $_dataslots {
386            foreach dobj $slot {
387                lappend dlist $dobj
388            }
389        }
390        eval $_mode2widget($_mode) scale $dlist
391    }
392}
393
394# ----------------------------------------------------------------------
395# USAGE: download coming
396# USAGE: download controls <downloadCommand>
397# USAGE: download now
398#
399# Clients use this method to create a downloadable representation
400# of the plot.  Returns a list of the form {ext string}, where
401# "ext" is the file extension (indicating the type of data) and
402# "string" is the data itself.
403# ----------------------------------------------------------------------
404itcl::body Rappture::ResultViewer::download {option args} {
405    if {"" == $_mode} {
406        return ""
407    }
408    return [eval $_mode2widget($_mode) download $option $args]
409}
410
411# ----------------------------------------------------------------------
412# USAGE: _xml2data <xmlobj> <path>
413#
414# Used internally to create a data object for the data at the
415# specified <path> in the <xmlobj>.
416# ----------------------------------------------------------------------
417itcl::body Rappture::ResultViewer::_xml2data {xmlobj path} {
418    set type [$xmlobj element -as type $path]
419    switch -- $type {
420        curve {
421            return [Rappture::Curve ::#auto $xmlobj $path]
422        }
423        histogram {
424            return [Rappture::Histogram ::#auto $xmlobj $path]
425        }
426        field {
427            return [Rappture::Field ::#auto $xmlobj $path]
428        }
429        mesh {
430            return [Rappture::Mesh ::#auto $xmlobj $path]
431        }
432        table {
433            return [Rappture::Table ::#auto $xmlobj $path]
434        }
435        image {
436            return [Rappture::Image ::#auto $xmlobj $path]
437        }
438        sequence {
439            return [Rappture::Sequence ::#auto $xmlobj $path]
440        }
441        string - log {
442            return [$xmlobj element -as object $path]
443        }
444        structure {
445            return [$xmlobj element -as object $path]
446        }
447        number - integer - boolean - choice {
448            return [$xmlobj element -as object $path]
449        }
450        time - status {
451            return ""
452        }
453    }
454    error "don't know how to plot <$type> data"
455}
456
457# ----------------------------------------------------------------------
458# CONFIGURATION OPTION: -width
459# ----------------------------------------------------------------------
460itcl::configbody Rappture::ResultViewer::width {
461    set w [winfo pixels $itk_component(hull) $itk_option(-width)]
462    set h [winfo pixels $itk_component(hull) $itk_option(-height)]
463    if {$w == 0 || $h == 0} {
464        pack propagate $itk_component(hull) yes
465    } else {
466        component hull configure -width $w -height $h
467        pack propagate $itk_component(hull) no
468    }
469}
470
471# ----------------------------------------------------------------------
472# CONFIGURATION OPTION: -height
473# ----------------------------------------------------------------------
474itcl::configbody Rappture::ResultViewer::height {
475    set h [winfo pixels $itk_component(hull) $itk_option(-height)]
476    set w [winfo pixels $itk_component(hull) $itk_option(-width)]
477    if {$w == 0 || $h == 0} {
478        pack propagate $itk_component(hull) yes
479    } else {
480        component hull configure -width $w -height $h
481        pack propagate $itk_component(hull) no
482    }
483}
Note: See TracBrowser for help on using the repository browser.