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

Last change on this file since 1549 was 1549, checked in by gah, 15 years ago

fixed improper transfer function for volumes

File size: 11.3 KB
Line 
1
2# ----------------------------------------------------------------------
3#  COMPONENT: curve - extracts data from an XML description of a field
4#
5#  This object represents a curve of data in an XML description of
6#  simulator output.  A curve is similar to a field, but a field is
7#  a quantity versus position in device.  A curve is any quantity
8#  versus any other quantity.  This class simplifies the process of
9#  extracting data vectors that represent the curve.
10# ======================================================================
11#  AUTHOR:  Michael McLennan, Purdue University
12#  Copyright (c) 2004-2005  Purdue Research Foundation
13#
14#  See the file "license.terms" for information on usage and
15#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16# ======================================================================
17package require Itcl
18package require BLT
19
20namespace eval Rappture {
21    # forward declaration
22}
23
24itcl::class Rappture::Curve {
25    constructor {xmlobj path} {
26        # defined below
27    }
28    destructor {
29        # defined below
30    }
31
32    public method components {{pattern *}}
33    public method mesh {{what -overall}}
34    public method values {{what -overall}}
35    public method limits {which}
36    public method hints {{key ""}}
37    public method xmarkers {}
38    public method ymarkers {}
39
40    protected method _build {}
41
42    private variable _xmlobj ""  ;# ref to lib obj with curve data
43    private variable _curve ""   ;# lib obj representing this curve
44    private variable _comp2xy    ;# maps component name => x,y vectors
45    private variable _hints      ;# cache of hints stored in XML
46
47    private variable _xmarkers "";# list of {x,label,options} triplets.
48    private variable _ymarkers "";# list of {y,label,options} triplets.
49
50    private common _counter 0    ;# counter for unique vector names
51}
52
53# ----------------------------------------------------------------------
54# CONSTRUCTOR
55# ----------------------------------------------------------------------
56itcl::body Rappture::Curve::constructor {xmlobj path} {
57    if {![Rappture::library isvalid $xmlobj]} {
58        error "bad value \"$xmlobj\": should be LibraryObj"
59    }
60    set _xmlobj $xmlobj
61    set _curve [$xmlobj element -as object $path]
62
63    # build up vectors for various components of the curve
64    _build
65}
66
67# ----------------------------------------------------------------------
68# DESTRUCTOR
69# ----------------------------------------------------------------------
70itcl::body Rappture::Curve::destructor {} {
71    itcl::delete object $_curve
72    # don't destroy the _xmlobj! we don't own it!
73
74    foreach name [array names _comp2xy] {
75        eval blt::vector destroy $_comp2xy($name)
76    }
77}
78
79# ----------------------------------------------------------------------
80# USAGE: components ?<pattern>?
81#
82# Returns a list of names for the various components of this curve.
83# If the optional glob-style <pattern> is specified, then it returns
84# only the component names matching the pattern.
85# ----------------------------------------------------------------------
86itcl::body Rappture::Curve::components {{pattern *}} {
87    set rlist ""
88    foreach name [array names _comp2xy] {
89        if {[string match $pattern $name]} {
90            lappend rlist $name
91        }
92    }
93    return $rlist
94}
95
96# ----------------------------------------------------------------------
97# USAGE: mesh ?<name>?
98#
99# Returns the xvec for the specified curve component <name>.
100# If the name is not specified, then it returns the vectors for the
101# overall curve (sum of all components).
102# ----------------------------------------------------------------------
103itcl::body Rappture::Curve::mesh {{what -overall}} {
104    if {[info exists _comp2xy($what)]} {
105        return [lindex $_comp2xy($what) 0]  ;# return xv
106    }
107    error "bad option \"$what\": should be [join [lsort [array names _comp2xy]] {, }]"
108}
109
110# ----------------------------------------------------------------------
111# USAGE: values ?<name>?
112#
113# Returns the xvec for the specified curve component <name>.
114# If the name is not specified, then it returns the vectors for the
115# overall curve (sum of all components).
116# ----------------------------------------------------------------------
117itcl::body Rappture::Curve::values {{what -overall}} {
118    if {[info exists _comp2xy($what)]} {
119        return [lindex $_comp2xy($what) 1]  ;# return yv
120    }
121    error "bad option \"$what\": should be [join [lsort [array names _comp2xy]] {, }]"
122}
123
124# ----------------------------------------------------------------------
125# USAGE: limits x|xlin|xlog|y|ylin|ylog
126#
127# Returns the {min max} limits for the specified axis.
128# ----------------------------------------------------------------------
129itcl::body Rappture::Curve::limits {which} {
130    set min ""
131    set max ""
132    switch -- $which {
133        x - xlin { set pos 0; set log 0; set axis xaxis }
134        xlog { set pos 0; set log 1; set axis xaxis }
135        y - ylin - v - vlin { set pos 1; set log 0; set axis yaxis }
136        ylog - vlog { set pos 1; set log 1; set axis yaxis }
137        default {
138            error "bad option \"$which\": should be x, xlin, xlog, y, ylin, ylog, v, vlin, vlog"
139        }
140    }
141
142    blt::vector create tmp zero
143    foreach comp [array names _comp2xy] {
144        set vname [lindex $_comp2xy($comp) $pos]
145        $vname variable vec
146
147        if {$log} {
148            # on a log scale, use abs value and ignore 0's
149            $vname dup tmp
150            $vname dup zero
151            zero expr {tmp == 0}            ;# find the 0's
152            tmp expr {abs(tmp)}             ;# get the abs value
153            tmp expr {tmp + zero*max(tmp)}  ;# replace 0's with abs max
154            set vmin [blt::vector expr min(tmp)]
155            set vmax [blt::vector expr max(tmp)]
156        } else {
157            set vmin $vec(min)
158            set vmax $vec(max)
159        }
160
161        if {"" == $min} {
162            set min $vmin
163        } elseif {$vmin < $min} {
164            set min $vmin
165        }
166        if {"" == $max} {
167            set max $vmax
168        } elseif {$vmax > $max} {
169            set max $vmax
170        }
171    }
172    blt::vector destroy tmp zero
173
174    set val [$_curve get $axis.min]
175    if {"" != $val && "" != $min} {
176        if {$val > $min} {
177            # tool specified this min -- don't go any lower
178            set min $val
179        }
180    }
181
182    set val [$_curve get $axis.max]
183    if {"" != $val && "" != $max} {
184        if {$val < $max} {
185            # tool specified this max -- don't go any higher
186            set max $val
187        }
188    }
189
190    return [list $min $max]
191}
192
193# ----------------------------------------------------------------------
194# USAGE: hints ?<keyword>?
195#
196# Returns a list of key/value pairs for various hints about plotting
197# this curve.  If a particular <keyword> is specified, then it returns
198# the hint for that <keyword>, if it exists.
199# ----------------------------------------------------------------------
200itcl::body Rappture::Curve::hints {{keyword ""}} {
201    if {![info exists _hints]} {
202        foreach {key path} {
203            color   about.color
204            group   about.group
205            label   about.label
206            style   about.style
207            type    about.type
208            xdesc   xaxis.description
209            xlabel  xaxis.label
210            xmax    xaxis.max
211            xmin    xaxis.min
212            xscale  xaxis.scale
213            xticks  xaxis.ticklabels
214            xunits  xaxis.units
215            ydesc   yaxis.description
216            ylabel  yaxis.label
217            ymax    yaxis.max
218            ymin    yaxis.min
219            yscale  yaxis.scale
220            yticks  yaxis.ticklabels
221            yunits  yaxis.units
222            bars    xaxis.bars
223        } {
224            set str [$_curve get $path]
225            if {"" != $str} {
226                set _hints($key) $str
227            }
228        }
229        if {[info exists _hints(xlabel)] && "" != $_hints(xlabel)
230              && [info exists _hints(xunits)] && "" != $_hints(xunits)} {
231            set _hints(xlabel) "$_hints(xlabel) ($_hints(xunits))"
232        }
233        if {[info exists _hints(ylabel)] && "" != $_hints(ylabel)
234              && [info exists _hints(yunits)] && "" != $_hints(yunits)} {
235            set _hints(ylabel) "$_hints(ylabel) ($_hints(yunits))"
236        }
237
238        if {[info exists _hints(group)] && [info exists _hints(label)]} {
239            # pop-up help for each curve
240            set _hints(tooltip) $_hints(label)
241        }
242    }
243
244    if {$keyword != ""} {
245        if {[info exists _hints($keyword)]} {
246            return $_hints($keyword)
247        }
248        return ""
249    }
250    return [array get _hints]
251}
252
253# ----------------------------------------------------------------------
254# USAGE: _build
255#
256# Used internally to build up the vector representation for the
257# curve when the object is first constructed, or whenever the curve
258# data changes.  Discards any existing vectors and builds everything
259# from scratch.
260# ----------------------------------------------------------------------
261itcl::body Rappture::Curve::_build {} {
262    # discard any existing data
263    foreach name [array names _comp2xy] {
264        eval blt::vector destroy $_comp2xy($name)
265    }
266    catch {unset _comp2xy}
267
268    #
269    # Scan through the components of the curve and create
270    # vectors for each part.
271    #
272    foreach cname [$_curve children -type component] {
273        set xv ""
274        set yv ""
275
276        set xydata [$_curve get $cname.xy]
277        if { "" != $xydata} {
278            set xv [blt::vector create \#auto]
279            set yv [blt::vector create \#auto]
280            set tmp [blt::vector create \#auto]
281            $tmp set $xydata
282            $tmp split $xv $yv
283            blt::vector destroy $tmp
284        } else {
285            set xv [blt::vector create \#auto]
286            set yv [blt::vector create \#auto]
287            $xv set [$_curve get $cname.xvector]
288            $yv set [$_curve get $cname.yvector]
289            if { [$xv length] != [$yv length] } {
290                blt::vector destroy $xv $yv
291                set xv ""; set yv ""
292            }
293        }
294        if {$xv != "" && $yv != ""} {
295            set _comp2xy($cname) [list $xv $yv]
296            incr _counter
297        }
298    }
299    # Creates lists of x and y marker data.
300    set _xmarkers {}
301    set _ymarkers {}
302    foreach cname [$_curve children -type "marker" xaxis] {
303        set at     [$_curve get "xaxis.$cname.at"]
304        set label  [$_curve get "xaxis.$cname.label"]
305        set styles [$_curve get "xaxis.$cname.style"]
306        set data [list $at $label $styles]
307        lappend _xmarkers $data
308    }
309    foreach cname [$_curve children -type "marker" yaxis] {
310        set at     [$_curve get "yaxis.$cname.at"]
311        set label  [$_curve get "yaxis.$cname.label"]
312        set styles [$_curve get "yaxis.$cname.style"]
313        set data [list $at $label $styles]
314        lappend _xmarkers $data
315    }
316}
317
318# ----------------------------------------------------------------------
319# USAGE: xmarkers
320#
321# Returns the list of settings for each marker on the x-axis.
322# If no markers have been specified the empty string is returned.
323# ----------------------------------------------------------------------
324itcl::body Rappture::Curve::xmarkers {} {
325    return $_xmarkers;
326}
327
328# ----------------------------------------------------------------------
329# USAGE: ymarkers
330#
331# Returns the list of settings for each marker on the y-axis.
332# If no markers have been specified the empty string is returned.
333# ----------------------------------------------------------------------
334itcl::body Rappture::Curve::ymarkers {} {
335    return $_ymarkers;
336}
337
Note: See TracBrowser for help on using the repository browser.