source: trunk/gui/scripts/field.tcl @ 9

Last change on this file since 9 was 9, checked in by mmc, 20 years ago

Massive changes across the entire toolkit. Rearranged the
XML description to agree better with new documentation and
conventions.

Added a small start of Rappture.interface and Rappture.number
in the python directory. This is the new way of doing Rappture--
by declaring variables directly in the program, not using XML
directly at all.

File size: 8.2 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: field - extracts data from an XML description of a field
3#
4#  This object represents one field in an XML description of a device.
5#  It simplifies the process of extracting data vectors that represent
6#  the field.
7# ======================================================================
8#  AUTHOR:  Michael McLennan, Purdue University
9#  Copyright (c) 2004  Purdue Research Foundation, West Lafayette, IN
10# ======================================================================
11package require Itcl
12package require BLT
13
14namespace eval Rappture { # forward declaration }
15
16itcl::class Rappture::Field {
17    constructor {devobj libobj path} { # defined below }
18    destructor { # defined below }
19
20    public method components {{pattern *}}
21    public method vectors {{what -overall}}
22    public method controls {option args}
23    public method hints {{key ""}}
24
25    protected method _build {}
26
27    private variable _device ""  ;# ref to lib obj with device data
28    private variable _libobj ""  ;# ref to lib obj with field data
29
30    private variable _units ""   ;# system of units for this field
31    private variable _limits     ;# maps slab name => {z0 z1} limits
32    private variable _zmax 0     ;# length of the device
33
34    private variable _field ""   ;# lib obj representing this field
35    private variable _comp2vecs  ;# maps component name => x,y vectors
36    private variable _comp2cntls ;# maps component name => x,y control points
37
38    private common _counter 0    ;# counter for unique vector names
39}
40
41# ----------------------------------------------------------------------
42# CONSTRUCTOR
43# ----------------------------------------------------------------------
44itcl::body Rappture::Field::constructor {devobj libobj path} {
45    if {![Rappture::library isvalid $devobj]} {
46        error "bad value \"$devobj\": should be LibraryObj"
47    }
48    if {![Rappture::library isvalid $libobj]} {
49        error "bad value \"$libobj\": should be LibraryObj"
50    }
51    set _device $devobj
52    set _libobj $libobj
53    set _field [$libobj element -flavor object $path]
54    set _units [$_field get units]
55
56    # determine the overall size of the device
57    set z0 [set z1 0]
58    foreach elem [$_device children components] {
59        switch -glob -- $elem {
60            slab* - molecule* {
61                if {![regexp {[0-9]$} $elem]} {
62                    set elem "${elem}0"
63                }
64                set tval [$_device get components.$elem.thickness]
65                set tval [Rappture::Units::convert $tval \
66                    -context um -to um -units off]
67                set z1 [expr {$z0+$tval}]
68                set _limits($elem) [list $z0 $z1]
69
70                set z0 $z1
71            }
72        }
73    }
74    set _zmax $z1
75
76    # build up vectors for various components of the field
77    _build
78}
79
80# ----------------------------------------------------------------------
81# DESTRUCTOR
82# ----------------------------------------------------------------------
83itcl::body Rappture::Field::destructor {} {
84    itcl::delete object $_field
85    # don't destroy the _device! we don't own it!
86
87    foreach name [array names _comp2vecs] {
88        eval blt::vector destroy $_comp2vecs($name)
89    }
90}
91
92# ----------------------------------------------------------------------
93# USAGE: components ?<pattern>?
94#
95# Returns a list of names for the various components of this field.
96# If the optional glob-style <pattern> is specified, then it returns
97# only the component names matching the pattern.
98# ----------------------------------------------------------------------
99itcl::body Rappture::Field::components {{pattern *}} {
100    set rlist ""
101    foreach name [array names _comp2vecs] {
102        if {[string match $pattern $name]} {
103            lappend rlist $name
104        }
105    }
106    return $rlist
107}
108
109# ----------------------------------------------------------------------
110# USAGE: vectors ?<name>?
111#
112# Returns a list {xvec yvec} for the specified field component <name>.
113# If the name is not specified, then it returns the vectors for the
114# overall field (sum of all components).
115# ----------------------------------------------------------------------
116itcl::body Rappture::Field::vectors {{what -overall}} {
117    if {$what == "component0"} {
118        set what "component"
119    }
120    if {[info exists _comp2vecs($what)]} {
121        return $_comp2vecs($what)
122    }
123    error "bad option \"$what\": should be [join [lsort [array names _comp2vecs]] {, }]"
124}
125
126# ----------------------------------------------------------------------
127# USAGE: controls get ?<name>?
128# USAGE: controls put <path> <value>
129#
130# Returns a list {path1 x1 y1 val1  path2 x2 y2 val2 ...} representing
131# control points for the specified field component <name>.
132# ----------------------------------------------------------------------
133itcl::body Rappture::Field::controls {option args} {
134    switch -- $option {
135        get {
136            set what [lindex $args 0]
137            if {[info exists _comp2cntls($what)]} {
138                return $_comp2cntls($what)
139            }
140            error "bad option \"$what\": should be [join [lsort [array names _comp2cntls]] {, }]"
141        }
142        put {
143            set path [lindex $args 0]
144            set value [lindex $args 1]
145            $_field put $path $value
146            _build
147        }
148        default {
149            error "bad option \"$option\": should be get or put"
150        }
151    }
152}
153
154# ----------------------------------------------------------------------
155# USAGE: hints ?<keyword>?
156#
157# Returns a list of key/value pairs for various hints about plotting
158# this field.  If a particular <keyword> is specified, then it returns
159# the hint for that <keyword>, if it exists.
160# ----------------------------------------------------------------------
161itcl::body Rappture::Field::hints {{keyword ""}} {
162    foreach key {label scale color units restrict} {
163        set str [$_field get $key]
164        if {"" != $str} {
165            set hints($key) $str
166        }
167    }
168
169    if {$keyword != ""} {
170        if {[info exists hints($keyword)]} {
171            return $hints($keyword)
172        }
173        return ""
174    }
175    return [array get hints]
176}
177
178# ----------------------------------------------------------------------
179# USAGE: _build
180#
181# Used internally to build up the vector representation for the
182# field when the object is first constructed, or whenever the field
183# data changes.  Discards any existing vectors and builds everything
184# from scratch.
185# ----------------------------------------------------------------------
186itcl::body Rappture::Field::_build {} {
187    # discard any existing data
188    foreach name [array names _comp2vecs] {
189        eval blt::vector destroy $_comp2vecs($name)
190    }
191    catch {unset _comp2vecs}
192
193    #
194    # Scan through the components of the field and create
195    # vectors for each part.
196    #
197    foreach cname [$_field children -type component] {
198        set xv ""
199        set yv ""
200
201        set val [$_field get $cname.constant]
202        if {$val != ""} {
203            set domain [$_field get $cname.domain]
204            if {$domain == "" || ![info exists _limits($domain)]} {
205                set z0 0
206                set z1 $_zmax
207            } else {
208                foreach {z0 z1} $_limits($domain) { break }
209            }
210            set xv [blt::vector create x$_counter]
211            $xv append $z0 $z1
212
213            if {$_units != ""} {
214                set val [Rappture::Units::convert $val \
215                    -context $_units -to $_units -units off]
216            }
217            set yv [blt::vector create y$_counter]
218            $yv append $val $val
219
220            set zm [expr {0.5*($z0+$z1)}]
221            set _comp2cntls($cname) \
222                [list $cname.constant $zm $val "$val$_units"]
223        } else {
224            set xydata [$_field get $cname.xy]
225            if {"" != $xydata} {
226                set xv [blt::vector create x$_counter]
227                set yv [blt::vector create y$_counter]
228
229                foreach line [split $xydata \n] {
230                    if {[scan $line {%g %g} xval yval] == 2} {
231                        $xv append $xval
232                        $yv append $yval
233                    }
234                }
235            }
236        }
237
238        if {$xv != "" && $yv != ""} {
239            set _comp2vecs($cname) [list $xv $yv]
240            incr _counter
241        }
242    }
243}
Note: See TracBrowser for help on using the repository browser.