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

Last change on this file since 1 was 1, checked in by mmc, 17 years ago

initial import

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::valid $devobj]} {
46        error "bad value \"$devobj\": should be LibraryObj"
47    }
48    if {![Rappture::Library::valid $libobj]} {
49        error "bad value \"$libobj\": should be LibraryObj"
50    }
51    set _device $devobj
52    set _libobj $libobj
53    set _field [$libobj get -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 get -children recipe] {
59        switch -glob -- $elem {
60            slab* - molecule* {
61                if {![regexp {[0-9]$} $elem]} {
62                    set elem "${elem}0"
63                }
64                set tval [$_device get recipe.$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 {[info exists _comp2vecs($what)]} {
118        return $_comp2vecs($what)
119    }
120    error "bad option \"$what\": should be [join [lsort [array names _comp2vecs]] {, }]"
121}
122
123# ----------------------------------------------------------------------
124# USAGE: controls get ?<name>?
125# USAGE: controls put <path> <value>
126#
127# Returns a list {path1 x1 y1 val1  path2 x2 y2 val2 ...} representing
128# control points for the specified field component <name>.
129# ----------------------------------------------------------------------
130itcl::body Rappture::Field::controls {option args} {
131    switch -- $option {
132        get {
133            set what [lindex $args 0]
134            if {[info exists _comp2cntls($what)]} {
135                return $_comp2cntls($what)
136            }
137            error "bad option \"$what\": should be [join [lsort [array names _comp2cntls]] {, }]"
138        }
139        put {
140            set path [lindex $args 0]
141            set value [lindex $args 1]
142            $_field put $path $value
143            _build
144        }
145        default {
146            error "bad option \"$option\": should be get or put"
147        }
148    }
149}
150
151# ----------------------------------------------------------------------
152# USAGE: hints ?<keyword>?
153#
154# Returns a list of key/value pairs for various hints about plotting
155# this field.  If a particular <keyword> is specified, then it returns
156# the hint for that <keyword>, if it exists.
157# ----------------------------------------------------------------------
158itcl::body Rappture::Field::hints {{keyword ""}} {
159    foreach key {label scale color units restrict} {
160        set str [$_field get $key]
161        if {"" != $str} {
162            set hints($key) $str
163        }
164    }
165
166    if {$keyword != ""} {
167        if {[info exists hints($keyword)]} {
168            return $hints($keyword)
169        }
170        return ""
171    }
172    return [array get hints]
173}
174
175# ----------------------------------------------------------------------
176# USAGE: _build
177#
178# Used internally to build up the vector representation for the
179# field when the object is first constructed, or whenever the field
180# data changes.  Discards any existing vectors and builds everything
181# from scratch.
182# ----------------------------------------------------------------------
183itcl::body Rappture::Field::_build {} {
184    # discard any existing data
185    foreach name [array names _comp2vecs] {
186        eval blt::vector destroy $_comp2vecs($name)
187    }
188    catch {unset _comp2vecs}
189
190    #
191    # Scan through the components of the field and create
192    # vectors for each part.
193    #
194    set max [$_field get -count component]
195    for {set i 0} {$i < $max} {incr i} {
196        set xv ""
197        set yv ""
198
199        set val [$_field get component$i.constant]
200        if {$val != ""} {
201            set domain [$_field get component$i.domain]
202            if {$domain == "" || ![info exists _limits($domain)]} {
203                set z0 0
204                set z1 $_zmax
205            } else {
206                foreach {z0 z1} $_limits($domain) { break }
207            }
208            set xv [blt::vector create x$_counter]
209            $xv append $z0 $z1
210
211            if {$_units != ""} {
212                set val [Rappture::Units::convert $val \
213                    -context $_units -to $_units -units off]
214            }
215            set yv [blt::vector create y$_counter]
216            $yv append $val $val
217
218            set zm [expr {0.5*($z0+$z1)}]
219            set _comp2cntls(component$i) \
220                [list component$i.constant $zm $val "$val$_units"]
221        } else {
222            set xydata [$_field get component$i.xy]
223            if {"" != $xydata} {
224                set xv [blt::vector create x$_counter]
225                set yv [blt::vector create y$_counter]
226
227                foreach line [split $xydata \n] {
228                    if {[scan $line {%g %g} xval yval] == 2} {
229                        $xv append $xval
230                        $yv append $yval
231                    }
232                }
233            }
234        }
235
236        if {$xv != "" && $yv != ""} {
237            set _comp2vecs(component$i) [list $xv $yv]
238            incr _counter
239        }
240    }
241}
Note: See TracBrowser for help on using the repository browser.