A little graph plotter

Summary

ulis, 2003-03-12:

A little script to plot a graph on a canvas. Non-stop scrolling capable. Can be used for real-time plotting.

http://perso.wanadoo.fr/maurice.ulis/tcl/plot.gif

See Also

A Graph plotter
a different approach.
Histogram Plotter
Fun with functions
Plotting data

Code

#! /bin/env tclsh

package require Tk

proc sleep {time} {
   after $time set end 1
   vwait end
}
# --------------------------
#   params
# --------------------------
# title
# canvas width & height
# delay between plots
# x = f(t)
# plot expression
# initial & final times
# accuracy
array set params {
    title     {sin(x)}
    width     400
    height    240
    delay     50
    x         {$t / 50.}
    plot      {sin($x)}
    t0        0
    #         {t1 < t0: non-stop scrolling}
    t1        -1
    accuracy  1.e-2
}

# --------------------------
#   plotting
# --------------------------
# computed heights
set h $params(height)
set h1 [expr {int($h * 0.5)}]  ;# canvas mid-height
set h2 [expr {$h1 + 1}]
set h3 [expr {int($h * 0.4)}]  ;# graph mid-height
# canvas & bindings
canvas .c -width $params(width) -height $h -xscrollincrement 1 -bg beige
bind . <Destroy> { exit }
# plotting
wm title . $params(title)
pack .c
.c xview scroll $params(t0) unit
set t $params(t0)

while TRUE {
        if {$t != $params(t1)} {
                set x [expr $params(x)]
                set vv [expr $params(plot)]
                set v [expr {int($vv * $h3) + $h1}]
                if {abs($vv) < $params(accuracy)} \
                { 
                                #puts "$vv [expr {$params(accuracy)}]" ;#because I wanted to understand the points
                                .c create text $t 0 -anchor n -text [expr { $t / 50. }] -fill gray
                                .c create line $t 0 $t $h -fill gray
                }
                .c create line $t $h1 $t $h2 -fill gray
                .c create rectangle $t $v $t $v
                incr t
                if {$t > $params(width)} { .c xview scroll 1 unit }
        }
        sleep $params(delay)
}


Another set of parameters

http://perso.wanadoo.fr/maurice.ulis/tcl/plot2.gif

array set params \
{
    title     {x^3 - x}
    width     400
    height    240
    delay     50
    x         {$t / 100.0}
    plot      {pow($x,3) - $x}
    t0        -200
    t1        200
    accuracy  1.e-6
}

marcDouglas, 2018-11-2:

Loved this, wanted to having something scrolling. Found it a bit confusing, think I cleaned it up. The problem was the UI freezes if you use

after 50

to get the pause in the loop. The sleep command accomplishes this and cleans the code up. However you did teach me how you could use the after command (have it execute a script after delay and is non-blocking), I just don't think this is the place for it.

Also edited the text to accurately reflect value of (x).

arjen (2018-11-3) (Moved the addition to the end of the page) The proper way to achieve this is by:

after 50 {
    ... some script ...
    set ::waiting 1  ;# Should be a global/namespace variable
}

vwait waiting 

See the page on the every script for more information and a convenient way of using the technique.