# graph.tcl # # Copyright (c) 1998 Mark Black # # This library contains all the graphing functions for drawing statsistics # # The data set for these comamnds is global. It is too slow otherwise set d0 {} set d1 {} set d2 {} set d3 {} set d4 {} set d5 {} set d6 {} set d7 {} # These are the time indexes set min {} set hour {} set day {} set tindx {} # This is the X magnification variable set magX 1 # # This procedure draws the graphs of the staticistics. # graphid - a .name for the graph frame (for multiple graphs) # maxval - the maximum value to graph # minval - the minimum value to graph # args - name/command pairs of the data in the datafile. The # command extracts the data from of the log file. # The data should be located in /tmp/mon01234.log # proc drawGraph { graphid hostname title xlabel maxval minval args } { if { [winfo exists $graphid ] != 0 } { destroy $graphid } global upgrade_buff global min hour day tindx magX set maxX 250 set maxY 250 set ylabelwidth 50 set tfont {-*-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*} # Define head space (space from top) and display space (y value range) set hs 10 set ds [expr {$maxY - $hs - 25.0} ] # Define constants for mapping the data range to the display range set m [expr { -$ds / ($maxval - $minval)} ] set b [expr {$hs + (($ds * $maxval) / ($maxval - $minval))}] # puts stdout "Y = $m X + $b" toplevel $graphid -class Dialog wm title $graphid "Statistics for $hostname" wm iconname $graphid "$hostname Stats" frame $graphid.f1 -relief raised -borderwidth 2 menubutton $graphid.f1.opt0 -text "File" -menu $graphid.f1.opt0.file menubutton $graphid.f1.opt5 -text "Display" -menu $graphid.f1.opt5.mag menu $graphid.f1.opt0.file $graphid.f1.opt0.file add command -label "Print" -command "printGraph $graphid.f5.canout $graphid.f5.yaxis" # $graphid.f1.opt0.file add command -label "Export" -command { } $graphid.f1.opt0.file add separator $graphid.f1.opt0.file add command -label "Close" -command "destroy $graphid" -foreground red pack $graphid.f1.opt0 -side left -fill x menu $graphid.f1.opt5.mag $graphid.f1.opt5.mag add cascade -label "Magnify X" -menu $graphid.f1.opt5.mag.magx menu $graphid.f1.opt5.mag.magx $graphid.f1.opt5.mag.magx add radio -label "1x" -variable magx -value 1 -command "set magX 1" $graphid.f1.opt5.mag.magx add radio -label "2x" -variable magx -value 2 -command "set magX 2" $graphid.f1.opt5.mag.magx add radio -label "4x" -variable magx -value 4 -command "set magX 4" $graphid.f1.opt5.mag.magx add radio -label "8x" -variable magx -value 8 -command "set magX 8" $graphid.f1.opt5.mag.magx invoke 1 pack $graphid.f1.opt5 -side left -fill x pack $graphid.f1 -anchor w -fill x label $graphid.title -text $title pack $graphid.title -fill x frame $graphid.f5 -relief flat -borderwidth 0 canvas $graphid.f5.yaxis -height $maxY -width $ylabelwidth -relief flat -bd -0 -selectborderwidth 0 -borderwidth 0 canvas $graphid.f5.canout -height $maxY -width $maxX -relief flat -bd 0 -selectborderwidth 0 -borderwidth 0 -xscrollcommand "$graphid.hscroll set " pack $graphid.f5.yaxis $graphid.f5.canout -side left -expand 0 label $graphid.xlabel -text $xlabel scrollbar $graphid.hscroll -orient horizontal -command "$graphid.f5.canout xview" pack $graphid.f5 $graphid.xlabel $graphid.hscroll -fill x -side top # Draw the Y axis labels $graphid.f5.yaxis create line $ylabelwidth 0 $ylabelwidth [expr {$hs + $ds + 1}] -width 1 set step [expr {($maxval - $minval) / 10.00}] set strt $minval for { set position 0 } { $position < 11 } { incr position 1 } { set yval [expr {( round ( 1000.0 * $strt)) / 1000.0 }] $graphid.f5.yaxis create line [expr {$ylabelwidth - 5}] [expr {($m * $strt) + $b}] $ylabelwidth [expr {($m * $strt) + $b}] -width 1 $graphid.f5.yaxis create text 25 [expr {($m * $strt) + $b}] -justify right -text $yval -font $tfont set tmp [expr {$strt + $step} ] set strt $tmp } # Create the ledgend set col(0) red set col(1) blue set col(2) green set col(3) yellow set col(4) magenta set col(5) cyan set col(6) white set col(7) grey # clear all the data point variables global d0 d1 d2 d3 d4 d5 d6 d7 set d0 {} set d1 {} set d2 {} set d3 {} set d4 {} set d5 {} set d6 {} set d7 {} # clear all the index variables set indx(0) 0 set indx(1) 0 set indx(2) 0 set indx(3) 0 set indx(4) 0 set indx(5) 0 set indx(6) 0 set indx(7) 0 set nolines 0 # This frame is used to encapsulate the ledgend frame $graphid.led -relief "flat" -bd 0 pack $graphid.led foreach line $args { frame $graphid.led$nolines -relief "flat" -bd 0 label $graphid.led$nolines.l -text " " -background $col($nolines) entry $graphid.led.hid$nolines $graphid.led.hid$nolines delete 0 end $graphid.led.hid$nolines insert end "0" eval "set v$nolines 0" checkbutton $graphid.led$nolines.cb -text [lindex $line 0 ] -onvalue 1 -offvalue 0 -variable v$nolines \ -command "toggleBtn $graphid $nolines" $graphid.led$nolines.cb invoke pack $graphid.led$nolines.l $graphid.led$nolines.cb -side left -anchor w pack $graphid.led$nolines.l -side left -anchor w pack $graphid.led$nolines -expand 0 -anchor w -padx 5 # Value to use to extract data from list set indx($nolines) [lindex $line 1 ] # puts stdout "Line = $line" incr nolines 1 } # Change cursor $graphid config -cursor watch update # Open data file and fill the data point variables #set fid [ open [string trim $logfile ] r ] set min {} set hour {} set day {} set tindx {} set nopts 0 for { set pos 0 } { $pos < [llength $upgrade_buff] } { incr pos 1 } { set raw [split [lindex $upgrade_buff $pos] ":" ] for { set cnt 0 } {$cnt < $nolines} { incr cnt 1 } { eval "lappend d$cnt $indx($cnt)" } # Save the min, hour, day every 15 counts if { [expr {$nopts % 15} ] == 0 } { lappend min [lindex $raw 3 ] lappend hour [lindex $raw 2 ] lappend day [lindex $raw 1 ] lappend tindx $nopts } incr nopts 1 # puts stdout "Min = [lindex $raw 3 ]" } incr nopts -1 # Draw the time scale set y1 [expr {$hs + $ds }] set y2 [expr {$hs + $ds + 5} ] set y3 [expr {$hs + $ds + 15} ] for { set po 0 } { $po < [llength $tindx] } { incr po 4 } { set line [lindex $tindx $po] $graphid.f5.canout create line $line $y1 $line $y2 -width 1 $graphid.f5.canout create text $line $y3 -text "[lindex $day $po]/[lindex $hour $po]:[lindex $min $po]" -font $tfont } $graphid.f5.canout create line 0 [expr {$hs + $ds + 1}] $nopts [expr {$hs + $ds + 1} ] -width 1 # Dismiss button frame $graphid.f10 -bd 2 -relief "ridge" button $graphid.f10.b2 -text "Dismiss" -foreground blue -activeforeground #000080 -command "destroy $graphid" button $graphid.f10.b4 -text "Redraw" -foreground blue -activeforeground #000080 \ -command "redraw $nolines $nopts $graphid $hs $maxY" label $graphid.f10.l1 -text "MinY" -width 4 entry $graphid.f10.e1 -width 6 label $graphid.f10.l2 -text "MaxY" -width 4 entry $graphid.f10.e2 -width 6 pack $graphid.f10.l1 $graphid.f10.e1 $graphid.f10.l2 $graphid.f10.e2 $graphid.f10.b4 $graphid.f10.b2 -side left -fill x pack $graphid.f10 -fill x $graphid.f10.e1 delete 0 end $graphid.f10.e1 insert end $minval $graphid.f10.e2 delete 0 end $graphid.f10.e2 insert end $maxval # Clear graphing area $graphid.f5.canout create rectangle 0 0 $nopts [expr {$hs + $ds} ] -fill black -outline black # Plot the data points for { set cnt 0 } {$cnt < $nolines} { incr cnt 1 } { plotData $graphid $cnt $maxval $minval $hs $maxY } # Change cursor back $graphid config -cursor top_left_arrow } proc redraw { nolines nopts w hs maxY } { global magX global min hour day tindx set maxval [$w.f10.e2 get] set minval [$w.f10.e1 get] set ds [expr {$maxY - $hs - 25.0} ] set ylabelwidth 50 set m [expr { -$ds / ($maxval - $minval)} ] set b [expr { $hs + (($ds * $maxval) / ($maxval - $minval))}] set tfont {-*-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*} # Draw the Y axis labels $w.f5.yaxis create rectangle 0 0 $ylabelwidth $maxY -fill [$w.f5.yaxis cget -background ] -outline [$w.f5.yaxis cget -background ] $w.f5.yaxis create line $ylabelwidth 0 $ylabelwidth [expr {$hs + $ds + 1}] -width 1 set step [expr {($maxval - $minval) / 10.00}] set strt $minval for { set position 0 } { $position < 11 } { incr position 1 } { set yval [expr {( round ( 1000.0 * $strt)) / 1000.0 }] $w.f5.yaxis create line [expr {$ylabelwidth - 5}] [expr {($m * $strt) + $b}] $ylabelwidth [expr {($m * $strt) + $b}] -width 1 $w.f5.yaxis create text 25 [expr {($m * $strt) + $b}] -justify right -text $yval -font $tfont set tmp [expr {$strt + $step} ] set strt $tmp } # Draw the time scale set y1 [expr {$hs + $ds} ] set y2 [expr {$hs + $ds + 5} ] set y3 [expr {$hs + $ds + 15} ] $w.f5.canout create rectangle 0 [expr {$hs + $ds + 1}] [expr {$nopts * 8} ] $maxY -fill [$w.f5.canout cget -background ] -outline [$w.f5.canout cget -background ] if { $magX == 1 } { set poi 4 } elseif { $magX == 2 } { set poi 2 } else { set poi 1 } for { set po 0 } { $po < [llength $tindx] } { incr po $poi } { set time [expr [lindex $tindx $po] * $magX] $w.f5.canout create line $time $y1 $time $y2 -width 1 $w.f5.canout create text $time $y3 -text "[lindex $day $po]/[lindex $hour $po]:[lindex $min $po]" -font $tfont } $w.f5.canout create line 0 [expr {$hs + $ds + 1}] $nopts [expr {$hs + $ds + 1} ] -width 1 $w.f5.canout xview moveto 0.0 $w.f5.canout create rectangle 0 0 [expr {$nopts * 8} ] [expr {$hs + $ds} ] -fill [ $w.f5.canout cget -background ] -outline [ $w.f5.canout cget -background ] $w.f5.canout create rectangle 0 0 [expr {$nopts * $magX} ] [expr {$hs + $ds} ] -fill black -outline black for { set cnt 0 } {$cnt < $nolines} { incr cnt 1 } { set tmp "$w.led.hid$cnt" set tp [$tmp get] # puts stdout "Tp = $tp" if { $tp == {1} } { plotData $w $cnt $maxval $minval $hs $maxY } } } # # toggleBtn - Toggle the button values # USE: toggleBtn window index # proc toggleBtn { w i } { set hid "$w.led.hid$i" if { [$hid get] == {1} } { $hid delete 0 end $hid insert end {0} } else { $hid delete 0 end $hid insert end {1} } } # # plotData - Given a data array, and some necessary variables draw the # data and a ledgend. # w - window # d - data array # indx - Index value of the color # maxval - Maximum value to graph # minval - Minimum value to graph # hs - Head space, amount of space to leave blank at top of graph # maxY - number of data points in Y coordinate of canvas # proc plotData { w indx maxval minval hs maxY } { set ds [expr {$maxY - $hs - 25.0} ] # Define constants for mapping the data range to the display range # Define constants for mapping the data range to the display range set m [expr { -$ds / ($maxval - $minval)} ] set b [expr { $hs + (($ds * $maxval) / ($maxval - $minval))}] set col(0) red set col(1) blue set col(2) green set col(3) yellow set col(4) magenta set col(5) cyan set col(6) white set col(7) black set c $col($indx) plotLine $w $indx $c $m $b } # # plotLine - Draw one of the data sets # USE: plotLine Window Data Colour M B # Values M and B are the slope, and offset # proc plotLine { w indx c m b } { global d0 d1 d2 d3 d4 d5 d6 d7 global magX eval "set v \$d$indx" # puts stdout "V = $v" set nopts [expr [llength $v ] - 1 ] # Plot the data points set ox 0 set oy [expr { ($m * [lindex $v $ox]) + $b }] for { set x 1} { $x < $nopts } { incr x 1 } { set ny [expr {($m * [lindex $v $x ]) + $b}] set mx [expr {$magX * $x }] $w.f5.canout create line $mx $ny $ox $oy -fill $c set oy $ny set ox $mx } } # printGraph - Printout the current canvas # USE: printGraph Window # proc printGraph { w w2 } { set black {1.0 1.0 1.0} $w postscript -file /tmp/can.ps -colormap black $w postscript -file /tmp/can2.ps -colormap black }