source: branches/blt4/gui/scripts/histogram.tcl @ 1681

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