source: branches/1.4/gui/scripts/analyzer.tcl @ 5060

Last change on this file since 5060 was 5060, checked in by ldelgass, 9 years ago

merge r5044,r5056 from trunk

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