---- #!/bin/sh # Restart with tcl: -*- mode: tcl; tab-width: 4; -*- \ exec wish $0 ${1+"$@"} # demo5-EEG.tcl - HaJo Gurt - 2005-12-20 - http://wiki.tcl.tk/15146 #: Demo - Toy-EEG: draw dots on head, colored according to data-values #########1#########2#########3#########4#########5#########6#########7##### package require Tk proc ReadFile {fn} { #: Read + parse datafile # Format of data (no tabs!) : # "0001 a b d t 0 0 x y a a b b d d t t" global Data P0 #puts "fn: $fn" ;## set i 0 set Comment 0 set nData 0 # Read file one line at a time: set fp [open $fn r] fconfigure $fp -buffering line gets $fp Line while {$Line != ""} { incr i 1 #puts "$i: $Line" ;## set Line [string trim $Line] switch -- [string index $Line 0] { # {incr Comment 1} default { incr nData 1 set w 0 set D {} foreach Word [split $Line " "] { if { $Word != ""} { if { $w == 0} { set Key $Word } else { #puts "$w '$Word'" ;## set Val grey catch { set Val $::ColorTab($Word) } lappend D $Val } incr w 1 } } set Data($nData) $D #puts "#> $Key: '$D'" ;## } } ;#switch gets $fp Line } ;#while close $fp puts "#EOF: $nData = [array size Data]" ;## return [array size Data] } # # Routines to draw heads and set up their dot-arrangement: # proc ReadPic {w fn} { #: Read imagefile, put image on canvas global im1 set midX [expr { $::maxX / 2 }] set midY [expr { $::maxY / 2 }] catch {image delete $im1} set im1 [image create photo -file $fn] $w create image $midX $midY -image $im1 -tags "all img" } proc DrawDots {w} { #: Same arrangement of dots as for head2 set i 0 foreach {x1 y1} { 50 70 80 70 110 70 140 70 50 100 80 100 110 100 140 100 50 130 80 130 110 130 140 130 50 160 80 160 110 160 140 160 } { incr i 1 set x2 [expr { $x1 + 15 }] set y2 [expr { $y1 + 15 }] $w create oval $x1 $y1 $x2 $y2 -fill white -tags "all Dot$i" } } proc DrawHead1 {w} { #: Draw a round head, as viewed from above set x1 20 set y1 40 ;# 120-80=40 set x2 [expr { $x1 + 160 }] set y2 [expr { $y1 + 160 }] $w create oval $x1 $y1 $x2 $y2 -tags "all Head1" # Nose up: $w create line [expr { $x1 + 69 }] [expr { $y1 + 1 }] \ [expr { $x1 + 80 }] [expr { $y1 - 10 }] -tags "all Head1" $w create line [expr { $x1 + 80 }] [expr { $y1 - 10 }] \ [expr { $x1 + 91 }] [expr { $y1 + 1 }] -tags "all Head1" # Ears: $w create rect [expr { $x1 - 2 }] [expr { $y1 + 70 }] \ [expr { $x1 + 2 }] [expr { $y1 + 90 }] -tags "all Head1" $w create rect [expr { $x1 +158 }] [expr { $y1 + 70 }] \ [expr { $x1 +162 }] [expr { $y1 + 90 }] -tags "all Head1" # Only some dots on this head: foreach {nr x1 y1} { Dot5 50 70 Dot6 80 70 Dot7 110 70 Dot8 140 70 } { set x2 [expr { $x1 + 15 }] set y2 [expr { $y1 + 15 }] $w create oval $x1 $y1 $x2 $y2 -fill white -tags "all $nr" } } proc DrawHead2 {w} { #: Draw oval head, side view set x1 20 set y1 20 ;# 120-100=20 set x2 [expr { $x1 + 160 }] set y2 [expr { $y1 + 200 }] $w create oval $x1 $y1 $x2 $y2 -tags "all Head2" # Nose on left: $w create line [expr { $x1 + 4 }] [expr { $y1 + 70 }] \ [expr { $x1 - 10 }] [expr { $y1 +120 }] -tags "all Head2" $w create line [expr { $x1 - 10 }] [expr { $y1 +120 }] \ [expr { $x1 + 4 }] [expr { $y1 +121 }] -tags "all Head2" # Create a grid of dots: set i 0 foreach {x1 y1} { 50 70 80 70 110 70 140 70 50 100 80 100 110 100 140 100 50 130 80 130 110 130 140 130 50 160 80 160 110 160 140 160 } { incr i 1 set x2 [expr { $x1 + 15 }] set y2 [expr { $y1 + 15 }] $w create oval $x1 $y1 $x2 $y2 -fill white -tags "all Dot$i" } } proc DrawHead3 {w} { #: Draw oval head, side view #set x1 380 set x1 20 set y1 20 ;# 120-100=20 set x2 [expr { $x1 + 160 }] set y2 [expr { $y1 + 200 }] $w create oval $x1 $y1 $x2 $y2 -tags "all Head3" # Nose on right: $w create line [expr { $x1 +156 }] [expr { $y1 + 70 }] \ [expr { $x1 +170 }] [expr { $y1 +120 }] -tags "all Head3" $w create line [expr { $x1 +170 }] [expr { $y1 +120 }] \ [expr { $x1 +156 }] [expr { $y1 +121 }] -tags "all Head3" # Grid of dots: set i 0 foreach {x1 y1} {140 70 110 70 80 70 50 70 140 100 110 100 80 100 50 100 140 130 110 130 80 130 50 130 140 160 110 160 80 160 50 160 } { incr i 1 set x2 [expr { $x1 + 15 }] set y2 [expr { $y1 + 15 }] $w create oval $x1 $y1 $x2 $y2 -fill white -tags "all Dot$i" } } # # Routines to change the color of dots: # proc ClrCanvas {} { #: Clear all canvas foreach {w} {.cA .cB .cC .cD} { $w delete "all" } } proc ColorAllDots {c} { #: Set all dots to the same color c for { set i 1 } { $i <= 16 } { incr i 1 } { foreach {w} {.cA .cB .cC .cD} { $w itemconfig Dot$i -fill $c } } } proc ColorDots {Colors} { #: Set all dots to the colors in array Colors ColorAllDots white set i 0 foreach c $Colors { incr i 1 foreach {w} {.cA .cB .cC .cD} { $w itemconfig Dot$i -fill $c } } } proc NextSample {inc} { #: Show next sample from data-array, with range-check global Data P0 set P $P0 if {[catch {incr P $inc}]} { bell; return } set x [array get Data $P] #puts "x: $x" ;## if {$x ==""} { bell return 1 ;# Error } else { ;# ok: set P0 $P ColorDots $Data($P0) return 0 } } # Repeating timer: proc every {ms body} {eval $body; after $ms [info level 0]} proc StartAnimation {} { #: Show data from data-array as animation every 100 { NextSample +1 } # ?? automatic stop at end of data ?? } proc StopAnimation {} { #: Reset all 'every' timers foreach id [after info] {after cancel $id} } #########1#########2#########3#########4#########5#########6#########7##### proc Init {} { #: Init. values, Build GUI global maxX maxY Data P0 ColorTab Color P1 P2 set maxX 200 set maxY 240 array set ColorTab { a red b yellow d green t blue 0 white x grey } set Color blue set Data(0) {} set P0 NoData set P1 {red yellow blue green grey pink yellow cyan green2 grey25 red2 yellow blue green4 grey50 orange} set P2 {OrangeRed2 red tomato pink salmon orange goldenrod bisque yellow cyan SteelBlue1 blue green green4 magenta grey white black} frame .f1 frame .f2 frame .f3 frame .f4 pack .f1 .f2 .f3 .f4 #canvas .cA -width $maxX -height $maxY -bg white foreach {w} {.cA .cB .cC .cD} { canvas $w -width $maxX -height $maxY -bg white } pack .cA .cB -in .f1 -side left pack .cC .cD -in .f2 -side left button .b1 -text "Clear" -command { ClrCanvas } button .b2 -text "Image" -command { ReadPic .cA "stampr1.gif" } button .b3 -text "Dots" -command { DrawDots .cA } button .b4 -text "Heads" -command { DrawHead1 .cB; DrawHead2 .cC; DrawHead3 .cD } label .- #button .b5 -text "Dot1" -command { .cA itemconfig Dot1 -fill $Color } button .b5 -text "AllDots" -command { ColorAllDots $Color} button .b6 -text "Pattern1" -command { ColorDots $P1} button .b7 -text "Pattern2" -command { ColorDots $P2} label .nr -textvar P0 button .bF -text "Read File" -command { set P0 [ReadFile "eeg1.txt"] } button .b0 -text "Reset" -command { set P0 0; NextSample 0 } button .b- -text " - " -command { NextSample -1 } button .b+ -text " + " -command { NextSample +1 } button .bA -text "Play" -command { StartAnimation } button .bS -text "Stop" -command { StopAnimation } pack .b1 .b2 .b3 .b4 .- .b5 .b6 .b7 -in .f3 -side left -padx 2 pack .bF .b0 .b- .nr .b+ .bA .bS -in .f4 -side left -padx 2 } # #: Main : # Init ReadPic .cA "stampr1.gif" DrawDots .cA DrawHead1 .cB ;# Nose up DrawHead2 .cC ;# Nose left DrawHead3 .cD ;# Nose right ### Debug: proc int x { expr int($x) } bind .cD {wm title . [int [%W canvasx %x]],[int [%W canvasy %y]]} bind .cA {wm title . [.cA itemcget current -tag ] } #catch {console show} #set c a; puts "$c : $ColorTab($c)" #. ---- [Category Toys]