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

Last change on this file since 3534 was 3523, checked in by gah, 11 years ago

o Change "dataset visible" to contour3d visible". Initial cutplane visibliity

only on reset.

o Fix: Don't replot (delete/add) when switching outputs to an existing viewer

with the same list of objects to plot. Need to test this one a bit.

o Fix: for some reason "clear" on 2D (and possibly 3D) fields would fail when

you resimulated because it could not find the saved widget.

o Change in vtkisosurfaceviewer to wait 200 milliseconds if the window hasn't

been resized yet (it needs to get an image from the server before the
Tk panedwidget resizes the canvas properly. Previously it was called on
idle again and again.

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