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

Last change on this file since 3187 was 3187, checked in by mmc, 12 years ago

Fixed the main program to catch kill signals and program termination
and flush the log buffer before exiting. Also saves "finished" as the
last message in the log.

Fixed the logger to see if the log directory is missing and warn about
it and turn off logging (rather than crapping out or trying to create
the log directory). The specific date for the log directory (e.g.,
/data/userlogs/2012-10-19) must be created by the middleware so that all
users can share it.

Added log messages for tooltips on the output quantities, and for almost
everything in the HeightmapViewer?.

File size: 53.0 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-2012  HUBzero Foundation, LLC
13#
14#  See the file "license.terms" for information on usage and
15#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16# ======================================================================
17package require Itk
18
19option add *Analyzer.width 3.5i widgetDefault
20option add *Analyzer.height 4i widgetDefault
21option add *Analyzer.simControl "auto" widgetDefault
22option add *Analyzer.simControlBackground "" widgetDefault
23option add *Analyzer.simControlOutline gray widgetDefault
24option add *Analyzer.simControlActiveBackground #ffffcc widgetDefault
25option add *Analyzer.simControlActiveOutline black widgetDefault
26option add *Analyzer.notebookpage "about" widgetDefault
27
28option add *Analyzer.font \
29    -*-helvetica-medium-r-normal-*-12-* widgetDefault
30option add *Analyzer.codeFont \
31    -*-courier-medium-r-normal-*-12-* widgetDefault
32option add *Analyzer.textFont \
33    -*-helvetica-medium-r-normal-*-12-* widgetDefault
34option add *Analyzer.boldTextFont \
35    -*-helvetica-bold-r-normal-*-12-* widgetDefault
36
37itcl::class Rappture::Analyzer {
38    inherit itk::Widget
39
40    itk_option define -codefont codeFont Font ""
41    itk_option define -textfont textFont Font ""
42    itk_option define -boldtextfont boldTextFont Font ""
43    itk_option define -simcontrol simControl SimControl ""
44    itk_option define -simcontroloutline simControlOutline Background ""
45    itk_option define -simcontrolbackground simControlBackground Background ""
46    itk_option define -simcontrolactiveoutline simControlActiveOutline Background ""
47    itk_option define -simcontrolactivebackground simControlActiveBackground Background ""
48    itk_option define -holdwindow holdWindow HoldWindow ""
49    itk_option define -notebookpage notebookPage NotebookPage ""
50
51    constructor {tool args} { # defined below }
52    destructor { # defined below }
53
54    public method simulate {args}
55    public method reset {{when -eventually}}
56    public method load {xmlobj}
57    public method clear {{xmlobj "all"}}
58    public method download {option args}
59
60    protected method _plot {args}
61    protected method _reorder {comps}
62    protected method _autoLabel {xmlobj path title cntVar}
63    protected method _fixResult {}
64    protected method _fixResultSet {args}
65    protected method _fixSize {}
66    protected method _fixSimControl {}
67    protected method _fixNotebook {}
68    protected method _simState {state args}
69    protected method _simOutput {message}
70    protected method _resultTooltip {}
71    protected method _isPdbTrajectory {data}
72    protected method _isLammpsTrajectory {data}
73    protected method _pdbToSequence {xmlobj path id child data}
74    protected method _lammpsToSequence {xmlobj path id child data}
75    protected method _trajToSequence {xmlobj {path ""}}
76
77    private variable _tool ""          ;# belongs to this tool
78    private variable _appName ""       ;# Name of application
79    private variable _control "manual" ;# start mode
80    private variable _resultset ""     ;# ResultSet object with all results
81    private variable _pages 0          ;# number of pages for result sets
82    private variable _label2page       ;# maps output label => result set
83    private variable _label2desc       ;# maps output label => description
84    private variable _label2item       ;# maps output label => output.xxx item
85    private variable _lastlabel ""     ;# label of last example loaded
86    private variable _plotlist ""      ;# items currently being plotted
87
88    private common job                 ;# array var used for blt::bgexec jobs
89}
90
91itk::usual Analyzer {
92    keep -background -cursor foreground -font
93}
94
95# ----------------------------------------------------------------------
96# CONSTRUCTOR
97# ----------------------------------------------------------------------
98itcl::body Rappture::Analyzer::constructor {tool args} {
99    set _tool $tool
100
101    # use this to store all simulation results
102    set _resultset [Rappture::ResultSet ::#auto]
103    $_resultset notify add $this [itcl::code $this _fixResultSet]
104
105    # widget settings...
106    itk_option add hull.width hull.height
107    pack propagate $itk_component(hull) no
108
109    frame $itk_interior.simol -borderwidth 1 -relief flat
110    pack $itk_interior.simol -fill x
111
112    itk_component add simbg {
113        frame $itk_interior.simol.simbg -borderwidth 0
114    } {
115        usual
116        rename -background -simcontrolcolor simControlColor Color
117    }
118    pack $itk_component(simbg) -expand yes -fill both
119
120    set simtxt [$tool xml get tool.action.label]
121    if {"" == $simtxt} {
122        set simtxt "Simulate"
123    }
124    itk_component add simulate {
125        button $itk_component(simbg).simulate -text $simtxt \
126            -command [itcl::code $this simulate]
127    } {
128        usual
129        rename -highlightbackground -simcontrolcolor simControlColor Color
130    }
131    pack $itk_component(simulate) -side left -padx 4 -pady 4
132
133    # BE CAREFUL: Shift focus when we click on "Simulate".
134    #   This shifts focus away from input widgets and causes them to
135    #   finalize and log any pending changes.  A better way would be
136    #   to have the "sync" operation finalize/sync, but this works
137    #   for now.
138    bind $itk_component(simulate) <ButtonPress> {focus %W}
139
140    # if there's a hub url, then add "About" and "Questions" links
141    set _appName [$_tool xml get tool.id]
142    set url [Rappture::Tool::resources -huburl]
143    if {"" != $url && "" != $_appName} {
144        itk_component add hubcntls {
145            frame $itk_component(simbg).hubcntls
146        } {
147            usual
148            rename -background -simcontrolcolor simControlColor Color
149        }
150        pack $itk_component(hubcntls) -side right -padx 4
151
152        itk_component add icon {
153            label $itk_component(hubcntls).icon -image [Rappture::icon ask] \
154                -highlightthickness 0
155        } {
156            usual
157            ignore -highlightthickness
158            rename -background -simcontrolcolor simControlColor Color
159        }
160        pack $itk_component(icon) -side left
161
162        itk_component add about {
163            button $itk_component(hubcntls).about -text "About this tool" \
164                -command [list Rappture::filexfer::webpage \
165                              "$url/tools/$_appName"]
166        } {
167            usual
168            ignore -font
169            rename -background -simcontrolcolor simControlColor Color
170            rename -highlightbackground -simcontrolcolor simControlColor Color
171        }
172        pack $itk_component(about) -side top -anchor w
173
174        itk_component add questions {
175            button $itk_component(hubcntls).questions -text Questions? \
176                -command [list Rappture::filexfer::webpage \
177                              "$url/resources/$_appName/questions"]
178        } {
179            usual
180            ignore -font
181            rename -background -simcontrolcolor simControlColor Color
182            rename -highlightbackground -simcontrolcolor simControlColor Color
183        }
184        pack $itk_component(questions) -side top -anchor w
185    }
186
187    itk_component add simstatus {
188        text $itk_component(simbg).simstatus -borderwidth 0 \
189            -highlightthickness 0 -height 1 -width 1 -wrap none \
190            -state disabled
191    } {
192        usual
193        ignore -highlightthickness
194        rename -background -simcontrolcolor simControlColor Color
195        rename -font -textfont textFont Font
196    }
197    pack $itk_component(simstatus) -side left -expand yes -fill x
198
199    $itk_component(simstatus) tag configure popup \
200        -underline 1 -foreground blue
201
202    $itk_component(simstatus) tag bind popup \
203        <Enter> {%W configure -cursor center_ptr}
204    $itk_component(simstatus) tag bind popup \
205        <Leave> {%W configure -cursor ""}
206    $itk_component(simstatus) tag bind popup \
207        <ButtonPress> {after idle {Rappture::Tooltip::tooltip show %W}}
208
209
210    itk_component add notebook {
211        Rappture::Notebook $itk_interior.nb
212    }
213    pack $itk_interior.nb -expand yes -fill both
214
215    # ------------------------------------------------------------------
216    # ABOUT PAGE
217    # ------------------------------------------------------------------
218    set w [$itk_component(notebook) insert end about]
219
220    Rappture::Scroller $w.info -xscrollmode off -yscrollmode auto
221    pack $w.info -expand yes -fill both -padx 4 -pady 20
222    itk_component add toolinfo {
223        text $w.info.text -width 1 -height 1 -wrap word \
224            -borderwidth 0 -highlightthickness 0
225    } {
226        usual
227        ignore -borderwidth -relief
228        rename -font -textfont textFont Font
229    }
230    $w.info contents $w.info.text
231
232    # ------------------------------------------------------------------
233    # SIMULATION PAGE
234    # ------------------------------------------------------------------
235    set w [$itk_component(notebook) insert end simulate]
236    frame $w.cntls
237    pack $w.cntls -side bottom -fill x -pady 12
238    frame $w.cntls.sep -background black -height 1
239    pack $w.cntls.sep -side top -fill x
240
241    itk_component add abort {
242        button $w.cntls.abort -text "Abort" \
243            -command [itcl::code $_tool abort]
244    }
245    pack $itk_component(abort) -side left -expand yes -padx 4 -pady 4
246
247    Rappture::Scroller $w.info -xscrollmode auto -yscrollmode auto
248    pack $w.info -expand yes -fill both -padx 4 -pady 4
249    itk_component add runinfo {
250        text $w.info.text -width 1 -height 1 -wrap none \
251            -borderwidth 0 -highlightthickness 0 \
252            -state disabled
253    } {
254        usual
255        ignore -borderwidth -relief
256        rename -font -codefont codeFont Font
257    }
258    $w.info contents $w.info.text
259
260    itk_component add progress {
261        Rappture::Progress $w.progress
262    }
263
264    # ------------------------------------------------------------------
265    # ANALYZE PAGE
266    # ------------------------------------------------------------------
267    set w [$itk_component(notebook) insert end analyze]
268
269    frame $w.top
270    pack $w.top -side top -fill x -pady 8
271    label $w.top.l -text "Result:" -font $itk_option(-font)
272    pack $w.top.l -side left
273
274    itk_component add viewselector {
275        Rappture::Combobox $w.top.sel -width 10 -editable no
276    } {
277        usual
278        rename -font -textfont textFont Font
279    }
280    pack $itk_component(viewselector) -side left -expand yes -fill x
281    bind $itk_component(viewselector) <<Value>> [itcl::code $this _fixResult]
282    bind $itk_component(viewselector) <Enter> \
283        [itcl::code $this download coming]
284
285    Rappture::Tooltip::for $itk_component(viewselector) \
286        "@[itcl::code $this _resultTooltip]"
287
288    $itk_component(viewselector) choices insert end \
289        --- "---"
290
291    itk_component add download {
292        button $w.top.dl -image [Rappture::icon download] -anchor e \
293            -borderwidth 1 -relief flat -overrelief raised \
294            -command [itcl::code $this download start $w.top.dl]
295    }
296    pack $itk_component(download) -side right -padx {4 0}
297    bind $itk_component(download) <Enter> \
298        [itcl::code $this download coming]
299
300    $itk_component(viewselector) choices insert end \
301        @download [Rappture::filexfer::label download]
302
303    if {[Rappture::filexfer::enabled]} {
304        Rappture::Tooltip::for $itk_component(download) "Downloads the current result to a new web browser window on your desktop.  From there, you can easily print or save results.
305
306NOTE:  Your web browser must allow pop-ups from this site.  If your output does not appear, look for a 'pop-up blocked' message and enable pop-ups."
307    } else {
308        Rappture::Tooltip::for $itk_component(download) "Saves the current result to a file on your desktop."
309    }
310
311    itk_component add results {
312        Rappture::Panes $w.pane -sashwidth 1 -sashrelief solid -sashpadding {4 0}
313    }
314    pack $itk_component(results) -expand yes -fill both
315    set f [$itk_component(results) pane 0]
316
317    itk_component add resultpages {
318        Rappture::Notebook $f.nb
319    }
320    pack $itk_component(resultpages) -expand yes -fill both
321
322    set f [$itk_component(results) insert end -fraction 0.1]
323    itk_component add resultselector {
324        Rappture::ResultSelector $f.rsel -resultset $_resultset \
325            -settingscommand [itcl::code $this _plot]
326    }
327    pack $itk_component(resultselector) -expand yes -fill both
328    bind $itk_component(resultselector) <<Layout>> [itcl::code $this _fixSize]
329    bind $itk_component(results) <Configure> [itcl::code $this _fixSize]
330
331    eval itk_initialize $args
332
333    $itk_component(runinfo) tag configure ERROR -foreground red
334    $itk_component(runinfo) tag configure text -font $itk_option(-textfont)
335
336    #
337    # Load up tool info on the first page.
338    #
339    $itk_component(toolinfo) tag configure title \
340        -font $itk_option(-boldtextfont)
341
342    set mesg [$tool xml get tool.title]
343    if {"" != $mesg} {
344        $itk_component(toolinfo) insert end $mesg title
345        $itk_component(toolinfo) insert end "\n\n"
346    }
347
348    set mesg [$tool xml get tool.about]
349    if {"" != $mesg} {
350        $itk_component(toolinfo) insert end $mesg
351    }
352    $itk_component(toolinfo) configure -state disabled
353    $itk_component(notebook) current about
354
355    # tool can run on "manual" (default) or "auto"
356    set cntl [$tool xml get tool.control]
357    if {"" == $cntl} {
358        set cntl [$tool xml get tool.control.type]
359    }
360    if {"" != $cntl} {
361        set _control $cntl
362    }
363
364    # reset everything to a clean state
365    reset
366}
367
368# ----------------------------------------------------------------------
369# DESTRUCTOR
370# ----------------------------------------------------------------------
371itcl::body Rappture::Analyzer::destructor {} {
372    after cancel [itcl::code $this simulate]
373    $_resultset notify remove $this
374    itcl::delete object $_resultset
375}
376
377# ----------------------------------------------------------------------
378# USAGE: simulate ?-ifneeded?
379# USAGE: simulate ?<path1> <value1> <path2> <value2> ...?
380#
381# Kicks off the simulator by executing the tool.command associated
382# with the tool.  If any arguments are specified, they are used to
383# set parameters for the simulation.  While the simulation is running,
384# it shows status.  When the simulation is finished, it switches
385# automatically to "analyze" mode and shows the results.
386# ----------------------------------------------------------------------
387itcl::body Rappture::Analyzer::simulate {args} {
388    if {$args == "-ifneeded"} {
389        # check to see if simulation is really needed
390        $_tool sync
391        if {[$_resultset contains [$_tool xml object]]
392              && ![string equal $_control "manual-resim"]} {
393            # not needed -- show results and return
394            $itk_component(notebook) current analyze
395            return
396        }
397        set args ""
398    }
399
400    # simulation is needed -- go to simulation page
401    $itk_component(notebook) current simulate
402
403    # no progress messages yet
404    pack forget $itk_component(progress)
405    lappend args -output [itcl::code $this _simOutput]
406
407    _simState off
408    $itk_component(runinfo) configure -state normal
409    $itk_component(runinfo) delete 1.0 end
410    $itk_component(runinfo) insert end "Running simulation...\n\n" text
411    $itk_component(runinfo) configure -state disabled
412
413    # if the hold window is set, then put up a busy cursor
414    if {$itk_option(-holdwindow) != ""} {
415        blt::busy hold $itk_option(-holdwindow)
416        raise $itk_component(hull)
417    }
418
419    # execute the job
420    foreach {status result} [eval $_tool run $args] break
421
422    # if job was aborted, then allow simulation again
423    if {$result == "ABORT"} {
424        _simState on "Aborted"
425    }
426
427    # load results from run.xml into analyzer
428    if {$status == 0 && $result != "ABORT"} {
429        set status [catch {load $result} result]
430    }
431
432    # back to normal
433    if {$itk_option(-holdwindow) != ""} {
434        blt::busy release $itk_option(-holdwindow)
435    }
436    $itk_component(abort) configure -state disabled
437
438    if {$status != 0} {
439        $itk_component(runinfo) configure -state normal
440        $itk_component(runinfo) delete 1.0 end
441        $itk_component(runinfo) insert end "Problem launching job:\n\n" text
442        _simOutput $result
443        $itk_component(runinfo) configure -state disabled
444        $itk_component(runinfo) see 1.0
445
446        # Try to create a support ticket for this error.
447        # It may be a real problem.
448        if {[Rappture::bugreport::shouldReport for jobs]} {
449            set ::errorInfo "\n\n== RAPPTURE INPUT ==\n[$_tool xml xml]"
450            Rappture::bugreport::register "Problem launching job:\n$result"
451            Rappture::bugreport::attachment [$_tool xml xml]
452            Rappture::bugreport::send
453        }
454    } else {
455        $itk_component(notebook) current analyze
456    }
457
458    # do this last -- after _simOutput above
459    pack forget $itk_component(progress)
460}
461
462# ----------------------------------------------------------------------
463# USAGE: reset ?-eventually|-now?
464#
465# Used to reset the analyzer whenever the input to a simulation has
466# changed.  Sets the mode back to "simulate", so the user has to
467# simulate again to see the output.  If the <start> option is set
468# to "auto", the simulation is invoked immediately.
469# ----------------------------------------------------------------------
470itcl::body Rappture::Analyzer::reset {{when -eventually}} {
471    if {$when == "-eventually"} {
472        after cancel [list catch [itcl::code $this reset -now]]
473        after idle [list catch [itcl::code $this reset -now]]
474        return
475    }
476
477    # check to see if simulation is really needed
478    $_tool sync
479    if {![$_resultset contains [$_tool xml object]]
480          || [string equal $_control "manual-resim"]} {
481        # if control mode is "auto", then simulate right away
482        if {[string match auto* $_control]} {
483            # auto control -- don't need button
484            pack forget $itk_interior.simol
485
486            after cancel [itcl::code $this simulate]
487            after idle [itcl::code $this simulate]
488        } else {
489            _simState on "new input parameters"
490        }
491    } else {
492        _simState off
493    }
494}
495
496# ----------------------------------------------------------------------
497# USAGE: load <xmlobj>
498#
499# Loads the data from the given <xmlobj> into the appropriate results
500# sets.  If necessary, new results sets are created to store the data.
501# ----------------------------------------------------------------------
502itcl::body Rappture::Analyzer::load {xmlobj} {
503    # only show the last result? then clear first
504    if {[$_tool xml get tool.analyzer] == "last"} {
505        clear
506    }
507
508    $_resultset add $xmlobj
509
510    # NOTE: Adding will trigger a !change event on the ResultSet
511    # object, which will trigger calls to _fixResultSet to add
512    # the results to display.
513}
514
515# ----------------------------------------------------------------------
516# USAGE: clear ?<xmlobj>?
517#
518# Discards one or more results previously loaded into the analyzer.
519# If an <xmlobj> is specified, then that one result is cleared.
520# Otherwise, all results are cleared.
521# ----------------------------------------------------------------------
522itcl::body Rappture::Analyzer::clear {{xmlobj "all"}} {
523    if {$xmlobj eq "" || $xmlobj eq "all"} {
524        $_resultset clear
525    } else {
526        $_resultset clear $xmlobj
527    }
528
529    # NOTE: Clearing will trigger a !change event on the ResultSet
530    # object, which will trigger calls to _fixResultSet to clean up
531    # the results being displayed.
532}
533
534# ----------------------------------------------------------------------
535# USAGE: download coming
536# USAGE: download controls <downloadCommand>
537# USAGE: download start ?widget?
538# USAGE: download now ?widget?
539#
540# Spools the current result so the user can download it.
541# ----------------------------------------------------------------------
542itcl::body Rappture::Analyzer::download {option args} {
543    set title [$itk_component(viewselector) value]
544    set page [$itk_component(viewselector) translate $title]
545
546    switch -- $option {
547        coming {
548            #
549            # Warn result that a download is coming, in case
550            # it needs to take a screen snap.
551            #
552            if {![regexp {^(|@download|---)$} $page]} {
553                set f [$itk_component(resultpages) page $page]
554                $f.rviewer download coming
555            }
556        }
557        controls {
558            # no controls for this download yet
559            return ""
560        }
561        start {
562            set widget $itk_component(download)
563            if {[llength $args] > 0} {
564                set widget [lindex $args 0]
565                if {[catch {winfo class $widget}]} {
566                    set widget $itk_component(download)
567                }
568            }
569            #
570            # See if this download has any controls.  If so, then
571            # post them now and let the user continue the download
572            # after selecting a file format.
573            #
574            if {$page != ""} {
575                set ext ""
576                set f [$itk_component(resultpages) page $page]
577                set arg [itcl::code $this download now $widget]
578                set popup [$f.rviewer download controls $arg]
579                if {"" != $popup} {
580                    $popup activate $widget below
581                } else {
582                    download now $widget
583                }
584            } else {
585                # this shouldn't happen
586                set file error.html
587                set data "<h1>Not Found</h1>There is no result selected."
588            }
589        }
590        now {
591            set widget $itk_component(download)
592            if {[llength $args] > 0} {
593                set widget [lindex $args 0]
594                if {[catch {winfo class $widget}]} {
595                    set widget $itk_component(download)
596                }
597            }
598            #
599            # Perform the actual download.
600            #
601            if {$page != ""} {
602                set ext ""
603                set f [$itk_component(resultpages) page $page]
604                set item [$itk_component(viewselector) value]
605                set result [$f.rviewer download now $widget $_appName $item]
606                if { $result == "" } {
607                    return;                # User cancelled the download.
608                }
609                foreach {ext data} $result break
610                if {"" == $ext} {
611                    if {"" != $widget} {
612                        Rappture::Tooltip::cue $widget \
613                            "Can't download this result."
614                    }
615                    return
616                }
617                regsub -all {[\ -\/\:-\@\{-\~]} $title {} title
618                set file "$title$ext"
619            } else {
620                # this shouldn't happen
621                set file error.html
622                set data "<h1>Not Found</h1>There is no result selected."
623            }
624
625            Rappture::Logger::log download [$itk_component(viewselector) value]
626            set mesg [Rappture::filexfer::download $data $file]
627            if {[string length $mesg] > 0} {
628                Rappture::Tooltip::cue $widget $mesg
629            }
630        }
631        default {
632            error "bad option \"$option\": should be coming, controls, now, start"
633        }
634    }
635}
636
637# ----------------------------------------------------------------------
638# USAGE: _plot ?<index> <options> <index> <options>...?
639#
640# Used internally to update the plot shown in the current result
641# viewer whenever the resultselector settings have changed.  Causes the
642# desired results to show up on screen.
643# ----------------------------------------------------------------------
644itcl::body Rappture::Analyzer::_plot {args} {
645    set _plotlist $args
646
647    set page [$itk_component(viewselector) value]
648    set page [$itk_component(viewselector) translate $page]
649    if {"" != $page} {
650        set f [$itk_component(resultpages) page $page]
651        $f.rviewer plot clear
652        foreach {index opts} $_plotlist {
653            $f.rviewer plot add $index $opts
654        }
655    }
656}
657
658# ----------------------------------------------------------------------
659# USAGE: _reorder <compList>
660#
661# Used internally to change the order of a series of output components
662# found in the <output> section.  Moves the <log> elements to the end
663# and returns the updated list.
664# ----------------------------------------------------------------------
665itcl::body Rappture::Analyzer::_reorder {comps} {
666    set i 0
667    set max [llength $comps]
668    while {$i < $max} {
669        set c [lindex $comps $i]
670        if {[string match log* $c]} {
671            set comps [lreplace $comps $i $i]
672            lappend comps $c
673            incr max -1
674        } else {
675            incr i
676        }
677    }
678    return $comps
679}
680
681# ----------------------------------------------------------------------
682# USAGE: _autoLabel <xmlobj> <path> <title> <cntVar>
683#
684# Used internally to check for an about.label property at the <path>
685# in <xmlobj>.  If this object doesn't have a label, then one is
686# supplied using the given <title>.  The <cntVar> is an array of
687# counters in the calling scopes for titles that have been used
688# in the past.  This is used to create titles like "Plot #2" the
689# second time it is encountered.
690#
691# The <xmlobj> is updated so that the label is inserted directly in
692# the tree.
693# ----------------------------------------------------------------------
694itcl::body Rappture::Analyzer::_autoLabel {xmlobj path title cntVar} {
695    upvar $cntVar counters
696
697    set group [$xmlobj get $path.about.group]
698    set label [$xmlobj get $path.about.label]
699    if {"" == $label} {
700        # no label -- make one up using the title specified
701        if {![info exists counters($group-$title)]} {
702            set counters($group-$title) 1
703            set label $title
704        } else {
705            set label "$title (#[incr counters($group-$title)])"
706        }
707        $xmlobj put $path.about.label $label
708    } else {
709        # handle the case of two identical labels in <output>
710        if {![info exists counters($group-$label)]} {
711            set counters($group-$label) 1
712        } else {
713            set label "$label (#[incr counters($group-$label)])"
714            $xmlobj put $path.about.label $label
715        }
716    }
717    return $label
718}
719
720# ----------------------------------------------------------------------
721# USAGE: _fixResult
722#
723# Used internally to change the result page being displayed whenever
724# the user selects a page from the results combobox.
725# ----------------------------------------------------------------------
726itcl::body Rappture::Analyzer::_fixResult {} {
727    set name [$itk_component(viewselector) value]
728    set page ""
729    if {"" != $name} {
730        set page [$itk_component(viewselector) translate $name]
731    }
732    if {$page == "@download"} {
733        # put the combobox back to its last value
734        $itk_component(viewselector) component entry configure -state normal
735        $itk_component(viewselector) component entry delete 0 end
736        $itk_component(viewselector) component entry insert end $_lastlabel
737        $itk_component(viewselector) component entry configure -state disabled
738        # perform the actual download
739        download start $itk_component(download)
740    } elseif {$page == "---"} {
741        # put the combobox back to its last value
742        $itk_component(viewselector) component entry configure -state normal
743        $itk_component(viewselector) component entry delete 0 end
744        $itk_component(viewselector) component entry insert end $_lastlabel
745        $itk_component(viewselector) component entry configure -state disabled
746    } elseif {$page != ""} {
747        set _lastlabel $name
748        set win [winfo toplevel $itk_component(hull)]
749        blt::busy hold $win
750        $itk_component(resultpages) current $page
751
752        set f [$itk_component(resultpages) page $page]
753        $f.rviewer plot clear
754        eval $f.rviewer plot add $_plotlist
755        blt::busy release [winfo toplevel $itk_component(hull)]
756        Rappture::Logger::log output $_label2item($name)
757        Rappture::Tooltip::for $itk_component(viewselector) \
758            "@[itcl::code $this _resultTooltip]" -log $_label2item($name)
759    }
760}
761
762# ----------------------------------------------------------------------
763# USAGE: _fixResultSet ?<eventData>...?
764#
765# Used internally to react to changes within the ResultSet.  When a
766# result is added, a new result viewer is created for the object.
767# When all results are cleared, the viewers are deleted.
768# ----------------------------------------------------------------------
769itcl::body Rappture::Analyzer::_fixResultSet {args} {
770    array set eventData $args
771    switch -- $eventData(op) {
772        add {
773            set xmlobj $eventData(what)
774
775            # Detect molecule elements that contain trajectory data
776            # and convert to sequences.
777            _trajToSequence $xmlobj output
778
779            # Go through the analysis and find all result sets.
780            set haveresults 0
781            foreach item [_reorder [$xmlobj children output]] {
782                switch -glob -- $item {
783                    log* {
784                        _autoLabel $xmlobj output.$item "Output Log" counters
785                    }
786                    number* {
787                        _autoLabel $xmlobj output.$item "Number" counters
788                    }
789                    integer* {
790                        _autoLabel $xmlobj output.$item "Integer" counters
791                    }
792                    string* {
793                        _autoLabel $xmlobj output.$item "String" counters
794                    }
795                    histogram* - curve* - field* {
796                        _autoLabel $xmlobj output.$item "Plot" counters
797                    }
798                    drawing* {
799                        _autoLabel $xmlobj output.$item "Drawing" counters
800                    }
801                    structure* {
802                        _autoLabel $xmlobj output.$item "Structure" counters
803                    }
804                    table* {
805                        _autoLabel $xmlobj output.$item "Energy Levels" counters
806                    }
807                    sequence* {
808                        _autoLabel $xmlobj output.$item "Sequence" counters
809                    }
810                }
811                set label [$xmlobj get output.$item.about.group]
812                if {"" == $label} {
813                    set label [$xmlobj get output.$item.about.label]
814                }
815
816                set hidden [$xmlobj get output.$item.hide]
817                set hidden [expr {"" != $hidden && $hidden}]
818
819                if {"" != $label && !$hidden} {
820                    set haveresults 1
821                }
822            }
823
824            # if there are any valid results, add them to the resultset
825            if {$haveresults} {
826                set index [$_resultset get simnum $xmlobj]
827
828                # add each result to a result viewer
829                foreach item [_reorder [$xmlobj children output]] {
830                    set label [$xmlobj get output.$item.about.group]
831                    if {"" == $label} {
832                        set label [$xmlobj get output.$item.about.label]
833                    }
834                    set hidden [$xmlobj get output.$item.hide]
835                    if { $hidden == "" } {
836                        set hidden 0
837                    }
838                    if {"" != $label && !$hidden} {
839                        if {![info exists _label2page($label)]} {
840                            set name "page[incr _pages]"
841                            set page [$itk_component(resultpages) \
842                                insert end $name]
843                            set _label2page($label) $page
844                            set _label2item($label) output.$item
845                            set _label2desc($label) \
846                                [$xmlobj get output.$item.about.description]
847                            Rappture::ResultViewer $page.rviewer
848                            pack $page.rviewer -expand yes -fill both -pady 4
849
850                            set end [$itk_component(viewselector) \
851                                choices index -value ---]
852                            if {$end < 0} {
853                                set end "end"
854                            }
855                            $itk_component(viewselector) choices insert $end \
856                                $name $label
857                        }
858
859                        # add/replace the latest result into this viewer
860                        set page $_label2page($label)
861
862                        if {![info exists reset($page)]} {
863                            $page.rviewer clear $index
864                            set reset($page) 1
865                        }
866                        $page.rviewer add $index $xmlobj output.$item
867                    }
868                }
869            }
870
871            # show the first page by default
872            set max [$itk_component(viewselector) choices size]
873            for {set i 0} {$i < $max} {incr i} {
874                set first [$itk_component(viewselector) choices get -label $i]
875                if {$first != ""} {
876                    set page [$itk_component(viewselector) choices get -value $i]
877                    set char [string index $page 0]
878                    if {$char != "@" && $char != "-"} {
879                        $itk_component(resultpages) current $page
880                        $itk_component(viewselector) value $first
881                        set _lastlabel $first
882                        break
883                    }
884                }
885            }
886        }
887        clear {
888            if {$eventData(what) ne "all"} {
889                # delete this result from all viewers
890                array set params $eventData(what)
891                foreach label [array names _label2page] {
892                    set page $_label2page($label)
893                    $page.rviewer clear $params(simnum)
894                }
895            }
896
897            if {[$_resultset size] == 0} {
898                # reset the size of the controls area
899                set ht [winfo height $itk_component(results)]
900                set cntlht [$itk_component(resultselector) size -controlarea]
901                set frac [expr {double($cntlht)/$ht}]
902                $itk_component(results) fraction end $frac
903
904                foreach label [array names _label2page] {
905                    set page $_label2page($label)
906                    destroy $page.rviewer
907                }
908                $itk_component(resultpages) delete -all
909                set _pages 0
910
911                $itk_component(viewselector) value ""
912                $itk_component(viewselector) choices delete 0 end
913                catch {unset _label2page}
914                catch {unset _label2item}
915                catch {unset _label2desc}
916                set _plotlist ""
917
918                $itk_component(viewselector) choices insert end --- "---"
919                $itk_component(viewselector) choices insert end \
920                    @download [Rappture::filexfer::label download]
921                set _lastlabel ""
922            }
923
924            # fix Simulate button state
925            reset
926        }
927        default {
928            error "don't know how to handle op \"$eventData(op)\""
929        }
930    }
931}
932
933# ----------------------------------------------------------------------
934# USAGE: _fixSize
935#
936# Used internally to change the size of the result set area whenever
937# a new control appears.  Adjusts the size available for the result
938# set up to some maximum.
939# ----------------------------------------------------------------------
940itcl::body Rappture::Analyzer::_fixSize {} {
941    set ht [winfo height $itk_component(results)]
942    if {$ht <= 1} { set ht [winfo reqheight $itk_component(results)] }
943    set cntlht [$itk_component(resultselector) size -controlarea]
944    set frac [expr {double($cntlht)/$ht}]
945
946    if {$frac < 0.4} {
947        $itk_component(results) fraction end $frac
948    }
949    _fixSimControl
950}
951
952# ----------------------------------------------------------------------
953# USAGE: _simState <boolean> ?<message>? ?<settings>?
954#
955# Used internally to change the "Simulation" button on or off.
956# If the <boolean> is on, then any <message> and <settings> are
957# displayed as well.  If the <boolean> is off, then only display
958# the message. The <message> is a note to the user about
959# what will be simulated, and the <settings> are a list of
960# tool parameter settings of the form {path1 val1 path2 val2 ...}.
961# When these are in place, the next Simulate operation will use
962# these settings.  This helps fill in missing data values.
963# ----------------------------------------------------------------------
964itcl::body Rappture::Analyzer::_simState {state args} {
965    if {$state} {
966        $itk_interior.simol configure \
967            -background $itk_option(-simcontrolactiveoutline)
968        configure -simcontrolcolor $itk_option(-simcontrolactivebackground)
969
970        $itk_component(abort) configure -state disabled
971        $itk_component(simulate) configure -state normal \
972            -command [itcl::code $this simulate]
973
974        #
975        # If there's a special message, then put it up next to the button.
976        #
977        set mesg [lindex $args 0]
978        if {"" != $mesg} {
979            $itk_component(simstatus) configure -state normal
980            $itk_component(simstatus) delete 1.0 end
981            $itk_component(simstatus) insert end $mesg
982
983            #
984            # If there are any settings, then install them in the
985            # "Simulate" button.  Also, pop them up as a tooltip
986            # for the message.
987            #
988            set settings [lindex $args 1]
989            if {[llength $settings] > 0} {
990                $itk_component(simulate) configure \
991                    -command [eval itcl::code $this simulate $settings]
992
993                set details ""
994                foreach {path val} $settings {
995                    set str [$_tool xml get $path.about.label]
996                    if {"" == $str} {
997                        set str [$_tool xml element -as id $path]
998                    }
999                    append details "$str = $val\n"
1000                }
1001                set details [string trim $details]
1002
1003                Rappture::Tooltip::for $itk_component(simstatus) $details
1004                $itk_component(simstatus) insert end " "
1005                $itk_component(simstatus) insert end "(details...)" popup
1006            }
1007            $itk_component(simstatus) configure -state disabled
1008        }
1009    } else {
1010        if {"" != $itk_option(-simcontrolbackground)} {
1011            set simcbg $itk_option(-simcontrolbackground)
1012        } else {
1013            set simcbg $itk_option(-background)
1014        }
1015        $itk_interior.simol configure \
1016            -background $itk_option(-simcontroloutline)
1017        configure -simcontrolcolor $simcbg
1018
1019        $itk_component(simulate) configure -state disabled
1020        $itk_component(abort) configure -state normal
1021
1022        $itk_component(simstatus) configure -state normal
1023        $itk_component(simstatus) delete 1.0 end
1024        set mesg [lindex $args 0]
1025        if {"" != $mesg} {
1026            $itk_component(simstatus) insert end $mesg
1027        }
1028        $itk_component(simstatus) configure -state disabled
1029    }
1030}
1031
1032# ----------------------------------------------------------------------
1033# USAGE: _simOutput <message>
1034#
1035# Invoked automatically whenever output comes in while running the
1036# tool.  Extracts any =RAPPTURE-???=> messages from the output and
1037# sends the output to the display.  For example, any
1038# =RAPPTURE-PROGRESS=> message pops up the progress meter and updates
1039# it to show the latest progress message.  This is useful for
1040# long-running tools, to let the user know how much longer the
1041# simulation will take.
1042# ----------------------------------------------------------------------
1043itcl::body Rappture::Analyzer::_simOutput {message} {
1044    #
1045    # Scan through and pick out any =RAPPTURE-PROGRESS=> messages first.
1046    #
1047    while {[regexp -indices \
1048               {=RAPPTURE-PROGRESS=> *([-+]?[0-9]+) +([^\n]*)(\n|$)} $message \
1049                match percent mesg]} {
1050
1051        foreach {i0 i1} $percent break
1052        set percent [string range $message $i0 $i1]
1053
1054        foreach {i0 i1} $mesg break
1055        set mesg [string range $message $i0 $i1]
1056
1057        pack $itk_component(progress) -fill x -padx 10 -pady 10
1058        $itk_component(progress) settings -percent $percent -message $mesg
1059
1060        foreach {i0 i1} $match break
1061        set message [string replace $message $i0 $i1]
1062    }
1063
1064    #
1065    # Break up the remaining lines according to =RAPPTURE-ERROR=> messages.
1066    # Show errors in a special color.
1067    #
1068    $itk_component(runinfo) configure -state normal
1069
1070    while {[regexp -indices \
1071               {=RAPPTURE-([a-zA-Z]+)=>([^\n]*)(\n|$)} $message \
1072                match type mesg]} {
1073
1074        foreach {i0 i1} $match break
1075        set first [string range $message 0 [expr {$i0-1}]]
1076        if {[string length $first] > 0} {
1077            $itk_component(runinfo) insert end $first
1078            $itk_component(runinfo) insert end \n
1079        }
1080
1081        foreach {t0 t1} $type break
1082        set type [string range $message $t0 $t1]
1083        foreach {m0 m1} $mesg break
1084        set mesg [string range $message $m0 $m1]
1085        if {[string length $mesg] > 0 && $type != "RUN"} {
1086            $itk_component(runinfo) insert end $mesg $type
1087            $itk_component(runinfo) insert end \n $type
1088        }
1089
1090        set message [string range $message [expr {$i1+1}] end]
1091    }
1092
1093    if {[string length $message] > 0} {
1094        $itk_component(runinfo) insert end $message
1095        if {[$itk_component(runinfo) get end-2char] != "\n"} {
1096            $itk_component(runinfo) insert end "\n"
1097        }
1098        $itk_component(runinfo) see end
1099    }
1100    $itk_component(runinfo) configure -state disabled
1101}
1102
1103# ----------------------------------------------------------------------
1104# USAGE: _resultTooltip
1105#
1106# Used internally to build the tooltip string displayed for the
1107# result selector.  If the current page has an associated description,
1108# then it is displayed beneath the result.
1109#
1110# Returns the string for the tooltip.
1111# ----------------------------------------------------------------------
1112itcl::body Rappture::Analyzer::_resultTooltip {} {
1113    set tip ""
1114    set name [$itk_component(viewselector) value]
1115    if {[info exists _label2desc($name)] &&
1116         [string length $_label2desc($name)] > 0} {
1117        append tip "$_label2desc($name)\n\n"
1118    }
1119    if {[array size _label2page] > 1} {
1120        append tip "Use this control to display other output results."
1121    }
1122    return $tip
1123}
1124
1125# ----------------------------------------------------------------------
1126# USAGE: _fixSimControl
1127#
1128# Used internally to add or remove the simulation control at the
1129# top of the analysis area.  This is controlled by the -simcontrol
1130# option.
1131# ----------------------------------------------------------------------
1132itcl::body Rappture::Analyzer::_fixSimControl {} {
1133    switch -- $itk_option(-simcontrol) {
1134        on {
1135            pack $itk_interior.simol -fill x -before $itk_interior.nb
1136        }
1137        off {
1138            pack forget $itk_interior.simol
1139        }
1140        auto {
1141            #
1142            # If we have two or more radiodials, then there is a
1143            # chance of encountering a combination of parameters
1144            # with no data, requiring simulation.
1145            #
1146            if {[$itk_component(resultselector) size -controls] >= 2} {
1147                pack $itk_interior.simol -fill x -before $itk_interior.nb
1148            } else {
1149                pack forget $itk_interior.simol
1150            }
1151        }
1152        default {
1153            error "bad value \"$itk_option(-simcontrol)\": should be on, off, auto"
1154        }
1155    }
1156}
1157
1158# ----------------------------------------------------------------------
1159# USAGE: _fixNotebook
1160#
1161# Used internally to switch the active notebook page
1162# ----------------------------------------------------------------------
1163itcl::body Rappture::Analyzer::_fixNotebook {} {
1164    switch -- $itk_option(-notebookpage) {
1165        about {
1166            $itk_component(notebook) current about
1167        }
1168        simulate {
1169            $itk_component(notebook) current simulate
1170        }
1171        analyze {
1172            $itk_component(notebook) current analyze
1173        }
1174        default {
1175            error "bad value \"$itk_option(-notebookpage)\": should be about, simulate, analyze"
1176        }
1177    }
1178}
1179
1180# ----------------------------------------------------------------------
1181# USAGE: _isPdbTrajectory <data>
1182#
1183# Used internally to determine whether pdb or lammps data represents a
1184# trajectory rather than a single frame
1185# ----------------------------------------------------------------------
1186itcl::body Rappture::Analyzer::_isPdbTrajectory {data} {
1187    if { [llength $data]  == 0 } {
1188        return 0
1189    }
1190    set nModels 0
1191    foreach line $data {
1192        if { [string match "MODEL*" $line] }  {
1193            incr nModels
1194            if { $nModels > 1 } {
1195                # Stop if more than one model found.  No need to count them
1196                # all.
1197                return 1
1198            }
1199        }
1200    }
1201    return 0
1202}
1203
1204# ----------------------------------------------------------------------
1205# USAGE: _isLammpsTrajectory <data>
1206#
1207# Used internally to determine whether pdb or lammps data represents a
1208# trajectory rather than a single frame
1209# ----------------------------------------------------------------------
1210itcl::body Rappture::Analyzer::_isLammpsTrajectory { data } {
1211    if { [llength $data]  == 0 } {
1212        return 0
1213    }
1214    set nModels 0
1215    foreach line $data {
1216        if { [regexp {^[\t ]*ITEM:[ \t]+TIMESTEP} $line] } {
1217            incr nModels
1218            if { $nModels > 1 } {
1219                # Stop if more than one model found.  No need to count them
1220                # all.
1221                return 1
1222            }
1223        }
1224    }
1225    return 0
1226}
1227
1228# ----------------------------------------------------------------------
1229# USAGE: _pdbToSequence <xmlobj> ?<path>?
1230#
1231# If the molecule element is a trajectory, delete the original
1232# and create a sequence of individual molecules.
1233# Used internally to detect any molecule output elements that contain
1234# trajectory data.  Trajectories will be converted into sequences of
1235# individual molecules.  All other elements will be unaffected. Scans
1236# the entire xml tree if a starting path is not specified.
1237# ----------------------------------------------------------------------
1238itcl::body Rappture::Analyzer::_pdbToSequence {xmlobj path id child data} {
1239
1240    set seqLabel [$xmlobj get ${child}.about.label]
1241    set descr    [$xmlobj get ${child}.about.description]
1242    set formula  [$xmlobj get ${child}.components.molecule.formula]
1243    $xmlobj remove $child
1244
1245    set sequence  $path.sequence($id)
1246    $xmlobj put ${sequence}.about.label $seqLabel
1247    $xmlobj put ${sequence}.about.description $descr
1248    $xmlobj put ${sequence}.index.label "Frame"
1249
1250    set frameNum 0
1251    set numLines [llength $data]
1252    for { set i 0 } { $i < $numLines } { incr i } {
1253        set line [lindex $data $i]
1254        set line [string trim $line]
1255        set contents {}
1256        if { [string match "MODEL*" $line] } {
1257            # Save the contents until we get an ENDMDL record.
1258            for {} { $i < $numLines } { incr i } {
1259                set line [lindex $data $i]
1260                set line [string trim $line]
1261                if { $line == "" } {
1262                    continue;           # Skip blank lines.
1263                }
1264                if { [string match "ENDMDL*" $line] } {
1265                    break;
1266                }
1267                append contents $line\n
1268            }
1269            set frame ${sequence}.element($frameNum)
1270            $xmlobj put ${frame}.index $frameNum
1271           
1272            set molecule ${frame}.structure.components.molecule
1273            $xmlobj put ${molecule}.pdb $contents
1274            $xmlobj put ${molecule}.formula $formula
1275            incr frameNum
1276        }
1277    }
1278}
1279
1280# ----------------------------------------------------------------------
1281# USAGE: _lammpsToSequence <xmlobj> ?<path>?
1282#
1283# If the molecule element is a trajectory, delete the original
1284# and create a sequence of individual molecules.
1285# Used internally to detect any molecule output elements that contain
1286# trajectory data.  Trajectories will be converted into sequences of
1287# individual molecules.  All other elements will be unaffected. Scans
1288# the entire xml tree if a starting path is not specified.
1289# ----------------------------------------------------------------------
1290itcl::body Rappture::Analyzer::_lammpsToSequence {xmlobj path id child data} {
1291
1292    set seqLabel [$xmlobj get ${child}.about.label]
1293    set descr    [$xmlobj get ${child}.about.description]
1294    set typemap  [$xmlobj get ${child}.components.molecule.lammpstypemap]
1295    $xmlobj remove $child
1296
1297    set sequence ${path}.sequence($id)
1298    $xmlobj put ${sequence}.about.label $seqLabel
1299    $xmlobj put ${sequence}.about.description $descr
1300    $xmlobj put ${sequence}.index.label "Frame"
1301
1302    set frameNum 0
1303    set frameContents ""
1304    set inModel 0
1305    foreach line $data {
1306        set line [string trim $line]
1307        if { $line == "" } {
1308            continue;                   # Skip blank lines
1309        }
1310        if {[regexp {^[\t ]*ITEM:[ \t]+ATOMS} $line] } {
1311            if { $inModel && $frameContents != "" } {
1312                set frame ${sequence}.element($frameNum)
1313                $xmlobj put ${frame}.index $frameNum
1314               
1315                set molecule ${frame}.structure.components.molecule
1316                $xmlobj put ${molecule}.lammps $frameContents
1317                $xmlobj put ${molecule}.lammpstypemap $typemap
1318               
1319                incr frameNum
1320                set frameContents ""
1321            }
1322            set inModel 1
1323        } elseif { [scan $line "%d %d %f %f %f" a b c d e] == 5 } {
1324            if { !$inModel } {
1325                puts stderr "found \"$line\" without previous \"ITEM: ATOMS\""
1326                set inModel 1
1327            }
1328            append frameContents $line\n
1329        }
1330    }
1331    if { $frameContents != "" } {
1332        set frame ${sequence}.element($frameNum)
1333        $xmlobj put ${frame}.index $frameNum
1334       
1335        set molecule ${frame}.structure.components.molecule
1336        $xmlobj put ${molecule}.lammps $frameContents
1337        $xmlobj put ${molecule}.lammpstypemap $typemap
1338    }
1339}
1340
1341# ----------------------------------------------------------------------
1342# USAGE: _trajToSequence <xmlobj> ?<path>?
1343#
1344#       Check for PDB and LAMMPS trajectories in molecule data and rewrite
1345#       the individual models as a sequence of molecules.  Used internally
1346#       to detect any molecule output elements that contain trajectory data.
1347#       Trajectories will be converted into sequences of individual molecules.
1348#       All other elements will be unaffected. Scans the entire xml tree if a
1349#       starting path is not specified. 
1350#
1351# ----------------------------------------------------------------------
1352itcl::body Rappture::Analyzer::_trajToSequence {xmlobj {path ""}} {
1353    # Remove leading dot from path, if present.
1354    if { [string index $path 0] == "." } {
1355        set path [string range $path 1 end]
1356    }
1357    # Otherwise check each child.
1358    foreach child [$xmlobj children $path] {
1359        set current ${path}.${child}
1360        if { [string match "structure*" $child] } {
1361            set isTraj [$xmlobj get ${current}.components.molecule.trajectory]
1362            if { $isTraj == "" || !$isTraj } {
1363                continue;               # Not a trajectory.
1364            }
1365            # Look for trajectory if molecule element found.  Check both pdb
1366            # data and lammps data.
1367            set type [$xmlobj element -as type $current]
1368            set id   [$xmlobj element -as id $current]
1369            set pdbdata    [$xmlobj get ${current}.components.molecule.pdb]
1370            set lammpsdata [$xmlobj get ${current}.components.molecule.lammps]
1371            if { $pdbdata != "" && $lammpsdata != "" } {
1372                puts stderr \
1373                    "found both <pdb> and <lammps> elements: picking pdb"
1374            }
1375            set pdbdata [split $pdbdata \n]
1376            set lammpsdata [split $lammpsdata \n]
1377            if { [_isPdbTrajectory $pdbdata] } {
1378                _pdbToSequence $xmlobj $path $id $current $pdbdata
1379            } elseif { [_isLammpsTrajectory $lammpsdata] } {
1380                _lammpsToSequence $xmlobj $path $id $current $lammpsdata
1381            }
1382            continue
1383        }
1384        if 0 {
1385        # Recurse over all child nodes.
1386        _trajToSequence $xmlobj $current
1387        }
1388    }
1389}
1390
1391# ----------------------------------------------------------------------
1392# CONFIGURATION OPTION: -simcontrol
1393#
1394# Controls whether or not the Simulate button is showing.  In some
1395# cases, it is not needed.
1396# ----------------------------------------------------------------------
1397itcl::configbody Rappture::Analyzer::simcontrol {
1398    _fixSimControl
1399}
1400
1401# ----------------------------------------------------------------------
1402# CONFIGURATION OPTION: -notebookpage
1403#
1404# Controls which page of the analyzer notebook is shown. It is
1405# particularly needed when using rerun, when you don't want to
1406# "simulate -ifneeded" because an actual simulation might be
1407# kicked off due to differences between tool.xml and run.xml
1408# ----------------------------------------------------------------------
1409itcl::configbody Rappture::Analyzer::notebookpage {
1410    _fixNotebook
1411}
Note: See TracBrowser for help on using the repository browser.