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

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

preliminary HQ output from molvisviewer; unexpand tabs; all jpeg generation at 100%

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