##  scatterplot.

proc import {w} {

   global filechoice number_columns format_read data_names
   global rawData cwidth cheight bigFont reallyBigFont plotFont
 
   #  Data import section.  gets data from an ASCII file arranged in columns,
   # like a spreadsheet.
 
 # WEBVERSION: data is embedded in the code...

 set header {case class prob grid prec year month day hour lat long}
 set number_columns [llength $header]

 set format_read " "
 set data_names " "
 for {set k 0} {$k < $number_columns} {incr k} {
  lappend format_read  %f
  lappend data_names [lindex $header $k]
 }
 set rawData(case)  {1 47 93 2 48 94 3 49 95 4 50 96 5 51 97 6 52 98 7 53 99 8 54 100}
 set rawData(class) {17 1 1 2 2 1 2 14 1 17 14 1 2 14 1 14 2 1 2 19 1 2 1 1}
 set rawData(prob) {0.54 0.99 0.99 0.49 0.93 0.93 0.99 0.94 0.99 0.5 0.96 0.99 0.94 0.96 0.99 0.94 0.99 0.74 0.99 0.93 0.66 0.98 0.51 0.99}
 set rawData(grid) {1 7 13 2 8 14 3 9 15 4 10 16 5 11 17 6 12 18 7 13 19 8 14 20}
 set rawData(prec) {2.4 0 0 3.4 0.5 0 0.4 0.1 0 2.2 0.1 0 1.6 0.1 0 0 2.8 0 1.3 0 0 2.4 0 0}
 set rawData(day) {1 3 5 1 3 5 1 3 5 1 3 5 1 3 5 1 3 5 1 3 5 1 3 5}
 set rawData(month) {11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11}
 set rawData(hour) {12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12}
 set rawData(year) {87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87}
 set rawData(lat) {22 24 28 22 24 28 22 26 28 22 26 28 24 26 30 24 26 30 24 28 30 24 28 30}
 set rawData(long) {-102.5 -97.5 -102.5 -100 -95 -100 -97.5 -102.5 -97.5 -95 -100 -95 -102.5 -97.5 -102.5 -100 -95 -100 -97.5 -102.5 -97.5 -95 -100 -95}
 
 main $w

}
 
 

proc main {w} {

   global filechoice number_columns format_read data_names
   global rawData cwidth cheight bigFont reallyBigFont plotFont recs

  # gets the max and min for each list.

  foreach item $data_names  {
      set l [llength $rawData($item)]
      set min(rawData$item) [lindex [lsort -real $rawData($item)] 0]
      set max(rawData$item) [lindex [lsort -real $rawData($item)] [expr ($l-1)]]
      set range(rawData$item) [expr {$max(rawData$item) - $min(rawData$item)}]
      if {$range(rawData$item) == 0} {set range(rawData$item) 1}
  }

  set c .c
 
  # sets the dimensions of each plot:
  set sub_width [expr {$cwidth/$number_columns}]
  set sub_height [expr {$cheight/$number_columns}]

  # nothing is brushed yet.
  set recs " "

  set i 0
  set j 0
  foreach theme1 $data_names {
 
   foreach theme2 $data_names {
      if {$j != $i} {
  # boxes.
   $c create rectangle \
  [expr (($i*$sub_width)+20)] [expr (($j*$sub_height)+20)] \
  [expr ((($i+1)*$sub_width)-20)] \
  [expr ((($j+1)*$sub_height)-20)] -width 1
  # x labels.
   $c create text [expr (($i*$sub_width)+(int($sub_height/2)))] \
  [expr ((($j+1)*$sub_height)-10)] \
  -text $theme2 -font $plotFont
  # x ticklabels.
   $c create text [expr (($i*$sub_width)+($sub_width-20))] \
  [expr ((($j+1)*$sub_height)-10)] \
  -text $max(rawData$theme2) -font $plotFont
   $c create text [expr (($i*$sub_width)+20)] \
  [expr ((($j+1)*$sub_height)-10)] \
  -text $min(rawData$theme2) -font $plotFont
  # ticks
   for {set k 0} {$k <= 5} {incr k} {
  set y [expr {$k*($sub_height-40)/5+20}]
  $c create line [expr (($i*$sub_width)+15)] \
   [expr (($j*$sub_height)+$y)] \
   [expr (($i*$sub_width)+20)] \
   [expr (($j*$sub_height)+$y)] -width 1
  set x $y
  $c create line [expr (($i*$sub_width)+$x)] \
   [expr ((($j+1)*$sub_height)-15)] \
   [expr (($i*$sub_width)+$x)] \
   [expr ((($j+1)*$sub_height)-20)]
   }
   $c create text [expr (($i*$sub_width)+20)] \
   [expr (($j*$sub_height)+10)] \
   -text $theme1 -font $plotFont
  #y ticklabels
   $c create text [expr ($i*$sub_width+4)] \
   [expr (($j*$sub_height)+20)] \
   -text $max(rawData$theme1) -font $plotFont
   $c create text [expr ($i*$sub_width+4)] \
   [expr (($j*$sub_height)+($sub_height-20))] \
  -text $min(rawData$theme1) -font $plotFont
   incr j
      } else {
   $c create text [expr (($i+1)*$sub_width)-($sub_width/2)] \
   [expr (($j+1)*$sub_width)-($sub_width/2)] \
   -text $theme2 -font $reallyBigFont
   incr j
      }
    }
      set j 0
      incr i
  }

  # plot the points!

  # plot (i, j) is the ith plot from the left, jth plot from the top.

  # the following loops plot the points in each of the 16 plots; the kth
  # point in each plot stands for record number k in the data set; e.g the
  # third row of the data file is plotted when k=2 (since k starts at 0).
  # There are three nested loops; the innermost plots k points on each plot,
  # the middle loop moves from plot (i, j) to (i, j+1), the outermost loop
  # moves to the next column of plots.

  # k is the vital piece of information... this is what will allow brushing
  # and linking to other ploats and to DX 3d plots.

  set i 0
  set j 0
  foreach theme1 $data_names {
 foreach theme2 $data_names {
    if {$i != $j} {
  for {set k 0} {$k < [llength $rawData($theme2)]} {incr k} {
     # x1 and y1 scale the data values to some number between
     # 0 and $boxsize.  E.g. is the data for one variable
     # ranges from
     # (4.5, 8.0), then the point representing 4.5 is scaled to
     # 0 and that representing 8.0 os assigned $boxsize.
     #  The boxes are $boxsize x $boxsize.
     set boxsize [expr {$sub_height - 40}]
     set x1 \
   [expr {int($boxsize*([lindex $rawData($theme2)\
    $k]-$min(rawData$theme2))/$range(rawData$theme2))}]
     set y1 \
   [expr {int($boxsize*([lindex $rawData($theme1)\
    $k]-$min(rawData$theme1))/$range(rawData$theme1))}]
     set x [expr {20 + $x1 + ($i*$sub_width)}]
     set y [expr {(($j+1)*$sub_height) - (20 + $y1)}]
     set item [$c create line  [expr $x-1] $y \
      [expr $x+1] $y -width 2 -fill red]
     $c addtag point$k withtag $item
     $c addtag point withtag $item
     $c addtag $k withtag $item
         }
    }
 incr j
 }
  set j 0
  incr i
  }

  $c bind point <Any-Enter> "ItemEnter $c"
  $c bind point <Any-Leave> "ItemLeave $c"
  bind $c <1> "ItemMark $c %x %y"
  bind $c <B1-Motion> "ItemStroke $c %x %y"
  bind $c <ButtonRelease-1> "ItemBrush $c"
}

proc ItemEnter {w} {
 $w itemconfig current -fill yellow
 set selected [$w gettags current]
 set rec [lindex $selected 0]
 $w itemconfig $rec -fill yellow
}

proc ItemLeave {w} {
 set selected [$w gettags current]
 set rec [lindex $selected 0]
 if {[lsearch [$w gettags current] area] != 1} {
  $w itemconfig $rec -fill red
 }
 
}
proc ItemMark {c x y} {
    global areaX1 areaY1 recs

    set areaX1 [$c canvasx $x]
    set areaY1 [$c canvasy $y]
    $c delete area
    for {set j 0} {$j < [llength $recs]} {incr j} {
 $c itemconfig [lindex $recs $j] -fill red
    }

}

proc ItemStroke {c x y} {
    global areaX1 areaY1 areaX2 areaY2
    set x [$c canvasx $x]
    set y [$c canvasy $y]
    if {($areaX1 != $x) && ($areaY1 != $y)} {
 $c delete area
 $c addtag area withtag [$c create rect $areaX1 $areaY1 $x $y \
  -outline black]
 set areaX2 $x
 set areaY2 $y
    }
}
proc ItemBrush {c} {
    global areaX1 areaY1 areaX2 areaY2 recs
    set area [$c find withtag area]
    set recs ""
    foreach i [$c find enclosed $areaX1 $areaY1 $areaX2 $areaY2] {
 
 if {[lsearch [$c gettags $i] point] == 1} {
   lappend items $i
   lappend recs [lindex [$c gettags $i] 0]
 }
    }
    for {set j 0} {$j < [llength $recs]} {incr j} {
 $c itemconfig [lindex $recs $j] -fill yellow
    }

}

# brings up window.

set m .m
set c .c

set plotFont -*-Helvetica-Medium-R-Normal--*-100-*-*-*-*-*-*
set bigFont -*-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*
set reallyBigFont -*-Helvetica-Medium-R-Normal--*-200-*-*-*-*-*-*

# entry $w.entry -textvariable filechoice -relief sunken
# bind $w.entry <Return> "import $w"

# ******
# these are variable.

set cwidth 1200
set cheight 1200
# ******

label .msg -font $bigFont -wraplength 300 -justify left \
 -text "In the canvas window below, there is (or will be) \
  an array of scatterplots of the variables in the data \
  file specified below.  You may select any point on the \
  array by touching it and the corresponding points in the \
  other polts will be highlighted.  In addition, you may \
  drag a box (using the left mousebutton) and 'brush' \
  corresponding points in other displays."
pack .msg -side top

set filechoice testclass.txt

frame .buttons
pack .buttons -side bottom -fill x -pady 2m

scrollbar .hscroll -orient horiz -command "$c xview"
pack .hscroll -side bottom -fill x
scrollbar .vscroll -command "$c yview"
pack .vscroll -side right -fill y

canvas $c -relief sunken -borderwidth 2 -height 1200 -width 1200 \
 -scrollregion {-10 -10 1200 1200} \
 -xscrollcommand ".hscroll set" \
 -yscrollcommand ".vscroll set"
pack $c -expand yes -fill both

import .