source: trunk/gui/scripts/histogram.tcl @ 2035

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