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

Last change on this file since 46 was 25, checked in by mmc, 19 years ago

Added <min>, <max>, and <scale> directives to the output plotter
for <curve> objects. If you specify any of these within an axis
for a curve, they set the default characteristics for the axis.

File size: 7.8 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 - v { 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        xmin    xaxis.min
158        xmax    xaxis.max
159        ylabel  yaxis.label
160        yunits  yaxis.units
161        yscale  yaxis.scale
162        ymin    yaxis.min
163        ymax    yaxis.max
164    } {
165        set str [$_curve get $path]
166        if {"" != $str} {
167            set hints($key) $str
168        }
169    }
170
171    if {[info exists hints(xlabel)] && "" != $hints(xlabel)
172          && [info exists hints(xunits)] && "" != $hints(xunits)} {
173        set hints(xlabel) "$hints(xlabel) ($hints(xunits))"
174    }
175    if {[info exists hints(ylabel)] && "" != $hints(ylabel)
176          && [info exists hints(yunits)] && "" != $hints(yunits)} {
177        set hints(ylabel) "$hints(ylabel) ($hints(yunits))"
178    }
179
180    if {[info exists hints(group)] && [info exists hints(label)]} {
181        # pop-up help for each curve
182        set hints(tooltip) $hints(label)
183    }
184
185    if {$keyword != ""} {
186        if {[info exists hints($keyword)]} {
187            return $hints($keyword)
188        }
189        return ""
190    }
191    return [array get hints]
192}
193
194# ----------------------------------------------------------------------
195# USAGE: _build
196#
197# Used internally to build up the vector representation for the
198# curve when the object is first constructed, or whenever the curve
199# data changes.  Discards any existing vectors and builds everything
200# from scratch.
201# ----------------------------------------------------------------------
202itcl::body Rappture::Curve::_build {} {
203    # discard any existing data
204    foreach name [array names _comp2xy] {
205        eval blt::vector destroy $_comp2xy($name)
206    }
207    catch {unset _comp2xy}
208
209    #
210    # Scan through the components of the curve and create
211    # vectors for each part.
212    #
213    foreach cname [$_curve children -type component] {
214        set xv ""
215        set yv ""
216
217        set xydata [$_curve get $cname.xy]
218        if {"" != $xydata} {
219            set xv [blt::vector create x$_counter]
220            set yv [blt::vector create y$_counter]
221
222            foreach line [split $xydata \n] {
223                if {[scan $line {%g %g} xval yval] == 2} {
224                    $xv append $xval
225                    $yv append $yval
226                }
227            }
228        }
229
230        if {$xv != "" && $yv != ""} {
231            set _comp2xy($cname) [list $xv $yv]
232            incr _counter
233        }
234    }
235}
Note: See TracBrowser for help on using the repository browser.