source: trunk/gui/scripts/analyzer.tcl @ 9

Last change on this file since 9 was 9, checked in by mmc, 16 years ago

Massive changes across the entire toolkit. Rearranged the
XML description to agree better with new documentation and
conventions.

Added a small start of Rappture.interface and Rappture.number
in the python directory. This is the new way of doing Rappture--
by declaring variables directly in the program, not using XML
directly at all.

File size: 12.5 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: analyzer - output area for Rappture
3#
4#  This widget acts as the output side of a Rappture application.
5#  When the input has changed, it displays a Simulate button that
6#  launches the simulation.  When a simulation is running, this
7#  area shows status.  When it is finished, the results appear
8#  in place of the button, according to the specs in the <analyze>
9#  XML data.
10# ======================================================================
11#  AUTHOR:  Michael McLennan, Purdue University
12#  Copyright (c) 2004  Purdue Research Foundation, West Lafayette, IN
13# ======================================================================
14package require Itk
15package require BLT
16
17option add *Analyzer.textFont \
18    -*-helvetica-medium-r-normal-*-*-120-* widgetDefault
19
20itcl::class Rappture::Analyzer {
21    inherit itk::Widget
22
23    itk_option define -tool tool Tool ""
24    itk_option define -device device Device ""
25    itk_option define -analysis analysis Analysis ""
26    itk_option define -holdwindow holdWindow HoldWindow ""
27
28    constructor {args} { # defined below }
29    destructor { # defined below }
30
31    public method simulate {}
32    public method reset {}
33    public method load {file}
34
35    protected method _fixResult {}
36
37    private variable _run ""           ;# results from last run
38    private variable _control "manual" ;# start mode
39    private variable _widgets          ;# maps analyze section => widget
40
41    private common job                 ;# array var used for blt::bgexec jobs
42}
43                                                                               
44itk::usual Analyzer {
45    keep -background -cursor foreground -font
46}
47
48# ----------------------------------------------------------------------
49# CONSTRUCTOR
50# ----------------------------------------------------------------------
51itcl::body Rappture::Analyzer::constructor {args} {
52    itk_component add notebook {
53        Rappture::Notebook $itk_interior.nb
54    }
55    pack $itk_interior.nb -expand yes -fill both
56
57    # ------------------------------------------------------------------
58    # SIMULATION PAGE
59    # ------------------------------------------------------------------
60    set w [$itk_component(notebook) insert end simulate]
61    frame $w.cntls
62    pack $w.cntls -side top -fill x -padx {20 2}
63
64    itk_component add simulate {
65        button $w.cntls.sim -text "Simulate" \
66            -command [itcl::code $this simulate]
67    }
68    pack $itk_component(simulate) -side left
69
70    itk_component add status {
71        label $w.cntls.info -width 1 -text "" -anchor w
72    } {
73        usual
74        rename -font -textfont textFont Font
75    }
76    pack $itk_component(status) -side left -expand yes -fill both
77
78    Rappture::Scroller $w.info -xscrollmode off -yscrollmode auto
79    pack $w.info -expand yes -fill both -padx {20 2} -pady {20 2}
80    itk_component add info {
81        text $w.info.text -width 1 -height 1 -wrap word \
82            -borderwidth 0 -highlightthickness 0 \
83            -state disabled
84    } {
85        usual
86        ignore -borderwidth -relief
87        rename -font -textfont textFont Font
88    }
89    $w.info contents $w.info.text
90
91    # ------------------------------------------------------------------
92    # ANALYZE PAGE
93    # ------------------------------------------------------------------
94    set w [$itk_component(notebook) insert end analyze]
95
96    itk_component add resultselector {
97        Rappture::Combobox $w.sel -width 30 -editable no
98    } {
99        usual
100        rename -font -textfont textFont Font
101    }
102    pack $itk_component(resultselector) -side top -fill x -padx {20 2}
103    bind $itk_component(resultselector) <<Value>> [itcl::code $this _fixResult]
104
105    itk_component add results {
106        Rappture::Notebook $w.nb
107    }
108    pack $itk_component(results) -expand yes -fill both -pady 4
109
110    eval itk_initialize $args
111    reset
112}
113
114# ----------------------------------------------------------------------
115# DESTRUCTOR
116# ----------------------------------------------------------------------
117itcl::body Rappture::Analyzer::destructor {} {
118    if {$_run != ""} {
119        itcl::delete object $_run
120    }
121}
122
123# ----------------------------------------------------------------------
124# USAGE: simulate
125#
126# If the simulation page is showing, this kicks off the simulator
127# by executing the tool.command associated with the -tool.  While
128# the simulation is running, it shows status.  When the simulation is
129# finished, it switches automatically to "analyze" mode and shows
130# the results.
131# ----------------------------------------------------------------------
132itcl::body Rappture::Analyzer::simulate {} {
133    if {[$itk_component(notebook) current] == "simulate"} {
134        $itk_component(status) configure -text "Running simulation..."
135        $itk_component(simulate) configure -text "Abort" \
136            -command {set ::Rappture::Analyzer::job(control) abort}
137
138        set job(control) ""
139        set job(error) ""
140
141        # if the hold window is set, then put up a busy cursor
142        if {$itk_option(-holdwindow) != ""} {
143            blt::busy hold $itk_option(-holdwindow)
144            raise $itk_component(hull)
145            update
146        }
147
148        # write out the driver.xml file for the tool
149        set status [catch {
150            set fid [open driver.xml w]
151            puts $fid "<?xml version=\"1.0\"?>"
152            set xml [$itk_option(-tool) xml]
153            if {$itk_option(-device) != ""} {
154                set xml2 [$itk_option(-device) xml]
155                regsub -all {&} $xml2 {\\\&} xml2
156                regsub {</run>} $xml "$xml2</run>" xml
157            }
158            puts $fid $xml
159            close $fid
160        } result]
161
162        # execute the tool using the path from the tool description
163        if {$status == 0} {
164            set cmd [$itk_option(-tool) get tool.command]
165
166            set status [catch {eval blt::bgexec \
167                ::Rappture::Analyzer::job(control) \
168                -output ::Rappture::Analyzer::job(output) \
169                -error ::Rappture::Analyzer::job(error) $cmd} result]
170        }
171
172        # read back the results from run.xml
173        if {$status == 0} {
174            set status [catch {load run.xml} result]
175        }
176
177        # back to normal
178        if {$itk_option(-holdwindow) != ""} {
179            blt::busy release $itk_option(-holdwindow)
180        }
181        $itk_component(status) configure -text ""
182        $itk_component(simulate) configure -text "Simulate" \
183            -command [itcl::code $this simulate]
184
185        # if anything went wrong, tell the user; otherwise, analyze
186        if {[regexp {^KILLED} $job(control)]} {
187            # job aborted -- do nothing
188        } elseif {$status != 0} {
189            $itk_component(info) configure -state normal
190            $itk_component(info) delete 1.0 end
191            $itk_component(info) insert end "Problem launching job:\n"
192            if {[string length $job(error)] > 0} {
193                $itk_component(info) insert end $job(error)
194            } else {
195                $itk_component(info) insert end $result
196            }
197            $itk_component(info) configure -state disabled
198        } else {
199            $itk_component(notebook) current analyze
200        }
201    }
202}
203
204# ----------------------------------------------------------------------
205# USAGE: reset
206#
207# Used to reset the analyzer whenever the input to a simulation has
208# changed.  Sets the mode back to "simulate", so the user has to
209# simulate again to see the output.  If the <start> option is set
210# to "auto", the simulation is invoked immediately.
211# ----------------------------------------------------------------------
212itcl::body Rappture::Analyzer::reset {} {
213    $itk_component(notebook) current simulate
214
215    # if control mode is "auto", then simulate right away
216    if {[string match auto* $_control]} {
217        simulate
218    }
219}
220
221# ----------------------------------------------------------------------
222# USAGE: load <file>
223#
224# Used to reset the analyzer whenever the input to a simulation has
225# changed.  Sets the mode back to "simulate", so the user has to
226# simulate again to see the output.
227# ----------------------------------------------------------------------
228itcl::body Rappture::Analyzer::load {file} {
229    # clear any old results
230    if {$_run != ""} {
231        itcl::delete object $_run
232        set _run ""
233    }
234
235    # try to load new results from the given file
236    set _run [Rappture::library $file]
237
238    # go through the analysis and create widgets to display results
239    foreach item [array names _widgets] {
240        $_widgets($item) configure -output $_run
241    }
242}
243
244# ----------------------------------------------------------------------
245# USAGE: _fixResult
246#
247# Used internally to change the result page being displayed whenever
248# the user selects a page from the results combobox.
249# ----------------------------------------------------------------------
250itcl::body Rappture::Analyzer::_fixResult {} {
251    set page [$itk_component(resultselector) value]
252    set page [$itk_component(resultselector) translate $page]
253    $itk_component(results) current $page
254}
255
256# ----------------------------------------------------------------------
257# CONFIGURATION OPTION: -tool
258#
259# Set to the Rappture::library object representing the tool being
260# run in this analyzer.
261# ----------------------------------------------------------------------
262itcl::configbody Rappture::Analyzer::tool {
263    if {![Rappture::library isvalid $itk_option(-tool)]} {
264        error "bad value \"$itk_option(-tool)\": should be Rappture::library"
265    }
266
267    $itk_component(info) configure -state normal
268    $itk_component(info) delete 1.0 end
269    $itk_component(info) insert end [$itk_option(-tool) get tool.about]
270    $itk_component(info) configure -state disabled
271}
272
273# ----------------------------------------------------------------------
274# CONFIGURATION OPTION: -device
275#
276# Set to the Rappture::library object representing the device being
277# run in this analyzer.
278# ----------------------------------------------------------------------
279itcl::configbody Rappture::Analyzer::device {
280    if {$itk_option(-device) != ""
281          && ![Rappture::library isvalid $itk_option(-device)]} {
282        error "bad value \"$itk_option(-device)\": should be Rappture::library"
283    }
284    reset
285}
286
287# ----------------------------------------------------------------------
288# CONFIGURATION OPTION: -analysis
289#
290# Set to the Rappture::library object representing the analysis that
291# should be shown in this analyzer.
292# ----------------------------------------------------------------------
293itcl::configbody Rappture::Analyzer::analysis {
294    if {![Rappture::library isvalid $itk_option(-analysis)]} {
295        error "bad value \"$itk_option(-analysis)\": should be Rappture::library"
296    }
297    set _control [$itk_option(-analysis) get control]
298
299    # go through the analysis and create widgets to display results
300    $itk_component(results) delete -all
301    catch {unset _widgets}
302
303    set counter 0
304    foreach item [$itk_option(-analysis) children] {
305        switch -glob -- $item {
306            xyplot* {
307                set name "page[incr counter]"
308                set label [$itk_option(-analysis) get $item.label]
309                if {$label == ""} { set label $name }
310
311                set page [$itk_component(results) insert end $name]
312                $itk_component(resultselector) choices insert end \
313                    $name $label
314
315                set _widgets($item) [Rappture::Xyplot $page.#auto \
316                    -layout [$itk_option(-analysis) element -flavor object $item]]
317                pack $_widgets($item) -expand yes -fill both
318            }
319            elevels* {
320                set name "page[incr counter]"
321
322                set page [$itk_component(results) insert end $name]
323                $itk_component(resultselector) choices insert end \
324                    $name "Energy Levels"
325
326                set _widgets($item) [Rappture::EnergyLevels $page.#auto \
327                    -layout [$itk_option(-analysis) element -flavor object $item]]
328                pack $_widgets($item) -expand yes -fill both
329            }
330        }
331    }
332
333    # if there is only one page, take down the selector
334    if {[$itk_component(resultselector) choices size] <= 1} {
335        pack forget $itk_component(resultselector)
336    } else {
337        pack $itk_component(resultselector) -before $itk_component(results) \
338            -side top -fill x -padx {20 2}
339    }
340
341    # show the first page by default
342    set first [$itk_component(resultselector) choices get -label 0]
343    if {$first != ""} {
344        $itk_component(results) current page1
345        $itk_component(resultselector) value $first
346    }
347}
Note: See TracBrowser for help on using the repository browser.