source: trunk/gui/scripts/curve.tcl @ 13

Last change on this file since 13 was 13, checked in by mmc, 16 years ago

Many improvements, including a new energy level viewer
for Huckel-IV. Added support for a new <boolean> type.
Fixed the cloud/field stuff so that when a cloud is 1D,
it reverts to BLT vectors so it will plot correctly.
Fixed the install script to work better on Windows.

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