source: trunk/gui/scripts/sequence.tcl @ 2652

Last change on this file since 2652 was 1930, checked in by gah, 14 years ago
File size: 8.6 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: sequence - represents a sequence of output results
3#
4#  This object represents a sequence of other output results.  Each
5#  element in the sequence has an index and a value.  All values in
6#  the sequence must have the same type, but they can all be curves,
7#  images, or other results.
8# ======================================================================
9#  AUTHOR:  Michael McLennan, Purdue University
10#  Copyright (c) 2004-2005  Purdue Research Foundation
11#
12#  See the file "license.terms" for information on usage and
13#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14# ======================================================================
15package require Itcl
16package require BLT
17
18namespace eval Rappture { # forward declaration }
19
20itcl::class Rappture::Sequence {
21    constructor {xmlobj path} { # defined below }
22    destructor { # defined below }
23
24    public method value {pos}
25    public method label {pos}
26    public method index {pos}
27    public method size {}
28    public method hints {{keyword ""}}
29
30    private variable _xmlobj ""  ;# ref to lib obj with sequence data
31    private variable _dataobjs   ;# maps index => data object
32    private variable _labels     ;# maps index => labels
33    private variable _indices    ;# list of sorted index values
34    private variable _hints      ;# cache of hints stored in XML
35}
36
37# ----------------------------------------------------------------------
38# CONSTRUCTOR
39# ----------------------------------------------------------------------
40itcl::body Rappture::Sequence::constructor {xmlobj path} {
41    if {![Rappture::library isvalid $xmlobj]} {
42        error "bad value \"$xmlobj\": should be LibraryObj"
43    }
44    set _xmlobj [$xmlobj element -as object $path]
45
46    #
47    # Extract data values from the element definitions.
48    #
49    foreach name [$_xmlobj children -type element] {
50        set index [$xmlobj get $path.$name.index]
51        if {"" == $index} {
52            continue
53        }
54
55        # check for an element about.label stanza
56        set elelabel [$xmlobj get $path.$name.about.label]
57
58        set ctype ""
59        set _dataobjs($index) ""
60        set _labels($index) ""
61        foreach cname [$_xmlobj children $name] {
62            set type [$xmlobj element -as type $path.$name.$cname]
63            switch -- $type {
64                index {
65                    # ignore this
66                    continue
67                }
68                about {
69                    # ignore this
70                    continue
71                }
72                curve {
73                    set obj [Rappture::Curve ::#auto $xmlobj $path.$name.$cname]
74                }
75                datatable {
76                    set obj [Rappture::DataTable ::#auto $xmlobj $path.$name.$cname]
77                }
78                histogram {
79                    set obj [Rappture::Histogram ::#auto $xmlobj $path.$name.$cname]
80                }
81                field {
82                    set obj [Rappture::Field ::#auto $xmlobj $path.$name.$cname]
83                }
84                image {
85                    set obj [Rappture::Image ::#auto $xmlobj $path.$name.$cname]
86                }
87                structure {
88                    # extract unique result set prefix
89                    scan $xmlobj "::libraryObj%d" rset
90
91                    # object rooted at x.sequence(y).element(z).structure
92                    set obj [$xmlobj element -as object $path.$name.$cname]
93
94                    # scene id (sequence id)
95                    set sceneid [$xmlobj element -as id $path]-$rset
96
97                    # sequence/element/frame number starting at 1
98                    set frameid [expr [$xmlobj element -as id $path.$name] + 1]
99
100                    # only supporting one molecule per structure at the moment
101                    # otherwise should go through all children that are molecules
102                    # and insert scene/frame data.
103                    $obj put "components.molecule.state" $frameid
104                    $obj put "components.molecule.model" $sceneid
105                }
106                default {
107                    error "don't know how to handle sequences of $type"
108                }
109            }
110            if {"" == $ctype} {
111                set ctype $type
112            }
113            if {$type == $ctype} {
114                lappend _dataobjs($index) $obj
115                set _labels($index) $elelabel
116            } else {
117                itcl::delete object $obj
118            }
119        }
120    }
121
122    #
123    # Generate a list of sorted index values.
124    #
125    set units [$xmlobj get $path.index.units]
126    if {"" != $units} {
127        # build up a list:  {10m 10} {10cm 0.1} ...
128        set vals ""
129        foreach key [array names _dataobjs] {
130            lappend vals [list $key [Rappture::Units::convert $key \
131                -context $units -to $units -units off]]
132        }
133
134        # sort according to raw values; store both values
135        set _indices [lsort -real -index 1 $vals]
136
137    } else {
138        # are the indices integers, reals, or strings?
139        set how -integer
140        foreach key [array names _dataobjs] {
141            if {[regexp {^[0-9]+[eE][-+]?[0-9]+|([0-9]+)?\.[0-9]+([eE][-+]?[0-9]+)?$} $key]} {
142                set how -real
143                break
144            } elseif {![regexp {^[0-9]+$} $key]} {
145                set how -dictionary
146                break
147            }
148        }
149
150        # keep a list of indices sorted in order
151        set _indices ""
152        if {[string equal $how -dictionary]} {
153            set n 0
154            foreach val [lsort $how [array names _dataobjs]] {
155                lappend _indices [list $val $n]
156                incr n
157            }
158        } else {
159            foreach val [lsort $how [array names _dataobjs]] {
160                lappend _indices [list $val $val]
161            }
162        }
163    }
164}
165
166# ----------------------------------------------------------------------
167# DESTRUCTOR
168# ----------------------------------------------------------------------
169itcl::body Rappture::Sequence::destructor {} {
170    foreach key [array names _dataobjs] {
171        eval itcl::delete object $_dataobjs($key)
172    }
173    itcl::delete object $_xmlobj
174}
175
176# ----------------------------------------------------------------------
177# USAGE: value <pos>
178#
179# Returns the value for the element as position <pos> in the
180# list of all elements.  Here, <pos> runs from 0 to size-1.
181# ----------------------------------------------------------------------
182itcl::body Rappture::Sequence::value {pos} {
183    set i [lindex [lindex $_indices $pos] 0]
184    return $_dataobjs($i)
185}
186
187# ----------------------------------------------------------------------
188# USAGE: label <pos>
189#
190# Returns the label for the element as position <pos> in the
191# list of all elements.  Here, <pos> runs from 0 to size-1.
192# ----------------------------------------------------------------------
193itcl::body Rappture::Sequence::label {pos} {
194    set i [lindex [lindex $_indices $pos] 0]
195    return $_labels($i)
196}
197
198# ----------------------------------------------------------------------
199# USAGE: index <pos>
200#
201# Returns information about the index value for the element at
202# position <pos> in the list of all elements.  The return value is
203# a list of two elements:  {string rawNumberValue}.  Here, <pos>
204# runs from 0 to size-1.
205# ----------------------------------------------------------------------
206itcl::body Rappture::Sequence::index {pos} {
207    return [lindex $_indices $pos]
208}
209
210# ----------------------------------------------------------------------
211# USAGE: size
212#
213# Returns the number of elements in this sequence.
214# ----------------------------------------------------------------------
215itcl::body Rappture::Sequence::size {} {
216    return [llength $_indices]
217}
218
219# ----------------------------------------------------------------------
220# USAGE: hints ?<keyword>?
221#
222# Returns a list of key/value pairs for various hints about showing
223# this image.  If a particular <keyword> is specified, then it returns
224# the hint for that <keyword>, if it exists.
225# ----------------------------------------------------------------------
226itcl::body Rappture::Sequence::hints {{keyword ""}} {
227    if {![info exists _hints]} {
228        foreach {key path} {
229            label        about.label
230            indexlabel   index.label
231            indexdesc    index.description
232        } {
233            set str [$_xmlobj get $path]
234            if {"" != $str} {
235                set _hints($key) $str
236            }
237        }
238    }
239
240    if {$keyword != ""} {
241        if {[info exists _hints($keyword)]} {
242            return $_hints($keyword)
243        }
244        return ""
245    }
246    return [array get _hints]
247}
Note: See TracBrowser for help on using the repository browser.