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

Last change on this file since 116 was 115, checked in by mmc, 19 years ago

Updated all copyright notices.

File size: 9.3 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  Purdue Research Foundation
12#
13#  See the file "license.terms" for information on usage and
14#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15# ======================================================================
16package require Itcl
17package require BLT
18
19namespace eval Rappture { # forward declaration }
20
21itcl::class Rappture::Curve {
22    constructor {xmlobj path} { # defined below }
23    destructor { # defined below }
24
25    public method components {{pattern *}}
26    public method mesh {{what -overall}}
27    public method values {{what -overall}}
28    public method limits {which}
29    public method hints {{key ""}}
30
31    protected method _build {}
32
33    private variable _xmlobj ""  ;# ref to lib obj with curve data
34    private variable _curve ""   ;# lib obj representing this curve
35    private variable _comp2xy    ;# maps component name => x,y vectors
36    private variable _hints      ;# cache of hints stored in XML
37
38    private common _counter 0    ;# counter for unique vector names
39}
40
41# ----------------------------------------------------------------------
42# CONSTRUCTOR
43# ----------------------------------------------------------------------
44itcl::body Rappture::Curve::constructor {xmlobj path} {
45    if {![Rappture::library isvalid $xmlobj]} {
46        error "bad value \"$xmlobj\": should be LibraryObj"
47    }
48    set _xmlobj $xmlobj
49    set _curve [$xmlobj element -as object $path]
50
51    # build up vectors for various components of the curve
52    _build
53}
54
55# ----------------------------------------------------------------------
56# DESTRUCTOR
57# ----------------------------------------------------------------------
58itcl::body Rappture::Curve::destructor {} {
59    itcl::delete object $_curve
60    # don't destroy the _xmlobj! we don't own it!
61
62    foreach name [array names _comp2xy] {
63        eval blt::vector destroy $_comp2xy($name)
64    }
65}
66
67# ----------------------------------------------------------------------
68# USAGE: components ?<pattern>?
69#
70# Returns a list of names for the various components of this curve.
71# If the optional glob-style <pattern> is specified, then it returns
72# only the component names matching the pattern.
73# ----------------------------------------------------------------------
74itcl::body Rappture::Curve::components {{pattern *}} {
75    set rlist ""
76    foreach name [array names _comp2xy] {
77        if {[string match $pattern $name]} {
78            lappend rlist $name
79        }
80    }
81    return $rlist
82}
83
84# ----------------------------------------------------------------------
85# USAGE: mesh ?<name>?
86#
87# Returns the xvec for the specified curve component <name>.
88# If the name is not specified, then it returns the vectors for the
89# overall curve (sum of all components).
90# ----------------------------------------------------------------------
91itcl::body Rappture::Curve::mesh {{what -overall}} {
92    if {[info exists _comp2xy($what)]} {
93        return [lindex $_comp2xy($what) 0]  ;# return xv
94    }
95    error "bad option \"$what\": should be [join [lsort [array names _comp2xy]] {, }]"
96}
97
98# ----------------------------------------------------------------------
99# USAGE: values ?<name>?
100#
101# Returns the xvec for the specified curve component <name>.
102# If the name is not specified, then it returns the vectors for the
103# overall curve (sum of all components).
104# ----------------------------------------------------------------------
105itcl::body Rappture::Curve::values {{what -overall}} {
106    if {[info exists _comp2xy($what)]} {
107        return [lindex $_comp2xy($what) 1]  ;# return yv
108    }
109    error "bad option \"$what\": should be [join [lsort [array names _comp2xy]] {, }]"
110}
111
112# ----------------------------------------------------------------------
113# USAGE: limits x|xlin|xlog|y|ylin|ylog
114#
115# Returns the {min max} limits for the specified axis.
116# ----------------------------------------------------------------------
117itcl::body Rappture::Curve::limits {which} {
118    set min ""
119    set max ""
120    switch -- $which {
121        x - xlin { set pos 0; set log 0; set axis xaxis }
122        xlog { set pos 0; set log 1; set axis xaxis }
123        y - ylin - v - vlin { set pos 1; set log 0; set axis yaxis }
124        ylog - vlog { set pos 1; set log 1; set axis yaxis }
125        default {
126            error "bad option \"$which\": should be x, xlin, xlog, y, ylin, ylog, v, vlin, vlog"
127        }
128    }
129
130    blt::vector create tmp zero
131    foreach comp [array names _comp2xy] {
132        set vname [lindex $_comp2xy($comp) $pos]
133        $vname variable vec
134
135        if {$log} {
136            # on a log scale, use abs value and ignore 0's
137            $vname dup tmp
138            $vname dup zero
139            zero expr {tmp == 0}            ;# find the 0's
140            tmp expr {abs(tmp)}             ;# get the abs value
141            tmp expr {tmp + zero*max(tmp)}  ;# replace 0's with abs max
142            set vmin [blt::vector expr min(tmp)]
143            set vmax [blt::vector expr max(tmp)]
144        } else {
145            set vmin $vec(min)
146            set vmax $vec(max)
147        }
148
149        if {"" == $min} {
150            set min $vmin
151        } elseif {$vmin < $min} {
152            set min $vmin
153        }
154        if {"" == $max} {
155            set max $vmax
156        } elseif {$vmax > $max} {
157            set max $vmax
158        }
159    }
160    blt::vector destroy tmp zero
161
162    set val [$_curve get $axis.min]
163    if {"" != $val && "" != $min} {
164        if {$val > $min} {
165            # tool specified this min -- don't go any lower
166            set min $val
167        }
168    }
169
170    set val [$_curve get $axis.max]
171    if {"" != $val && "" != $max} {
172        if {$val < $max} {
173            # tool specified this max -- don't go any higher
174            set max $val
175        }
176    }
177
178    return [list $min $max]
179}
180
181# ----------------------------------------------------------------------
182# USAGE: hints ?<keyword>?
183#
184# Returns a list of key/value pairs for various hints about plotting
185# this curve.  If a particular <keyword> is specified, then it returns
186# the hint for that <keyword>, if it exists.
187# ----------------------------------------------------------------------
188itcl::body Rappture::Curve::hints {{keyword ""}} {
189    if {![info exists _hints]} {
190        foreach {key path} {
191            group   about.group
192            label   about.label
193            color   about.color
194            style   about.style
195            xlabel  xaxis.label
196            xunits  xaxis.units
197            xscale  xaxis.scale
198            xmin    xaxis.min
199            xmax    xaxis.max
200            ylabel  yaxis.label
201            yunits  yaxis.units
202            yscale  yaxis.scale
203            ymin    yaxis.min
204            ymax    yaxis.max
205        } {
206            set str [$_curve get $path]
207            if {"" != $str} {
208                set _hints($key) $str
209            }
210        }
211
212        if {[info exists _hints(xlabel)] && "" != $_hints(xlabel)
213              && [info exists _hints(xunits)] && "" != $_hints(xunits)} {
214            set _hints(xlabel) "$_hints(xlabel) ($_hints(xunits))"
215        }
216        if {[info exists _hints(ylabel)] && "" != $_hints(ylabel)
217              && [info exists _hints(yunits)] && "" != $_hints(yunits)} {
218            set _hints(ylabel) "$_hints(ylabel) ($_hints(yunits))"
219        }
220
221        if {[info exists _hints(group)] && [info exists _hints(label)]} {
222            # pop-up help for each curve
223            set _hints(tooltip) $_hints(label)
224        }
225    }
226
227    if {$keyword != ""} {
228        if {[info exists _hints($keyword)]} {
229            return $_hints($keyword)
230        }
231        return ""
232    }
233    return [array get _hints]
234}
235
236# ----------------------------------------------------------------------
237# USAGE: _build
238#
239# Used internally to build up the vector representation for the
240# curve when the object is first constructed, or whenever the curve
241# data changes.  Discards any existing vectors and builds everything
242# from scratch.
243# ----------------------------------------------------------------------
244itcl::body Rappture::Curve::_build {} {
245    # discard any existing data
246    foreach name [array names _comp2xy] {
247        eval blt::vector destroy $_comp2xy($name)
248    }
249    catch {unset _comp2xy}
250
251    #
252    # Scan through the components of the curve and create
253    # vectors for each part.
254    #
255    foreach cname [$_curve children -type component] {
256        set xv ""
257        set yv ""
258
259        set xydata [$_curve get $cname.xy]
260        if {"" != $xydata} {
261            set xv [blt::vector create x$_counter]
262            set yv [blt::vector create y$_counter]
263
264            foreach line [split $xydata \n] {
265                if {[scan $line {%g %g} xval yval] == 2} {
266                    $xv append $xval
267                    $yv append $yval
268                }
269            }
270        }
271
272        if {$xv != "" && $yv != ""} {
273            set _comp2xy($cname) [list $xv $yv]
274            incr _counter
275        }
276    }
277}
Note: See TracBrowser for help on using the repository browser.