[1] | 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 Purdue Research Foundation, West Lafayette, IN |
---|
| 12 | # ====================================================================== |
---|
| 13 | package require Itcl |
---|
| 14 | package require BLT |
---|
| 15 | |
---|
| 16 | namespace eval Rappture { # forward declaration } |
---|
| 17 | |
---|
| 18 | itcl::class Rappture::Curve { |
---|
| 19 | constructor {libobj path} { # defined below } |
---|
| 20 | destructor { # defined below } |
---|
| 21 | |
---|
| 22 | public method components {{pattern *}} |
---|
| 23 | public method vectors {{what -overall}} |
---|
| 24 | public method controls {option args} |
---|
| 25 | public method hints {{key ""}} |
---|
| 26 | |
---|
| 27 | protected method _build {} |
---|
| 28 | |
---|
| 29 | private variable _libobj "" ;# ref to lib obj with curve data |
---|
| 30 | private variable _curve "" ;# lib obj representing this curve |
---|
| 31 | private variable _comp2vecs ;# maps component name => x,y vectors |
---|
| 32 | |
---|
| 33 | private common _counter 0 ;# counter for unique vector names |
---|
| 34 | } |
---|
| 35 | |
---|
| 36 | # ---------------------------------------------------------------------- |
---|
| 37 | # CONSTRUCTOR |
---|
| 38 | # ---------------------------------------------------------------------- |
---|
| 39 | itcl::body Rappture::Curve::constructor {libobj path} { |
---|
[6] | 40 | if {![Rappture::library isvalid $libobj]} { |
---|
[1] | 41 | error "bad value \"$libobj\": should be LibraryObj" |
---|
| 42 | } |
---|
| 43 | set _libobj $libobj |
---|
[6] | 44 | set _curve [$libobj element -flavor object $path] |
---|
[1] | 45 | |
---|
| 46 | # build up vectors for various components of the curve |
---|
| 47 | _build |
---|
| 48 | } |
---|
| 49 | |
---|
| 50 | # ---------------------------------------------------------------------- |
---|
| 51 | # DESTRUCTOR |
---|
| 52 | # ---------------------------------------------------------------------- |
---|
| 53 | itcl::body Rappture::Curve::destructor {} { |
---|
| 54 | itcl::delete object $_curve |
---|
| 55 | # don't destroy the _libobj! we don't own it! |
---|
| 56 | |
---|
| 57 | foreach name [array names _comp2vecs] { |
---|
| 58 | eval blt::vector destroy $_comp2vecs($name) |
---|
| 59 | } |
---|
| 60 | } |
---|
| 61 | |
---|
| 62 | # ---------------------------------------------------------------------- |
---|
| 63 | # USAGE: components ?<pattern>? |
---|
| 64 | # |
---|
| 65 | # Returns a list of names for the various components of this curve. |
---|
| 66 | # If the optional glob-style <pattern> is specified, then it returns |
---|
| 67 | # only the component names matching the pattern. |
---|
| 68 | # ---------------------------------------------------------------------- |
---|
| 69 | itcl::body Rappture::Curve::components {{pattern *}} { |
---|
| 70 | set rlist "" |
---|
| 71 | foreach name [array names _comp2vecs] { |
---|
| 72 | if {[string match $pattern $name]} { |
---|
| 73 | lappend rlist $name |
---|
| 74 | } |
---|
| 75 | } |
---|
| 76 | return $rlist |
---|
| 77 | } |
---|
| 78 | |
---|
| 79 | # ---------------------------------------------------------------------- |
---|
| 80 | # USAGE: vectors ?<name>? |
---|
| 81 | # |
---|
| 82 | # Returns a list {xvec yvec} for the specified curve component <name>. |
---|
| 83 | # If the name is not specified, then it returns the vectors for the |
---|
| 84 | # overall curve (sum of all components). |
---|
| 85 | # ---------------------------------------------------------------------- |
---|
| 86 | itcl::body Rappture::Curve::vectors {{what -overall}} { |
---|
| 87 | if {[info exists _comp2vecs($what)]} { |
---|
| 88 | return $_comp2vecs($what) |
---|
| 89 | } |
---|
| 90 | error "bad option \"$what\": should be [join [lsort [array names _comp2vecs]] {, }]" |
---|
| 91 | } |
---|
| 92 | |
---|
| 93 | # ---------------------------------------------------------------------- |
---|
| 94 | # USAGE: hints ?<keyword>? |
---|
| 95 | # |
---|
| 96 | # Returns a list of key/value pairs for various hints about plotting |
---|
| 97 | # this curve. If a particular <keyword> is specified, then it returns |
---|
| 98 | # the hint for that <keyword>, if it exists. |
---|
| 99 | # ---------------------------------------------------------------------- |
---|
| 100 | itcl::body Rappture::Curve::hints {{keyword ""}} { |
---|
| 101 | foreach {key path} { |
---|
| 102 | label label |
---|
| 103 | color color |
---|
| 104 | color style |
---|
| 105 | xlabel xaxis.label |
---|
| 106 | xunits xaxis.units |
---|
| 107 | xscale xaxis.scale |
---|
| 108 | ylabel yaxis.label |
---|
| 109 | yunits yaxis.units |
---|
| 110 | yscale yaxis.scale |
---|
| 111 | } { |
---|
| 112 | set str [$_curve get $path] |
---|
| 113 | if {"" != $str} { |
---|
| 114 | set hints($key) $str |
---|
| 115 | } |
---|
| 116 | } |
---|
| 117 | |
---|
| 118 | if {$keyword != ""} { |
---|
| 119 | if {[info exists hints($keyword)]} { |
---|
| 120 | return $hints($keyword) |
---|
| 121 | } |
---|
| 122 | return "" |
---|
| 123 | } |
---|
| 124 | return [array get hints] |
---|
| 125 | } |
---|
| 126 | |
---|
| 127 | # ---------------------------------------------------------------------- |
---|
| 128 | # USAGE: _build |
---|
| 129 | # |
---|
| 130 | # Used internally to build up the vector representation for the |
---|
| 131 | # curve when the object is first constructed, or whenever the curve |
---|
| 132 | # data changes. Discards any existing vectors and builds everything |
---|
| 133 | # from scratch. |
---|
| 134 | # ---------------------------------------------------------------------- |
---|
| 135 | itcl::body Rappture::Curve::_build {} { |
---|
| 136 | # discard any existing data |
---|
| 137 | foreach name [array names _comp2vecs] { |
---|
| 138 | eval blt::vector destroy $_comp2vecs($name) |
---|
| 139 | } |
---|
| 140 | catch {unset _comp2vecs} |
---|
| 141 | |
---|
| 142 | # |
---|
| 143 | # Scan through the components of the curve and create |
---|
| 144 | # vectors for each part. |
---|
| 145 | # |
---|
[6] | 146 | foreach cname [$_curve children -type component] { |
---|
[1] | 147 | set xv "" |
---|
| 148 | set yv "" |
---|
| 149 | |
---|
[6] | 150 | set xydata [$_curve get $cname.xy] |
---|
[1] | 151 | if {"" != $xydata} { |
---|
| 152 | set xv [blt::vector create x$_counter] |
---|
| 153 | set yv [blt::vector create y$_counter] |
---|
| 154 | |
---|
| 155 | foreach line [split $xydata \n] { |
---|
| 156 | if {[scan $line {%g %g} xval yval] == 2} { |
---|
| 157 | $xv append $xval |
---|
| 158 | $yv append $yval |
---|
| 159 | } |
---|
| 160 | } |
---|
| 161 | } |
---|
| 162 | |
---|
| 163 | if {$xv != "" && $yv != ""} { |
---|
[6] | 164 | set _comp2vecs($cname) [list $xv $yv] |
---|
[1] | 165 | incr _counter |
---|
| 166 | } |
---|
| 167 | } |
---|
| 168 | } |
---|