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

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