Psych 285: Computational Statistics
and Statistical Visualization

Professor Forrest Young

LispStat Programming Examples


Chapter 9 - Statistical Graphics Programming

This chapter deals with statistical graphics programming. We start by setting up a statistical graphics object, to which we send messages to demonstrate statistical graphics programming. These examples follow Luke Tierney's Chapter 9 closely.

Some 4-dimensional data for the plot examples.

(def air 
     (list 80 80 75 62 62 62 62 62 58 58 58 58 58 58 50 50 50 50 50 56 70))
(def temp 
     (list 27 27 25 24 22 23 24 24 23 18 18 17 18 19 18 18 19 19 20 20 20))
(def conc
     (list 89 88 90 87 87 87 93 93 87 80 89 88 82 93 89 86 72 79 80 82 91))
(def loss
     (list 42 37 37 28 18 18 19 20 15 14 14 13 11 12  8  7  8  8  9 15 15))

9.1 The Graph Prototype

9.1.1 Constructing a new graph
(setf w (send graph-proto :new 4))

(send w :num-variables)

(send w :variable-label 0 "Air")
(send w :variable-label '(1 2 3) (list "Temp" "Conc" "Loss"))
9.1.2 Adding Data and Axes
(send w :add-points (list air temp conc loss))

(send w :adjust-to-data)

(send w :point-symbol 0)
(send w :point-color 0)
(send w :point-label 0)

(send w :point-state (iseq (length loss)))

(send w :add-lines (list air temp conc loss))

(send w :linestart-next 7 nil)
(send w :redraw)
(send w :linestart-next 7 8)
(send w :redraw)
(send w :linestart-next 7 nil)
(send w :redraw)

(send w :x-axis t)
(send w :y-axis t)
(send w :y-axis t nil 5)

(send w :range 0)
(send w :range 1 15 30)
(send w :y-axis t nil 4)

(send w :current-variables)
(send w :current-variables 2 3)
9.1.3 Scaling and Transformations
(send w :scale-type)
(send w :scale-type 'variable)

(let* ((c (cos (/ pi 20)))
       (s (sin (/ pi 20)))
       (m (+ (* c (identity-matrix 4))
             (* s '#2A((0  0 -1  0)
                       (0  0  0 -1)
                       (1  0  0  0)
                       (0  1  0  0))))))
  (dotimes (i 10)
           (pause 2)
           (send w :apply-transformation m)))

(dotimes (i 100)
         (pause 1)
         (send w :rotate-2 0 2 (/ pi 20) :draw nil)
         (send w :rotate-2 1 3 (/ pi 20)))
9.1.4 Mouse Events and Mouse Modes
(send w :mouse-modes)

(send w :add-mouse-mode 'show-coordinates
      :title "Show Coordinates"
      :click :do-show-coordinates
      :cursor 'cross)

(defmeth w :do-show-coordinates (x y m1 m2)
  (let* ((xy (cond 
              (m2 (send self :canvas-to-scaled x y))
              (m1 (list x y))
              (t  (send self :canvas-to-real   x y))))
        (s (format nil "~s" xy))
        (mode (send self :draw-mode)))
    (send self :draw-mode 'xor)
    (send self :draw-string s x y)
    (send self :while-button-down #'(lambda (x y) nil))
    (send self :draw-string s x y)
    (send self :draw-mode mode)))

(send w :add-mouse-mode 'identify
      :title "Identify"
      :click :do-identify
      :cursor 'finger)

(defmeth w :do-identify (x y m1 m2)
  (let* ((cr (send self :click-range))
         (p (first (send self :points-in-rect
                         (- x (round (/ (first  cr) 2)))
                         (- y (round (/ (second cr) 2)))
                         (first  cr)
                         (second cr)))))
    (if p
        (let ((mode (send self :draw-mode))
              (label (send self :point-label p)))
          (send self :draw-mode 'xor)
          (send self :draw-string label (+ x 5) y)
          (send self :while-button-down #'(lambda (x y) nil))
          (send self :draw-string label (+ x 5) y)
          (send self :draw-mode mode)))))

(send w :add-mouse-mode 'point-moving
      :title "Point Moving"
      :cursor 'hand
      :click :do-point-moving)

(defmeth w :do-point-moving (x y m1 m2)
  (let ((p (send self :drag-point x y)))
    (if p (format t "Point ~d has been moved.~%" p))))
9.1.6 Window Layout, Resizing and Redrawing
(send w :x-axis t t 4)
(send w :y-axis t t 5)
(send w :current-variables 0 1)

(send w :content-rect)
(apply #'send w :frame-rect (send w :content-rect))
(send w :redraw)

(send w :margin)
(send w :margin 10 10 10 10)
9.1.7 Plot Overlays
(let ((h (+ (send w :text-ascent) (send w :text-descent))))
  (send w :margin 0 (round (* 1.5 h)) 0 0))

(setf interp-overlay (send graph-overlay-proto :new))

(let* ((ascent (send w :text-ascent))
       (x ascent)
       (y (round (* 1.5 ascent)))
       (box ascent))
  (send interp-overlay :add-slot 'location
        (list x y box (round (+ x (* 1.5 box))))))

(defmeth interp-overlay :location ()
  (slot-value 'location))

(defmeth interp-overlay :redraw ()
  (let* ((loc (send self :location))
         (x (first loc))
         (y (second loc))
         (box (third loc))
         (string-x (fourth loc))
         (graph (send self :graph)))
    (send graph :frame-rect x (- y box) box box)
    (send graph :draw-string "Interpolate" string-x y)))

(send w :add-overlay interp-overlay)

(defmeth interp-overlay :do-click (x y m1 m2)
  (let* ((loc (send self :location))
         (box (third loc))
         (left (first loc))
         (top (- (second loc) box))
         (right (+ left box))
         (bottom (+ top box))
         (graph (send self :graph)))
    (when (and (< left x right) (< top y bottom))
          (send graph :interpolate)
          t)))

(defmeth w :interpolate ()
  (send self :transformation nil)
  (dotimes (i 40)
           (pause 2)
           (send self :rotate-2 0 2 (/ pi 20) :draw nil)
           (send self :rotate-2 1 3 (/ pi 20) )))
9.2.4 Histograms (with normal density)
(setf hs (histogram (list air temp conc loss)))

(send hs :num-variables)

(send w :variable-label '(0 1 2 3) (list "Air" "Temp" "Conc" "Loss"))

(send hs :content-variables)
(send hs :current-variables)

(send hs :content-variables 1 4)
(send hs :current-variables 2 4)
(send hs :current-variables 1 2)
(send hs :current-variables 3 4)

(send hs :current-variables 0 4)

(send hs :scale-type 'variable)

(dotimes (i 10)
         (send hs :rotate-2 0 1 (/ pi 20)))

(setf hp (histogram air))

(let* ((mu (mean air))
       (s (standard-deviation air))
       (x (rseq (min air) (max air) 30))
       (y (/ (normal-dens (/ (- x mu) s)) s)))
  (send hp :add-lines (list x y)))